Crusader_Decomp/crusader_decompilation_notes.md

49 lines
13 KiB
Markdown
Raw Normal View History

# 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](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.
2026-03-25 23:32:13 +01:00
Recent verified batch: [docs/retail-debug-arg.md](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.
2026-03-26 23:12:38 +01:00
Recent tooling batch: [docs/map-rendering.md](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.
2026-03-25 23:32:13 +01:00
Latest doc-reconciliation batch: [docs/ne-segment1.md](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](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](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](docs/phar-lap-extender.md) | DOS extender architecture, named functions (entry, loading, memory, I/O, interrupts), key string references |
| [docs/ne-segment1.md](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](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](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](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](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](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](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](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](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](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](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 |
2026-03-25 23:32:13 +01:00
| [docs/retail-debug-arg.md](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](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](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 |
2026-03-26 23:12:38 +01:00
| [docs/map-rendering.md](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/usecode-roundtrip-ir.md](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](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 |
2026-03-25 23:32:13 +01:00
| [docs/usecode-tooling-comparison.md](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](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](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](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](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 |
2026-03-26 00:37:17 +01:00
| [docs/usecode/windsurf-regret-vs-remorse.md](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 |