Crusader_Decomp/crusader_decompilation_notes.md

58 KiB

Crusader: No Remorse — Decompilation Notes

This file is an index. Detailed notes have been split into the docs/ folder by topic.

Active live analysis target is now CRUSADER.EXE. Existing CRUSADER-RAW.EXE notes remain in scope as cross-reference evidence and should be cited alongside live NE addresses when they support a rename, variable role, or behavior claim.

Recent verified PSX map-viewer batch: docs/psx/psx.md, docs/psx/map-rendering.md, docs/psx/map-viewer-plan.md, and the new docs/psx/art-binding-recovery.md now record both the latest executable-backed renderer findings and the first measured recovery pass against placeholder-heavy PSX scenes. Current best read is that the cache builder still exports executable-named section-0 visible families (section0_dispatch_roots, section0_constructor_placements), runtime/state layers for DAT_800758d8, DAT_800758d0, DAT_800758cc, DAT_800758d4, and one offline FUN_8003b00c decode candidate for DAT_8006b5d8 -> DAT_8006769c, but it now also treats large zero-block DAT_800758d8 constructor-placement bands as inherited-art candidates before falling back to placeholders. That donor-based recovery path moved the built cache from 58,262 fallback items / 1,714 bundle-mapped items down to 25,038 fallback items / 34,938 bundle-mapped items, making maps such as 0, 9, and 43 mostly real-art while leaving map 104 as the clearest remaining outlier. The newest pass does not change the earlier DAT_800758d4 conclusion: psx_object_advance_state_script still sign-extends those three bytes into obj+0x30/+0x34/+0x38 for overlap/contact-style consumers rather than the draw path, and the unresolved blocker still sits later in the live state-to-resource/frame bridge for the remaining constructor-placement families.

Recent verified combat-data batch: docs/combat-dat.md now documents the shipped COMBAT.DAT archive end to end. Current best read is that all local Remorse/Regret variants ship the same 14-record combat-tactic archive, each record contains a 16-byte name plus four block offsets and bytecode, and the tactic VM is now grounded both in the live CRUSADER.EXE helpers (Attack_SetupForTacticNo, Attack_SetupForBlockNo, NPC_Get/SetNPCTacticNo) and in ScummVM's readable Crusader attack-process implementation. The new note also promotes the per-tactic human-readable catalog, including the midpoint-pressure, marker-shuttle, step-out-shoot, and stationary-chaos families.

Recent verified NE movement/collision batch: docs/raw-0008-000c.md now extends the live AreaSearch_CollideMove lane one helper layer deeper. Current best read is that the collision-storage queue is no longer only anchored at StorageDataProcess_Create / Run and the legal-move wrappers: the live database now also carries the step-aware seg029 sweep helpers AreaSearch_SweepShapeBetweenPoints, AreaSearch_SweepItemToPointWithStepUp, and AreaSearch_SweepShapeBetweenPointsWithStepUp, the seg031 release-side queue cleanup pair StorageDataProcess_Release and storage_process_ref_list_terminate_item_matches, and adjacent seg090 helper ItemCache_PushAndPopToDirectionalOffset. The practical remaining gap in this lane is now earlier caller policy rather than local helper identity.

Recent map-renderer egg-link follow-up: docs/map_renderer/egg-identification.md now closes the old No Regret map-3 destination-egg 102 gap. Current best read is that Regret uses a second elevator family at shape:400 (0x0190) in addition to the earlier Remorse-focused shape:542 rule: recovered Regret ELEVATOR::gotHit accepts QLo >= 100, treats QLo < 0x00c8 as the generic same-map lane, and map 3 contains a concrete source object item:664:fixed:400:0:44030:9662:0 with quality 614 (QLo 102) that resolves the previously unexplained destination egg 102.

Recent map-renderer editor-object follow-up: docs/map_renderer/trigger-usecode-links.md and docs/map_renderer/editor-object-survey.md now promote a Regret-only controller cluster that had still been sitting in the unresolved editor bucket. Current best read is that 0x04c6 / 0x04de are WATCHNS / WATCHEW secret-door watcher controllers, 0x0510 is their nearby SECRET_DOOR_POST target keyed by shared QLo, 0x05e1 is CRYOBOX, and 0x05df / 0x05e0 are the paired pressure-barrier faces it drives by shared QLo. The same batch also closes 0x0451 / 0x05ae as CRAZYEW / CRAZYNS hit-driven NPC wake-up relays and 0x056d as VIDEOBOX, then promotes cautious local viewer arrows for WATCH* -> 0x0510 and CRYOBOX -> 0x05DF/0x05E0 in the map renderer.

Recent map-renderer control-pad follow-up: docs/map_renderer/egg-identification.md, docs/map_renderer/trigger-usecode-links.md, and docs/map_renderer/editor-object-survey.md now tighten the 0x0318 / 0x0366 read using the decompressed .cache scenes rather than the packed site export. Current best read is that 0x0318 is CRUMORPH, not a generic placeholder cube: both extracted usecode corpora expose class 0x0318 as CRUMORPH, and the recovered equip body is a control-transfer pad that scans nearby NPCs for a local-QLo actor-key match before bracketing TRIGGER.slot_20. The strongest current viewer promotion is still grounded in Regret scene evidence, where authored same-QLo local CRUMORPH -> 0x04B1 matches are strong enough to expose, while 0x0366 remains NPC_ONLY, a hit-driven NPC-only trigger pad keyed by an internal actor field.

Recent map-renderer controller follow-up: docs/map_renderer/trigger-usecode-links.md and docs/map_renderer/editor-object-survey.md now tighten three more shared controller shapes. Current best read is that 0x00A2 is PANELEW, the east-west panel-switch counterpart to PANELNS; 0x03C1 is GENERATR, a destroyable generator/controller whose gotHit body immediately forwards into TRIGGER.slot_20 lane 0; and 0x04E7 is the same DEATHBOX class in both Remorse and Regret rather than a Remorse-only crosswalk. The map viewer now has enough evidence to label those shapes directly, open PANELEW::use / GENERATR::gotHit, and expose cautious same-QLo cmd-link arrows for PANELEW and GENERATR.

Recent actor-key follow-up: the same map-renderer notes now make the current blocker explicit instead of leaving it as an implied missing export. Current best read is that the hidden actor-side value behind CRUMORPH / NPC_ONLY is mutable actor field 0x63, not a stable DTABLE row: sampled Regret DTABLE rows still read as zero at record byte 0x63, while recovered TRIGGER.slot_29 / slot_2B lanes can rewrite actor field 0x63 on nearby matched NPCs after load. The same pass also widens the sibling-family set that uses this mechanism: WATCHNS / WATCHEW, THRMBCKN / THRMBCKE, and SURCAMNS / SURCAMEW all compare controller-local bytes against actor field 0x63 in recovered lanes, so the viewer now documents a broader actor-key controller family while still withholding speculative actor-target arrows.

