- Introduced new binary files for user data and database. - Updated project state to include new paths for Spanish executable. - Added detailed notes on Spanish cheat/debug differences in a new document. - Revised mid-project plan to reflect findings from localized build comparison.
11 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 localized-build batch: docs/spanish-cheat-differences.md now records a focused live-Ghidra comparison against /es/CRUSADER.EXE for the known cheat/debug control areas. Current best read is now split more tightly: 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. The -laurie parser still sets the broad cheat/debug gate (1478:0910), the gameplay-input gate still exists at 1478:0927, the lower keyboard-cheat latch still exists at 1478:5fb3, and Hack Mover still toggles through 13e8:24a5; but a direct live byte scan found no exact 24 1e 1f 1f 17 2e 1e 02 07 00 table anywhere in Spanish data 1478:0000-8c3f or 1480:0000-1fff, and the old English-side slot at 1478:2833 now contains pointer-like words instead. The same batch also tightens the secondary-latch story: Hack Mover is pre-gated by 1478:8ad6 before the broad gate check, so the Spanish target still appears to retain an additional post-sequence-style latch even though its actual writer and matcher routine remain unresolved.
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.
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.
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.
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/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/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/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-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/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/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-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/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 |