Recent verified PSX pre-alpha batch: docs/psx/prealpha.md now records a focused Ghidra pass on /psx/prealpha/SLUS_002.68 plus a disc-tree comparison against the released PlayStation Crusader: No Remorse build. Current best read is that this pre-pre alpha still looks much more like a trimmed early No Remorse PSX branch than a clearly rebranded Crusader 2 executable: it still carries direct Crusader: No Remorse save/quit text, the renamed wdl_resource_bundle_load_by_index still embeds the full retail \LSET1\L through \LSET7\L prefix table and the same 10/20/30/40/50/60 threshold ladder, and the mission/passcode UI scaffolding is still present with the same visible 15 mission briefing strings and consonant/digit passcode alphabet. The main concrete differences in this batch are the heavily reduced shipped content (3 level bundles, 1 XA, no .STR movies) and the surviving architectural leftovers that no longer match the current disc literally, especially the missing-file \AUDIO\TALK1.XA;1 path and the LoadExec helper for MENU.EXE / ENGINE.EXE / PSX.EXE.

Recent verified PSX executable batch: docs/psx/psx.md now records a focused Ghidra pass on SLUS_002.68 for mission/map inventory, passcode handling, and catalog text. Current best read is that the PSX loader hardcodes seven \LSETn\L folder prefixes and the extracted disc ships 62 level bundles (L0..L58, L62..L64) with a real gap at L59..L61, while the executable still exposes only 15 plain-text Mission Briefing ^Mission N strings. The same pass closes the visible passcode-generation side too: mission-complete flow synthesizes 4-character passcodes from the alphabet BCDFGHJKLMNPQRSTVWXZ0123456789, and the executable preserves direct ammo/item/weapon name tables. The hidden password-screen cheat codes remain less direct: public PSX references point to XXXX and L0SR/L0SER, but those values are not stored as plain ASCII in SLUS_002.68, so the compare path still looks numeric or transformed rather than table-driven.

Recent verified Japanese-build batch: docs/jp-remorse-windows9x-investigation.md now records a focused live-Ghidra investigation of /ja/CRUSADER.EXE around the claim that the Japanese release runs natively on Windows 95 / Windows 9x instead of requiring a DOS boot path. Current best static-analysis read is strongly in favor: the JP executable is a flat Win32 image with PE-style sections, a Windows import table, native window creation, DirectDraw/DirectSound initialization, registry-backed config under Software\Electronic Arts\Crusader: No Remorse\J1.21, and a meaningful GetVersion-based Win9x compatibility branch that changes TLS allocation behavior when the classic Win9x high bit is set. The only remaining uncertainty is practical deployment rather than architecture: this pass did not runtime-test on real Win95 or prove which DirectX/runtime prerequisites are required.

Recent verified Japanese-build follow-up: docs/jp-remorse-cheats-and-launch-params.md now records a focused pass on the surviving cheat/debug and startup-argument lanes in /ja/CRUSADER.EXE. Current best read is that the JP Win32 build kept real executable cheat/debug machinery, not just leftover strings: -laurie is still a special parser case, the hidden JASSICA16 sequence matcher still toggles the cheat-active state with live Cheats are now active/inactive. messages, the option-key handler still contains the immortality toggle path, and the command-line parser still executes live handlers for -debug, -u <arg>, -warp <mission>, -skill <n>, -mapoff <delta>, -egg <id>, and -demo. The same pass also narrows one important difference from older DOS-side notes: the JP Win32 parser has not yet been proven to support positional -warp <mission> <x> <y> <z> consumption, so that form should not currently be assumed for this build.

Recent verified localized-build batch: docs/spanish-cheat-differences.md now records a tighter live-Ghidra comparison against /es/CRUSADER.EXE for the known cheat/debug control areas. Current best read is now narrower than the earlier "moved matcher" theory: the Spanish executable still preserves the same broad cheat/debug framework as the English build with relocated addresses rather than different behavior, but it does not preserve the English jassica16 table as the same static data object and this pass also failed to recover any replacement compiled matcher or any translated ~ cheat-latch toggle. The -laurie parser still sets the broad cheat/debug gate (1478:0910), the gameplay-input gate still exists at 1478:0927, and Hack Mover still toggles through 13e8:24a5; but the old English-side slot at 1478:2833 now contains pointer-like words, the old English immortality-string slots at 1478:2850/2866 are also repurposed as non-string data in Spanish, 1478:0910 has only the -laurie write at 1050:0985, 1478:5fb3 only has the Laurie-hint helper writes at 13e8:0071/0077, World_HandleKeyboardInput does not expose a recovered 0x7e / tilde branch, and 1478:8ad6 still has no recovered writer even though Hack Mover checks it. The new keyboard-side conclusion is stronger too: 1478:5fb3 does not act like a live positive enable latch in Spanish, because every recovered consumer requires it to be zero and the Laurie-hint helper pulses it back to zero immediately, while the nearby 8ad7/8ad8/8ad9 runtime-state writes still do not explain 8ad6. The Hack Mover runtime chain is also tighter now: 1478:5fb2 is the actual on/off toggle, 13e8:0ef9 / 13e8:0f77 clear it, 13e8:282f is the adjacent runtime helper using 1478:8ad9, and 13e8:2f0e / 13e8:3009 bracket the active drag state via 1478:8ac0, 1478:8acc, and 1478:8ace. Current safest localized-build read is therefore -laurie is the only recovered positive enabler for the surviving broad Spanish cheat/debug family; no replacement hidden matcher, no runtime keyboard-latch bootstrap, and no direct Spanish F10 cheat branch have been recovered, with the remaining open question narrowed to whether 1478:8ad6 is written through an analysis-dark path or is just a dead leftover gate.

Recent startup fixed-map patch batch: docs/startup-map-patch-file.md now records the current evidence-backed read of the retail Using map patch file. startup line. Current best read is that Init_Everything at 1048:039b prints that line only if static\fixed.dat exists, and the later fixed-map loader path treats that file as a preferred alternate FIXED.DAT source by loading it into DAT_1478_1064 and choosing that handle over the base archive handle when present. The safest current wording is therefore alternate fixed-map archive selected at startup, not the -u usecode override and not a proven per-record merge overlay.

New roadmap note: docs/function-knowledge-roadmap.md now turns the current decompilation state into a concrete path toward broad function coverage, with explicit completion criteria, lane priorities, and batch rules. The same note now also records the latest applied process-family rename work: 1100:0437 = SurrenderProcess_Destroy, 1100:0913 = NPC_DoRandomIdleAnimTwiceIfNotBusy, 1100:0d3e = LoiterProcess_VtableSlot10DispatchByShapeIfAlive, 1100:0fe8 = PaceProcess_Destroy, 1100:0f95 = GuardProcess_Destroy, 1100:0f47 = LoiterProcess_Destroy, 1100:1036 = StandProcess_Destroy, 1100:1084 = NPCActionProcess_RunNoop, 1100:1089 = NPCActionProcess_Destroy, 1100:0fe3 = NPCActionProcess_VtableSlot10Noop, 1128:1e14 = CruHealer_Destroy, 1128:1fbe = BatteryChargerProcess_Destroy, 1128:22ca = DeathSilenceProcess_Destroy, 1110:0f19 = PathfinderProcess_Destroy, 1090:0aaf = TeleporterProcess_Destroy, 1090:0a60 = EggHatcherProcess_Destroy, 1020:087e = MapJumpProcess_Destroy, 1028:06bd = FadeProcess1_Destroy, 1030:03cc = AnimProcess_Destroy, 1058:08fc = SnapProcess_Destroy, 10a0:4437 = ItemProcess_Destroy, 1138:0819 = SuperSpriteProcess_Destroy, 1150:32d3 = OneFrameDelayProc_Destroy, 1180:1e0a = CameraProcess_Destroy, 11b8:0293 = KeyDaemonProcess_Destroy, 11b8:04c5 = KeyboardProcess_Destroy, 11c0:06df = AccWaitProcess_Destroy, 11c0:0748 = SystemTimerProcess_RunNoop, 11c0:074d = SystemTimerProcess_Destroy, 11c8:03fd = BiosProcess_Destroy, 13b8:012e = CustomWaitProcess_Destroy, 1430:0363 = DumbTimerProcess_Destroy, 1438:0557 = CycleProcess_Destroy, 1440:0f67 = FadeProcAlt_Destroy, 1468:4322 = MyTimerProcess_Destroy, 1468:0494 = VideoPlayer_Destroy, 1468:03e3 = VideoPlayer_InitializePlayback, 1468:2f7c = VideoPlayer_OpenMediaFiles, 1468:32cb = VideoPlayer_AllocPlaybackBuffers, 1468:3904 = VideoPlayer_OpenMoviListAndPrimeStreams, 1468:0483 = VideoPlayer_StopAndDestroyWrapper, 1468:431d = VideoPlayerProcess_VtableSlot11Noop, 1468:001a = File_Exists, 1468:03b4 = VideoPlayer_FormatErrorMessage, 1468:17b0 = VideoPlayer_AdvanceChunkCursor, 1468:1d3d = VideoPlayer_AdvanceChunkCursorWrapper, 1468:1ef7 = VideoPlayer_LoadAudioChunk, 1468:1929 = VideoPlayer_LoadVideoChunk, 1468:1a92 = VideoPlayer_BlitDecodedFrame, 1030:0428 = GameTimeProcess_Destroy, 1030:03c7 = AnimProcess_RunNoop, 1048:0d3e = Process1048_0000_RunNoop, 1048:0d43 = Process1048_0000_Destroy, 1050:051f = SavegameSlot_GetLabelPtr, 1050:0532 = SavegameSlot_SetLabel, 1050:057e = File_CloseAndMaybeFree, 10c0:00b9 = MapJumpProcess_VtableSlot10AdvanceItemFind, 10e8:4192 = AnimPrimitiveProcessSomethingElse_Destroy, 10f8:0120 = ItemScript_AppendBytes, 10f8:0161 = ItemTypeflagRecord_ResetDefaults, 1150:2f20 = AnimPrimitiveProcessFamily_VtableSlot11CallSlot3, 1188:0057 = Process1188_0000_RunOnTimerDelta, 1188:0979 = Process1188_0000_Destroy, 11c0:0483 = WaitProcessFamily_VtableSlot10DispatchByPair, 11c0:0691 = WaitProcess_Destroy, 11c0:02bf = AccWaitProcess_VtableSlot10DispatchByAnimation, 1138:0444 = SpriteProcess_Destroy, 12e0:0151 = ASS_StoreInitCallbackState, 13c8:03f5 = MainMenu_Destroy, 13c8:04ee = MainMenu_DrawCornerDecorations, 13c8:06a4 = MainMenu_HandleButtonClick, 13c8:06cd = MainMenu_HandleKey, 13c8:082e = MainMenu_ActivateSelection, 13c8:0ce7 = MainMenuOptionButtonGump_Create, 13c8:0dc0 = MainMenuOptionButtonGump_HandlePointerEvent, 13c8:0e2d = MainMenuOptionButtonGump_SelectPeer, 13c8:0e94 = MainMenuOptionButtonGump_Draw, 13c8:0ece = MainMenuOptionsPanel_Create, 13d0:0000 = SavegameNameField_MapInputChar, 13d0:0226 = SavegameMenu_Destroy, 13d0:02cb = SavegameMenu_HandleKey, 13d0:03dd = SavegameMenu_HandleSlotAction, 13d0:058c = SavegameSlot_DrawCornerDecorations, 13d0:074e = SavegameSlotGump_Create, 13d0:0841 = SavegameSlotGump_Destroy, 13d0:08a8 = SavegameNameField_HandleKey, 13d0:0b0a = SavegameSlot_HandleClick, 13d0:0b89 = SavegameSlot_BeginEditOrActivate, 13d0:0cd5 = SavegameNameField_Draw, 13d0:0e18 = SavegameSlot_Select, 11c8:03c9 = BiosProcess_VtableSlot10DosRealFarCall, 1108:2259 = AttackProcess_VtableSlot10DispatchByClip, 1030:0183 = AnimProcess_VtableSlot10DispatchByPort, 1300:0d4e = BaseCameraProcess_VtableSlot10SetViewportRect, 1300:0d76 = BaseCameraProcess_VtableSlot11FreeBuffer, 13b8:021a = CustomWaitProcess_VtableSlot11ArmAndRun, 1440:03a0 = FadeProcess2_VtableSlot10BlendTowardTargetPalette, 1448:08fd = FlicPlayProcess_Destroy, 1448:3290 = FlicWaitProcess_Destroy, 11f8:00a4 = MusicPlayerProcess_RunNoop, 11f8:035e = MusicPlayerProcess_Destroy, 11f8:028e = Music_RestorePreviousTrackFromStack, 11f8:02bf = Music_LoadStateAndReplayCurrentTrack, 11f8:0311 = Music_SaveState, 12e0:0267 = AssProcess_Destroy, 1448:00eb = FlicWaitProcess_VtableSlot10TickAndMaybeAdvance, 11f8:00a9 = MusicPlayerProcess_VtableSlot10Noop, 12e0:00ed = AssProcess_VtableSlot5ClearCreatedFlag, 12e0:0105 = AssProcess_VtableSlot6SetCreatedFlag, 1020:08cd = Process_VtableSlot4Noop, 1020:08d2 = Process_VtableSlot8Noop, 1028:0724 = Process_VtableSlot9ReturnZero, 1468:0114 = MyTimerProcess_VtableSlot10IncrementCounterOnTick, 11f0:02b9 = StdIntHandlerProcess_Destroy, 12f8:0530 = GumpShared_DestroyNoop, 12f8:0544 = KeyboardInputHandler_DestroyNoop, 12f8:0553 = GumpShared_VtableSlot10Noop, 12f8:0578 = KeyboardInputHandler_VtableSlot10Noop, 12f8:057d = KeyboardInputHandler_VtableSlot11Noop, 1308:0616 = ButtonGump_Destroy, 13c0:04ee = KeypadGump_Destroy, 13c0:0a94 = KeypadButtonGump_Destroy, 13e8:3aae = HelpGump_Destroy, 13e8:3ba5 = HelpGump_RefreshPage, 13e8:3d53 = HelpGump_HandleAdvanceAction, 13e8:3d99 = HelpGump_HandleNavigationKey, 13e8:3ec8 = HelpGump_RunAmbientSfxTick, 13e8:3fd8 = RunCreditsProcess_Destroy, 13f8:01e9 = QuickSaveLoadExitGump_Destroy, 13f8:0510 = Gump13f80383_Destroy, 13f8:058c = Gump13f80383_Draw, 13f8:05c6 = Gump13f80383_VtableSlot10Noop, and 13f8:05cb = Gump13f80383_VtableSlot11Noop. That work is now live in Ghidra, and it also confirms the practical write-path rule for future work: read-only MCP analysis can stay on the live GUI session, while live write-capable scripts can land small verified rename/comment batches when the simpler edit-plan route refuses to commit.

Latest broad-sweep correction batch: several previously over-specific gump no-op names were generalized after direct table evidence showed they are shared across multiple gump families, not keyboard-only handlers. The live database now carries 12f8:0535 = GumpShared_VtableSlot3Noop, 12f8:0544 = GumpShared_VtableSlot7Noop, 12f8:0549 = GumpShared_VtableSlot8Noop, 12f8:054e = GumpShared_VtableSlot9Noop, 12f8:0578 = GumpShared_VtableSlot16Noop, and 12f8:057d = GumpShared_VtableSlot17Noop from direct g_helpGumpFnPtr / g_gump13f80383FnPtr slot reuse at 1478:6241 and 1478:6346.

Latest broad-sweep UI follow-up: the same UI-heavy lane is now tighter in three more local families without requiring deeper subsystem claims. The live database now carries 12f8:02e4 = GumpShared_DestroyCommon, 13f8:0237 = QuickSaveLoadExitGump_HandleChildButtonEvent, 13f8:0299 = QuickSaveLoadExitGump_HandleKey, 13f8:0349 = QuickSaveLoadExitGump_DrawLabel, 13f8:0383 = QuickSaveLoadExitGump_Create, 13c8:2f37 = MainMenuOptionsPanelButtonGump_Create, 13c8:2fca = MainMenuOptionsPanelButtonGump_DrawLabel, 13c8:3004 = MainMenuOptionsPanelButtonGump_Select, 13c8:3030 = MainMenuOptionsPanelButtonGump_Deselect, 13c8:1759 = MainMenuOptionsMenu_Destroy, 13c8:17c5 = MainMenuOptionsMenu_Create, 13c8:1e62 = MainMenuOptionsMenu_GetOptionRect, 13c8:2975 = MainMenuOptionsMenu_HandleChildButtonEvent, 13c8:29b3 = MainMenuOptionsMenu_HandleKey, 13c8:2b16 = MainMenuOptionsMenu_DrawTitle, and 13c8:2c56 = MainMenuOptionsMenuButtonGump_DrawLabel. Current best read is that 12f8:02e4 is the shared gump base destroy path used by multiple UI families, the 13f8: mini-cluster is the quick save/load/exit modal's constructor-plus-local input/draw surface, the 13c8:2f37..3030 cluster is the options-panel-specific button wrapper layered over the generic 1308: button-gump create path, and the separate 13c8:1759..2c56 lane is now clearly the main options-menu create/destroy/input surface because its teardown path saves the current options back to config before the shared gump cleanup.

Recent retail debugger-entry follow-up: docs/retail-debugger-entry-options.md now consolidates the hidden-debugger entry question with the newer live Ghidra evidence instead of leaving it split across the older -debug and patch-attempt notes. Current best read is now tighter in three ways: first, fresh data-use recovery still finds reads but no writer for the debugger-state global at 1478:659c/659e; second, fresh decompiles of usecode_debugger_open_for_current_unit, usecode_debugger_open_modal, usecode_debugger_gump_create, and usecode_debugger_handle_event confirm that the debugger UI and event bundle are real but only meaningful after a valid break-state object/gump already exists; and third, the retail -u override remains the lowest-risk non-EXE experiment surface but still does not currently show a script-visible way to construct the seg1408 break-state object or write the required global pointer. The resulting priority order is now explicit: prefer a focused No Regret / JP No Remorse bootstrap comparison first, keep -u plus a replacement EUSECODE.FLX as the least invasive indirect experiment surface second, and treat the current interpreter-callsite-retarget patch family as the smallest structurally defensible retail EXE path only if cross-build comparison fails to reveal a smaller missing bootstrap.

Recent No Regret debugger follow-up: docs/regret-hidden-debugger-investigation.md now also records the first forcing-options pass instead of stopping at structural recovery. Current best read is that Regret is now the first build where a practical forced debugger bring-up looks realistically hackable without rebuilding the subsystem: executable patching is the strongest route because Regret already has the bootstrap, the live vtable override, and the interpreter-side auto-open path; live memory forcing is plausible if the debugger object already exists; and usecode remains useful only as a hybrid context-generator after code or memory has already armed the debugger, not yet as a pure launcher.

Recent JP hidden-debugger follow-up: docs/jp-remorse-hidden-debugger-investigation.md now records the first debugger-focused comparison pass on /ja/CRUSADER.EXE. Current best read is narrower than the No Regret result but still useful: the JP Win32 build clearly retains broad executable cheat/debug features, but this pass did not recover the classic hidden usecode-debugger UI signature bundle. Live byte searches on the active JP image found known positive-control strings like JASSICA16, Immortality enabled., and Cheats are now active., but returned no hits for the debugger-only strings Goto Line, Watch what?, Inspect what?, Global name, Search for, FILE NOT FOUND, Unable to open this file, Nothing to find, Not found, and Done. The practical outcome is that JP currently strengthens the broad cheat/debug support survived in Win32 story, but not the JP preserved the missing retail debugger bootstrap theory; No Regret remains the stronger sibling-build anchor for the hidden-debugger unlock problem.

Recent verified batch: docs/retail-debug-arg.md now records the live NE proof that retail CRUSADER.EXE still recognizes and executes a real -debug command-line branch. That branch prints Debugging mode ON., sets g_debugMsgLevel at 1478:87e0, and toggles two debug globals at 1478:0845/0859. The later sink pass also closes the text-output target more tightly: ProbablyPrintDebugMessage formats through the static stdio-style table at 1478:6c32..6c81 and writes to the handle-1 entry at 1478:6c46, so the non-video side is ordinary DOS stdout gated by the debug threshold, plus the already-confirmed AVI timing overlay. Current best read remains surviving debug-output / instrumentation switch, not the missing bootstrap for the hidden seg109/seg1408 usecode debugger. The same batch also leaves the earlier -laurie and 0x659c/659e debugger-state conclusions intact: -debug is a separate switch and is not currently evidenced as constructing the hidden usecode-debugger break-state object.

Recent tooling batch: docs/map-rendering.md now starts a dedicated offline map-rendering lane. tools/render_crusader_map.py can load FIXED.DAT, expand GLOB.FLX, decode the required SHAPES.FLX entries with Crusader frame headers, apply GAMEPAL.PAL, and write a first-pass PNG, with a --fixed-dat override so the same pipeline can be pointed at either game's map file. The current renderer is intentionally limited to fixed-map content and a simple deterministic painter rather than the full Pentagram/ScummVM dependency sorter, and the current workspace caveat is that STATIC_REGRET still lacks a copied FIXED.DAT, so No Regret rendering needs that file supplied explicitly.

Recent map/editor visibility batch: docs/editor-object-visibility.md now records a focused live-Ghidra pass on whether retail CRUSADER.EXE explicitly hides editor-only map objects and whether any built-in switch re-enables them. The current best read is now tighter than the first pass: Item_PaintSprite at 1198:02e4 does contain a real downstream flags2 & 1 (SI_EDITOR) early-out, but the active world-item renderer also has an upstream controlling skip at 1180:0951..095c that filters editor-tagged shapes before draw-node allocation. That corrected render-path model explains why the first executable patch attempt, which only flipped the downstream draw-time branch, produced no visible change in-game. The same note still closes the negative side of the question more tightly: no recovered retail -debug, cheat/debug hotkey, Laurie/usecode-debugger path, or 0x410 event behavior currently reaches either gate or exposes a show editor items state. The closest confirmed toggle remains ScummVM's own _showEditorItems debugger command, which is an engine-added reimplementation feature rather than evidence of a retail built-in toggle.

Recent map-viewer trigger batch: docs/map_renderer/trigger-usecode-links.md now records the evidence-backed editor/controller-object -> USECODE mapping used by the viewer when opening readable pseudocode from pinned tooltips. Current best read is that the stable viewer targets are BOX_EW, PANELNS, CARD_NS, and SPANEL -> use; FASTSKIL -> enterFastArea; SKILLBOX, EVENT, ALARMHAT, and ALRMTRIG -> equip; TRIGPAD and NPC_ONLY -> gotHit; and the 0x04B1 cmd helper itself -> TRIGGER.slot_20, the shared high-slot fan-out lane that nearby controller families keep spawning.

Recent usecode-event vocabulary note: docs/usecode-event-slots-combine-cast-fast-area.md now records a focused evidence pass on the suspicious inherited combine / cast slot names and the current best meaning of fast area. Current best read is that shipped Crusader usecode exposes no recovered slot_0C handler bodies at all, while slot_11 cast is real but acts as a scripted activation/dispatch lane rather than a classic spell system. The same note also tightens enterFastArea / leaveFastArea to authored proximity/activation region callbacks instead of the older speed-zone-style shorthand.

Recent startup/map-selection batch: docs/first-mission-map-selection.md now records the live proof that fresh-game map choice is code-selected rather than read from CRUSADER.CFG or another external mission-mapping file. For CRUSADER.EXE, the normal fresh-game path still hardcodes map 1, egg 0x1e inside Game_Start. For REGRET.EXE, the same values are hardcoded twice: once in an early Game_Start selector and again in the later FUN_1030_032d mission-start path that actually controls a real new game. The same note also captures the separate debug -warp mission path: it indexes a small executable-embedded mission-to-map word table at 1478:0488 (0,1,3,5,...,0x1d,0x28) and then applies -mapoff, while the actual map contents remain external in FIXED.DAT.

New REGRET startup-flow batch: docs/regret-game-start.md now documents the live REGRET.EXE Game_Start neighborhood more thoroughly. That note promotes HandleCommandlineArgs, Game_RunNewGameFlow, Game_DrawCenteredStartupSplash, Game_EnterFrontendMenuViewport, and Game_RestoreGameplayViewport in the live database, records the startup-state globals used by the new-game and -warp lanes, and explains the current best reason map 1 is set twice in No Regret: two separate live startup entry paths still own their own teleporter literals instead of sharing one final startup-map source.

New command-line argument batch: docs/command-line-parameters.md now consolidates the currently recovered startup/debug argument set across the retail Crusader executables. The key new closure is the actual direct-warp syntax in REGRET.EXE: -warp <mission> [x y z] rather than separate -x/-y/-z switches. The same note also records the now-proven precedence rule that nonnegative -egg overrides beat the X/Y/Z teleport path, the practical parameter-only route into eggless maps (-warp <mission> <x> <y> <z> plus -mapoff, with -egg omitted), and the current best read of -setver as a displayed version/build-string override rather than a gameplay compatibility switch.

Follow-up No Remorse cross-check: the same command-line note and docs/first-mission-map-selection.md now record the matching live CRUSADER.EXE proof. HandleCommandlineArgs at 1048:0adc uses the same positional -warp <mission> [x y z] syntax as Regret, and Game_Start at 1020:029e / 1020:02d0 applies the same precedence rule where nonnegative -egg overrides beat the direct-coordinate NPC_Teleport path.

Latest warp-table follow-up: the same docs/first-mission-map-selection.md and docs/regret-game-start.md notes now close the missing No Regret table details directly. Live REGRET.EXE Game_RunNewGameFlow indexes the -warp mission base-map table at 1480:075c, and retail byte checks now show the same 17-word payload as No Remorse: 0,1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,40, followed by a 0,0 terminator. The public renderer project now also has a dedicated extractor that writes both retail tables into Crusader_Decomp_Public/map_renderer/.cache/mission-map-data.generated.json for scene-metadata use.

Latest command-line follow-up: that same docs/command-line-parameters.md note now closes the retail non-Japanese -u lane as well. In live CRUSADER.EXE, the parser case at 1048:0a46 copies the following token into 1478:065a, and the newly named startup_apply_u_override_if_present at 1420:0cdf consumes that buffer to load an alternate usecode/EUSECODE source into 1478:6611/6613 before rebuilding the cumulative slot-base words. Current best read is therefore real startup usecode override, not JP-only feature and not dead parser-table residue. The same follow-up also means the older consolidated -setver note is now weaker on the CRUSADER side and should be treated as needing a direct retail re-close.

Latest -u deep dive: new note docs/usecode-startup-override.md now follows that retail override into the live usecode runtime itself. Current best read is that -u replaces the single live usecode root at 1478:6611/6613 rather than adding a parallel overlay. The same root is later consumed by Usecode_ItemCallEvent, UsecodeProcess_CreateProcess, Interpreter_NextUsecodeOp, and Item_GetDamaged, so the override reaches ordinary scripted gameplay behavior, not just a startup-only side lane. Current safest tooling implication is runtime replacement for the existing Crusader usecode VM, not arbitrary native plug-in system.

Latest -u token-shape follow-up: the same docs/usecode-startup-override.md note now tightens the argument semantics materially. In live retail CRUSADER.EXE, startup_apply_u_override_if_present does not pass the copied argv token through as an arbitrary final filename. It loads the mutable filename template eusecode.flx from 1478:07a0 via the far pointer at 1478:06d6/06d8, forces the first byte to 'e', and calls Filespec_GetFullPath(0, s_usecode, "eusecode.flx", 0). Current safest read is therefore path/root override for the standard EUSECODE archive family, not free-form arbitrary filename switch. The same note now also separates the stock-path status more cleanly: the raw-side VM bootstrap is strongly cross-referenced, but the exact live-NE writer that seeds 1478:6611/6613 without -u is still not directly closed.

Latest -u practical follow-up: that same docs/usecode-startup-override.md and docs/command-line-parameters.md notes now make the immediate user-facing consequence explicit. Failed attempts like -u USECODE/FLICTEST.FLX and -u FLICTEST.FLX fit the live helper badly because retail No Remorse still appends the fixed filename template EUSECODE.FLX; the copied argv token is only the path/root component. Current safest experiment shape is therefore directory passed to -u, complete replacement archive named EUSECODE.FLX inside that directory, not free-form archive basename override.

Latest -u loader-layout follow-up: the same docs/usecode-startup-override.md note now records the direct constructor/loader pair behind the override in the live NE session. 1420:1499 is now renamed entity_vm_runtime_create and currently reads as a 0x1319-byte runtime-object constructor with a 0x1300-byte front region that behaves like 0x80 stride-0x26 slot/runtime records plus tail metadata at 0x1300..0x1318. 1430:0000 is now renamed entity_vm_runtime_owner_resource_create and currently reads as the compact 0x14-byte file-backed helper allocated from the resolved eusecode.flx path and attached to the runtime object at +0x1315/+0x1317.

Latest doc-reconciliation batch: docs/ne-segment1.md now has a combined hidden-debugger component table that explicitly separates the seg109/raw-reference UI wrappers (000b:9a86, 000b:9c0d, 000b:b3b1, 000b:b62c, 000b:2882) from the live seg1408 breakpoint-state helpers (1408:0000, 1408:0053, 1408:00dd, 1408:029e, 1408:03b0, 1408:03f7, 1408:0419, 1408:0432, 1408:0444) and the interpreter hook at 1418:04aa..04b5. Current best read remains two connected layers of one hidden usecode debugger, not conflicting address claims for the same function family.

Latest hidden-debugger floor pass: docs/retail-debugger-patch-attempts.md now records a fresh live-Ghidra constraint check on the smallest viable retail unlock patch. Current best read is tighter than the earlier "there must be one tiny jump" idea: retail still has no recovered writer for 1478:659c/659e, the constructor still seeds only the inert shared callbacks 1478:65ab -> 1408:046f / 1478:65af -> 1408:0474, and the interpreter-side gate at 1418:049e..04b5 only checks for a non-null debugger object before handing off to 1408:0053. That makes the current O/P interpreter-callsite-retarget family the smallest structurally defensible executable patch shape so far, because smaller one-site ideas lose either object bootstrap, one-shot deferred gating, or wrapper-argument sanitation.

Follow-up cheat-key correction pass: docs/ne-segment1.md now also records a live NE cleanup of several folklore keyboard-cheat claims. ~ is a real runtime cheat-latch toggle at 13e8:203d, Ctrl+C is wrong for this build and should be Ctrl+L for the coordinate popup at 13e8:255e, and the third F7-family overlay really does exist as a separate Ctrl+F7 path at 13e8:1a20 alongside the other two cheat-gated F7 overlay toggles.

That same note now also separates ~ from jassica16 more cleanly: jassica16 is the raw scan-code unlock path that toggles both 1478:0844 and 1478:6045 and sets the extra post-sequence latch 1478:8c52, while ~ is only the later translated logical-0x7e hotkey that flips 1478:6045 after 1478:0844 is already on. The F7-family clarification is tighter too: Ctrl+F7 is best read as an egg-hatcher trigger-range overlay rather than a third generic background grid.

The same docs/ne-segment1.md note now also has the first consolidated cheat/debug key matrix for the live NE target, including which paths need the broader Laurie/debug master gate (1478:0844), which ones need the full keyboard-cheat latch (1478:6045), and which ones depend on the extra post-jassica16 latch (1478:8c52). That pass also expands the egg-hatcher explanation: Ctrl+F7 is now documented as a live EggHatcherProcess range visualizer, with practical guidance on where to look for egg-trigger regions in gameplay.

Latest F7 overlay follow-up: new note docs/f7-overlays.md now separates the three F7-family debug overlays more rigorously at the geometry level. The main correction is on Alt+F7: instead of treating it as broad egg coverage, the current best read now follows the live SnapProcess path directly, where Snap_AddSnapEgg is only reached for shape 0x04fe and Snap_GetSnapEggRange derives the overlay rectangle from that item's QHi, mapNum, and npcNum bytes. The same note also clarifies the viewer-facing rule for plain F7: use an origin-aligned infinite 0x200-unit world lattice across the visible viewport, not a screen-centered patch.

Documentation Structure

File Contents
docs/overview.md Binary overview, installed copy findings, address space layout, NE fixup placeholder, segment map, NE import details, next steps
docs/combat-dat.md COMBAT.DAT archive layout, live CRUSADER.EXE tactic-field integration, shipped opcode subset, and a human-readable catalog of all 14 tactic records
docs/phar-lap-extender.md DOS extender architecture, named functions (entry, loading, memory, I/O, interrupts), key string references
docs/ne-segment1.md NE Segment 1 full analysis: cursor, input, entity system, shot lifecycle, combat, weapons, AI, player/HUD, destruction, entity constants, vtable index, cheat system
docs/f7-overlays.md Focused note on the three cheat-gated F7 debug overlays: toggle sites, live consumers, recovered geometry math, what each overlay represents, and the current viewer-safe reproduction rules
docs/jp-remorse-windows9x-investigation.md Focused note on the Japanese /ja/CRUSADER.EXE Windows-native claim: PE/Win32 image evidence, Win32 windowing, DirectDraw/DirectSound, registry config under J1.21, IME/DBCS clues, and the GetVersion-driven Win9x compatibility branch
docs/jp-remorse-cheats-and-launch-params.md Focused note on surviving JP /ja/CRUSADER.EXE cheat/debug and startup-argument lanes: -laurie, JASSICA16, immortality, the recovered Win32 parser table, the live -u usecode override, and the current caution that JP -warp is only directly proven in mission-only form
docs/jp-remorse-hidden-debugger-investigation.md Focused first pass on whether the JP Win32 build kept the classic hidden usecode debugger: positive-control hits for surviving cheat/debug strings, but no live hits for the debugger-only UI string bundle (Goto Line, Watch what?, Inspect what?, Global name, Search for, FILE NOT FOUND, Unable to open this file, Nothing to find, Not found, Done)
docs/spanish-cheat-differences.md Focused comparison note for /es/CRUSADER.EXE versus the English build's known cheat/debug lanes: -laurie, broad cheat gate, gameplay-input gate, low-level keyboard latch, Ctrl+Q, Hack Mover, and the current status of the unresolved secret sequence
docs/raw-porting-progress.md seg091 RNG, 0x4588 callback lifecycle batches 1-6, 0007 gameplay helper batches, snap_entity_to_ground, AI sweep, animation/range/command globals, seg043 boundary recovery
docs/raw-000e.md 000e parser helper cluster (record table init/parse/dispatch), 000e RIFF/animation cluster (animation object field map, RIFF format, constructor variants)
docs/raw-0007-rendering.md Draw list node format and functions, world-to-screen isometric, tile visibility system, scroll/camera functions, scroll region table, save slot system, string/memory utilities, coordinate transform deep analysis
docs/raw-0008-000c.md 0008 dispatch helpers (init, pair-sync, flag helpers, word-list, gate-callbacks) and 000c state machine (tick dispatch, flag guards, palette fade, mini-VM, cursor nav)
docs/raw-000a-000d.md 000d proximity/visibility buckets, 000a tracked handles, cache manager, init/shutdown, seg082 allocator, seg137/138 palette helpers, seg004/005 startup, 0x4588 object-role evidence, 000d VM owner/resource loader follow-up
docs/far-call-targets.md Top-104 most-called far-call targets (Tiers 1-5, ranks 1-104), supporting functions discovered, analysis gaps and seg043 reconciliation
docs/function-knowledge-roadmap.md Concrete path to broad function coverage: completion criteria, prioritized workstreams, write-path discipline, staged rename batches, and immediate next steps
docs/crusader-disasm-reference.md Local auxiliary disassembly corpus at K:/ghidra/crusader-disasm: handwritten notes, shape tables, map dumps, opcode lists, intrinsic/function dumps, and the safe reuse rules for porting into CRUSADER.EXE
docs/ne-hole-filling-priorities.md Ranked CRUSADER.EXE hole-filling tracker: NE-side unclear lanes, the verified raw-side knowledge that can close them, and the recommended order for old-to-new porting passes
docs/retail-debugger-patch-attempts.md Chronological log of retail CRUSADER.EXE debugger-unlock patch attempts, byte-level designs, runtime failures, root-cause findings, and the current live candidate
docs/retail-debugger-entry-options.md Focused retail hidden-debugger entry analysis: fresh live-Ghidra proof that 1478:659c/659e still lacks a recovered writer, what the seg109 wrappers and gump constructor now prove about real reachability, why -u is the best low-risk experiment surface but still not a direct debugger bootstrap, and why No Regret / JP comparison is now the preferred next move
docs/regret-hidden-debugger-investigation.md Focused live REGRET.EXE hidden-debugger comparison: recovered wrapper/gump/dispatcher equivalents, the seg13e0 break-state family, the seg13f0 interpreter-side consumer, the debugger global at 1480:712c/712e, and the compact bootstrap stub at 1398:0000 that writes that global
docs/retail-debug-arg.md Focused note on the retail -debug command-line switch: live parser evidence, exact startup message, surviving globals, segment 1468 instrumentation path, and why it is currently separate from the hidden usecode debugger bootstrap
docs/startup-map-patch-file.md Focused note on the retail Using map patch file. startup line: exact Init_Everything print gate, static\fixed.dat detection, the later ItemCache_InitAndLoadFixedDat archive load, and the current evidence that fixed-map reads prefer the alternate archive when present
docs/remorse-class-candidate-inventory.md Evidence-backed inventory of the strongest current Remorse class families, with confidence, ctor/dtor/vtable/layout anchors, and recommended modeling order for later Ghidra class work
docs/remorse-class-lift-index.md Central navigation note for the Remorse class-lift and C++-reconstruction prep lane, grouping the plan, candidate inventory, ABI notes, endpoint spec, and family-specific layout notes into one work order
docs/remorse-first-class-authoring-checklist.md Operational checklist for the first real Ghidra/MCP class-authoring batch, including pilot-family order, authoring rules, and source-emission readiness gates
docs/remorse-cpp-decompilation-plan.md Plan for shifting the current Remorse decompilation from flat C-like recovery toward evidence-backed C++ classes, typed object models, and an eventual recompilable source tree
docs/remorse-cpp-compatibility-header-draft.md Draft contract for the future compatibility/support header that early Remorse C++ skeletons should target: exact-width aliases, packing markers, calling-convention placeholders, segmented-pointer helpers, and slot-order guardrails
docs/remorse-toolchain-fingerprint-evidence.md Focused evidence note for the current toolchain story behind Remorse reconstruction: bound MZ -> NE structure, Phar Lap runtime, loader-patched far calls, and the current High-C-related runtime fingerprints
docs/ghidra-mcp-class-lifting-endpoint-spec.md Draft endpoint surface for future GhidraMCP class-lifting work: namespace/class creation, symbol moves, struct and vtable authoring, this typing, and transactional class-layout application
docs/scummvm-crusader-reference.md ScummVM Ultima8/Pentagram Crusader integration survey: USECODE/event tables, FLEX/resource formats, world/map loaders, HUD/media, and RE follow-up priorities
docs/pentagram-crusader-reference.md Pentagram-source Crusader/U8 reference: direct Crusader USECODE parser and VM evidence, U8 usecode docs, runtime-confidence limits, and cross-checks against the ScummVM note
docs/map-rendering.md Offline map-rendering lane: FIXED.DAT/GLOB.FLX/SHAPES.FLX/GAMEPAL.PAL format notes, current Python renderer, supported inputs, and fidelity gaps
docs/editor-object-visibility.md Focused note on retail editor-only map object hiding: the live 1198:02e4 SI_EDITOR early-out in the normal item paint path, the lack of a recovered retail visibility toggle, and the ScummVM/Pentagram cross-check that treats show editor items as an engine-side debug feature
docs/entity-class-family-split.md Focused working note on the large seg001 Entity lane: shared base-layout evidence, conservative split into projectile, debris, corpse/remnant, and adjacent non-entity families, and the recommended promotion order for later class lifting
docs/entity-dispatch-entry-class-layout.md Focused working note for the EntityDispatchEntry family: base versus derived split, stable field groups, constructor and release surfaces, candidate method map, and conservative future Ghidra modeling order
docs/entity-vm-runtime-owner-resource-layout.md Focused working note for the VM runtime lane: EntityVmRuntime, EntityVmOwnerResource, and EntityVmContext ownership, stable layout claims, masked-create helpers, and the safest current class-lift order
docs/presentation-callback-broker-layout.md Focused working note for the 0x4588 callback-object lane: install/teardown lifecycle, global state cluster, provisional vtable slots, payload-pair evidence, and conservative class-lift guidance
docs/map_renderer/trigger-usecode-links.md Evidence-backed map-viewer note for editor/controller shapes that now expose direct USECODE navigation, including the stable class/event targets and the special TRIGGER.slot_20 handling for 0x04B1 cmd helpers
docs/map_1_spawners_targeted_investigation.md Focused map-1 note on suspicious 0x04D0 frame-paired spawners: decompressed-cache examples, the recovered MONSTER -> ITEM.slot_2D -> create NPC chain, QLo-based pairing, and the corrected mapNum bit 0x08 enter-area interpretation
docs/first-mission-map-selection.md Focused note on fresh-game startup map selection: No Remorse Game_Start, No Regret's early and later mission-start selectors, the separate embedded -warp mission table, and the split between code-selected startup and external FIXED.DAT map content
docs/regret-game-start.md Detailed REGRET.EXE startup-flow note: Game_Start, Game_RunNewGameFlow, newly named helpers, startup override globals, and the current best explanation for the duplicated map-1 selector
docs/remorse-rebuild-abi-notes.md Working note for rebuild constraints: segmented-memory model, far-call provenance, runtime/toolchain evidence, ABI guardrails, and the split between original-style executable reconstruction and a behaviorally equivalent port
docs/command-line-parameters.md Consolidated startup/debug argument reference for the retail Crusader executables: live retail -u usecode override, the current -setver caution, -debug, -asylum, -warp, -skill, -mapoff, -egg, -demo, the -laurie cross-reference, and the evidence-backed direct-coordinate warp syntax/limits
docs/psx/psx.md PlayStation SLUS_002.68 and disc-resource note: boot/load layout, LSET/menu WDL structure, executable-backed map inventory, passcode alphabet/display path, recovered PSX ammo/item/weapon tables, and current unresolved enemy/password-compare gaps
docs/psx/map-rendering.md Detailed PlayStation map-rendering architecture note: LSET*.WDL storage model, constructor record layouts, runtime banks, state/variant/art bridge, stage-1 versus stage-2 render lanes, visible-list sorting, final primitive submission, and the current best recipe for reconstructing PSX maps in the viewer
docs/psx/art-binding-recovery.md Focused PSX viewer recovery note: extraction-versus-render diagnosis, zero-block DAT_800758d8 constructor-family donor heuristics, measured fallback reduction, representative map stats, and the remaining outlier families/maps
docs/psx/prealpha.md PlayStation pre-pre alpha /psx/prealpha/SLUS_002.68 comparison note: reduced disc inventory, retained retail-style LSET loader, surviving No Remorse branding, stale TALK1.XA and LoadExec leftovers, and the current read that this build is closer to an unfinished No Remorse PSX branch than to a visibly rebranded sequel executable
docs/sprite-node-class-layout.md Focused working note for the SpriteNode family: current core layout, destructor and event-dispatch evidence, candidate virtual slots, and a conservative Ghidra modeling plan
docs/usecode-startup-override.md Focused retail -u deep dive: startup call order, why the override looks like full live-root replacement rather than addition, which event/process/interpreter consumers use that root, and what that implies for future custom usecode experiments
docs/usecode-roundtrip-ir.md ScummVM-to-binary USECODE cross-walk, owner-loaded class-layout and header/event-count reconciliation, conservative IR v0 plan, and the generated class-event/body-window outputs that now ground reversible _BOOT, SURCAM*, and environmental family decompile artifacts plus repeated-family regression checks
docs/usecode-event-slots-combine-cast-fast-area.md Focused note on whether inherited event labels combine and cast are actually live in shipped Crusader usecode, plus the current evidence-backed explanation of enterFastArea / leaveFastArea as proximity-trigger callbacks
docs/usecode-pentagram-ghidra-path.md Pentagram-derived Crusader USECODE parser plan, proof-of-concept workflow, canonical IR v1 goals, and the Ghidra-side annotation import path
docs/usecode-tooling-comparison.md Comparison of Pentagram's converter/disassembler, the local crusader-disasm corpus/scripts, and the current workspace parser/pseudocode exporter, with emphasis on assumptions, strengths, and repo-specific differences
docs/usecode-tool-improvement-plan.md Concrete next-step plan for the local USECODE parser/decompiler, distilled from the Pentagram and crusader-disasm comparison into prioritized parser, loop-decoding, intrinsic, trailer, corpus, and runtime-bridge upgrades
docs/usecode-jelyhack-analysis.md Focused analysis of exported JELYHACK / JELYH2 pseudocode, the tiny shared use stub, and why the current best model remains referent anchor + neighboring event-bearing attachment
docs/usecode-equipment-system.md Evidence-backed note on Crusader's surviving equip / unequip event system, including live compiled-side dispatcher proof, corpus-wide slot counts, actor/turret/environment examples, and the current best model of equip as a generalized inherited Ultima-style item event
docs/usecode-alarmhat-analysis.md Focused analysis of exported ALARMHAT::equip, the nearby shape 0x04D0 equip loops, alarm-family comparisons, and the current gameplay-facing read of ALARMHAT as a local alarm-state driver
docs/usecode/flictest-investigation.md Focused investigation of FLICTEST: class/body structure, Remorse versus Regret differences, confirmed caller scripts, and the stronger Regret finding that a hidden KEYPADNS VIDEO PLAYER route appears to have matching shipped placement evidence
docs/usecode/windsurf-regret-vs-remorse.md Side-by-side comparison of WINDSURF in Regret and No Remorse, including shared slot behavior, helper-family drift, body-size differences, and the current best read of WINDSURF as a directional wind-force helper used by vent scripts
docs/removed_items.md Evidence summary for suspicious removed item shapes in old No Remorse maps: grenade-family leftovers 0343/034E/034F/0350, the inventory-labeled 0548 Invalid item, and unresolved non-pickup shapes 0110/0112