Documentation improvements
This commit is contained in:
parent
d78808d6b5
commit
c34f481c3a
34 changed files with 2800 additions and 20 deletions
31
plan-mid.md
31
plan-mid.md
|
|
@ -50,10 +50,22 @@ Detailed completed analysis belongs in the files under `docs/`, not in this plan
|
|||
- 000e parser and animation subsystems have a real partial map.
|
||||
- The auxiliary local disassembly corpus at `K:/ghidra/crusader-disasm` is now inventoried and integrated as a separate evidence source for shape metadata, static map/object dumps, opcode names, and older Remorse/Regret intrinsic-function vocabularies; its safe-reuse rules and porting implications are captured in `docs/crusader-disasm-reference.md`.
|
||||
- The workspace now also has a first dedicated offline map-rendering/tooling lane: `tools/render_crusader_map.py` can load a chosen `FIXED.DAT`, expand `GLOB.FLX`, decode required `SHAPES.FLX` frames, apply `GAMEPAL.PAL`, and emit a first-pass PNG from either static set, while `docs/map-rendering.md` captures the current format contracts, the `--fixed-dat` override, and the intentionally limited compositor model.
|
||||
- The map/editor-visibility lane is now tighter too. New note `docs/editor-object-visibility.md` records live `CRUSADER.EXE` proof that the downstream item draw helper `1198:02e4` (`Item_PaintSprite`) explicitly returns early on `ShapeData.flags2 & 1` (`SI_EDITOR`), but the follow-up render-path pass also found the controlling upstream skip at `1180:0951..095c` in the world-item builder. Current best read is therefore `editor-tagged shapes are filtered before draw-node allocation in the normal world-item renderer, with a second downstream paint-time guard still present`, which also explains why a first patch that only flipped `1198:033b` produced no visible change in-game. No recovered retail `-debug`, cheat/debug hotkey, Laurie/usecode-debugger path, or `0x410` lane currently re-enables those objects. The closest confirmed toggle remains ScummVM's own `_showEditorItems` debugger command, which is engine-added rather than retail.
|
||||
- The localized-build comparison lane now covers the Japanese Windows-native executable too. New note `docs/jp-remorse-windows9x-investigation.md` records that `/ja/CRUSADER.EXE` is a PE-style Win32 image with native window creation, DirectDraw/DirectSound init, registry-backed config under `Software\Electronic Arts\Crusader: No Remorse\J1.21`, IME/DBCS-facing imports, and a `GetVersion`-driven Win9x compatibility branch that retries `TlsAlloc()` until the slot is above `2` when the classic Win9x version bit is set. Current best read is `real Windows 9x-native port with likely Win95 intent`, with runtime prerequisites still left to test.
|
||||
- The Japanese localized-build lane now also covers surviving cheat/debug and startup-argument behavior. New note `docs/jp-remorse-cheats-and-launch-params.md` records that the JP Win32 build still has a live `-laurie` special-case, a live `JASSICA16` cheat-state matcher, a still-executable immortality toggle path, and a working Win32 parser for `-debug`, `-u`, `-warp`, `-skill`, `-mapoff`, `-egg`, and `-demo`. The same pass also adds one important caveat relative to the older DOS-side docs: the JP Win32 parser is only directly closed for mission-only `-warp <mission>` so far, not for positional `-warp <mission> <x> <y> <z>`.
|
||||
- The startup map-selection lane is now tighter across both retail games too: No Remorse still hardcodes `Teleporter_CreateProcessDirect(1, 0x1e, 1)` inside `Game_Start`, while No Regret keeps the same literal selector in two live places, the early `Game_Start` site at `1008:1448` and the later authoritative new-game hop in `Game_RunNewGameFlow` at `1030:05c5`. The separate `-warp mission` path still uses an executable-embedded word table plus `-mapoff`, and the repo docs now include the dedicated REGRET-side note `docs/regret-game-start.md`. Current best read remains `startup map choice in code, map contents in external FIXED.DAT resources`, not `mission-start map configured in CRUSADER.CFG`.
|
||||
- That same startup lane is now tighter at the argument level too. Current best parser/control-flow read in `REGRET.EXE` is `-warp <mission> [x y z]`, with X/Y/Z carried as positional argv tokens after the mission number rather than as separate recovered switches. The corresponding runtime branch in `Game_RunNewGameFlow` is also clearer: nonnegative `-egg` overrides beat the coordinate path, while the real eggless-map workaround is `-warp <mission> <x> <y> <z>` plus `-mapoff` with `-egg` omitted so the game falls into direct `NPC_Teleport` instead of the teleporter-egg lookup.
|
||||
- The matching No Remorse cross-check is now closed too. Live `CRUSADER.EXE` `HandleCommandlineArgs` at `1048:0adc` uses the same positional `-warp <mission> [x y z]` parser shape, and `Game_Start` at `1020:029e` / `1020:02d0` uses the same runtime precedence: direct coordinates only win when the egg override is still negative, otherwise the code falls back to `Teleporter_CreateProcessDirect`. The parameter-only eggless-map workaround is therefore shared across both retail games, not Regret-specific.
|
||||
- The command-line lane is tighter around `-u` now too. In live non-Japanese `CRUSADER.EXE`, the parser case at `1048:0a46` copies the following token into `1478:065a`, and the renamed `startup_apply_u_override_if_present` at `1420:0cdf` later consumes that buffer to resolve/load an alternate usecode/EUSECODE source into `1478:6611/6613`, mark `1478:6615`, and rebuild the cumulative slot-base words at `1478:8c7c..8c82`. Current best read is `real retail startup usecode override`, not `JP-only` and not `dead string-table residue`; the paired consequence is that the older CRUSADER-side `-setver` attribution should now be treated as reopened until its exact retail consumer is isolated directly.
|
||||
- That same `-u` lane is now tighter at the runtime-scope level too. The follow-up note `docs/usecode-startup-override.md` now records that retail `-u` appears to replace the single live usecode root at `1478:6611/6613`, not add a sidecar table: `startup_apply_u_override_if_present` overwrites that root directly, rebuilds the cumulative slot-base words, and later consumers including `Usecode_ItemCallEvent`, `UsecodeProcess_CreateProcess`, `Interpreter_NextUsecodeOp`, and `Item_GetDamaged` all read the same replacement root. Current safest tooling implication is `runtime swap for the existing Crusader usecode VM`, which makes `-u` a potentially important future validation hook for round-tripped/custom usecode archives once the accepted source format is nailed down.
|
||||
- The same `-u` lane is tighter at the token-shape level now too. Live `1420:0cdf` does not use the copied argv token as an arbitrary final filename; it treats `1478:065a` as the `Filespec_GetFullPath` path component while loading the fixed mutable filename template `eusecode.flx` from `1478:07a0` through `1478:06d6/06d8` and forcing the first byte to `'e'` before both the existence probe and the final load call. Current safest read is therefore `path/root override for standard EUSECODE archive naming`, not `free-form filename override`. The stock bootstrap side is also better scoped: `1478:6611/6613` starts zero in the live NE image and the only currently recovered explicit writer there is the `-u` helper, so the normal non-`-u` seed remains only cross-referenced through the verified raw-side VM bootstrap note rather than fully live-NE-closed.
|
||||
- The same override lane now has a concrete live-NE constructor pair too. `1420:1499` is now renamed `entity_vm_runtime_create` and currently reads as a `0x1319`-byte runtime-object allocator that zeroes a `0x1300`-byte front region behaving like `0x80` stride-`0x26` slot/runtime records before storing an attached helper pointer at `+0x1315/+0x1317`. `1430:0000` is now renamed `entity_vm_runtime_owner_resource_create` and currently reads as the compact `0x14`-byte file-backed helper that opens the resolved `eusecode.flx` path, queries entry count through vtable `+0x04`, allocates a backing buffer at `+0x10/+0x12`, and materializes indexed owner/resource records through vtable `+0x0c`. Current safest implication is that `-u` swaps the live VM runtime object graph, not just a raw archive handle.
|
||||
- The USECODE/VM owner/resource/runtime lane now has a workable partial model, a named sequencer entry, paired external file-family loader evidence, and supporting extraction/reporting tooling.
|
||||
- The USECODE/VM tooling lane now also has a concrete near-term implementation path: a Pentagram-derived proof-of-concept parser can reuse opcode decoding while swapping in the locally verified owner-loaded class and slot arithmetic, with a hybrid Ghidra comment/bookmark import path instead of a premature custom processor module.
|
||||
- The USECODE tooling lane now also has a first full readable corpus export: `tools/export_usecode_pseudocode.py` writes `977` current pseudocode bodies into `USECODE/EUSECODE_extracted/pseudocode`, and the first focused read of that corpus now shows `JELYHACK::use` / `JELYH2::use` as tiny shared `set_info(0x0207) -> process_exclude -> return` stubs rather than hidden active event cores.
|
||||
- The USECODE tooling lane now also has two new follow-up notes grounded in the exported corpus: `docs/usecode-tool-improvement-plan.md` turns the Pentagram/`crusader-disasm` comparison into a concrete parser roadmap, and `docs/usecode-alarmhat-analysis.md` records the current best evidence-backed read of `ALARMHAT::equip` as a frame-driven local alarm-state controller that equips nearby `shape 0x04D0` helper objects in different modes.
|
||||
- That same `0x04D0` lane is tighter again after the next follow-up: `MONSTER::enterFastArea` is now verified as the immediate-spawn gate for `shape 0x04D0`, with the automatic lane only reached when `frame == 0` and `(mapNum & 0x08) == 0`, while frame `1` skips that hook entirely and remains the best current candidate for paired or externally signaled setups.
|
||||
- The public renderer follow-up now has a better audit surface for that same lane: the `Monster Spawners` panel lists `0x04D0` records directly, the tooltip editor writes the verified `frame`/`mapNum bit 0x08` controls back into exportable FIXED records, and the new arrow overlay is intentionally scoped to evidence-backed link families only. Exported-usecode corroboration now reaches beyond `ALARMHAT` too: `ITEM.slot_2D`, `FUSPAC.slot_01`, and `MISS8.slot_20` all show nearby `0x04D0` scans keyed by frame and/or `Item.getQLo(...)`, which strengthens the current low-quality-byte-as-local-signal-key model without promoting it into a universal object pointer.
|
||||
- The USECODE tooling lane now also has a broader equipment-event note: `docs/usecode-equipment-system.md` records live binary proof that `Item_Equip` / `Item_Unequip` are real generic usecode event dispatchers gated by owner-row capability masks (`0x400` / `0x800`), and that the exported corpus currently contains `77` `equip` bodies plus `50` `unequip` bodies spread across actor, turret, alarm, conveyor, camera, and hazard classes. Current best read is `surviving Ultima-style event vocabulary generalized into activation/setup/state-change semantics`, not yet `fully proven paper-doll RPG gear subsystem`.
|
||||
- The USECODE tooling lane now also has its first implemented readability follow-through from that improvement list: `tools/poc_crusader_usecode_parser.py` and `tools/export_usecode_pseudocode.py` now regenerate the full `977`-body corpus with one verified wrapper alias seed (`FREE.waitNTimerTicks` for `0A0C:0032`), class-name-aware target rendering (`FREE.slot_21`, `BLASTPAC.slot_20`, `TRIGGER.slot_20`, etc.), first-pass selector decoding that upgrades the simpler alarm/trigger `loopscr` runs into `for ... in nearby_items(shape=..., origin=...)` / `for ... in nearby_items(family=..., origin=...)` loops, and a second readable selector-family fallback that collapses raw `loopscr 0x42` runs into `selector_0x42(arg0=..., arg1=..., arg2=..., origin=...)` annotations or `for ... in selector_0x42(...)` loops where the control flow is simple enough.
|
||||
- The USECODE/VM lane now also has a verified generic masked-context creation hub (`000d:463a`) plus two concrete sequencer-internal consumer blocks (`000d:208b`, `000d:21ed`) built directly on `entity_vm_context_create_from_slot_index`.
|
||||
|
|
@ -175,16 +187,17 @@ Detailed completed analysis belongs in the files under `docs/`, not in this plan
|
|||
6. Use boundary repair only on active blockers with clear payoff, with `000c:db68` now downgraded to optional hygiene unless it blocks adjacent work again.
|
||||
7. Revisit the `0x4588` callback object only when caller-side evidence is strong enough to support behavioral naming.
|
||||
8. Exercise `tools/render_crusader_map.py` on a few representative No Remorse and No Regret maps, then tighten the paint order using `TYPEFLAG.DAT` footpads and any mismatches visible against in-game screenshots or `crusader-disasm` map evidence.
|
||||
9. If the map/editor-visibility lane is revisited, start from `docs/editor-object-visibility.md` and the upstream `1180:0951..095c` world-item builder gate first; rule in or rule out a second debug-only world-item builder before spending more time on cheat or command-line searches.
|
||||
|
||||
9. Recover the real upstream caller/selector path into `entity_vm_opcode_sequence_run`, most likely by finding the first non-recursive `0x6714` context-method caller or vtable dispatch site rather than by repeating raw xref queries that still return no direct edges.
|
||||
10. Recover real caller roles for `entity_vm_context_try_create_mask_0400_slot0a_with_offset` and `entity_vm_context_try_create_mask_0800_slot0b_with_offset` by treating them as the remaining dark members of the now-verified signed-additive masked-materializer subfamily and comparing them against the newly anchored slot-`0x12` caller pattern.
|
||||
11. Tighten the newly surfaced higher-slot wrapper ladder around `0005:3115..31da`, especially the two slot-`0x12` caller sites at `0005:1776` / `0005:1945` and the slot-`0x10` guarded callsite, so any future promotion to `leaveFastArea` / `func11|cast` / `justMoved` / `AvatarStoleSomething` / `animGetHit` is driven by binary caller behavior rather than by external tables alone.
|
||||
12. Tighten the outward caller chains around the renamed seg006 masked helpers `entity_vm_context_try_create_mask_0008_slot30_with_offset` (`0006:0ba4`) and `entity_vm_context_try_create_mask_0010_slot08_with_offset_if_ready` (`0006:108c`) so the local state-selector lane and the adjacent class-linked value family can be tied back to concrete gameplay subsystems rather than only to class-detail fields.
|
||||
13. Tighten the paired-file-family reading of the seg070 twin loops at `0009:67b6` and `0009:6916` by recovering which temporary buffer and record schema each family populates behind `entity_vm_runtime_owner_resource_create`.
|
||||
14. Promote additional ledger rows where the current docs already justify `Foothold`, `Partial`, or `Deep`.
|
||||
15. If the VM lane stalls again, revisit `000e:ffb0` from the now-verified `00db/00dc` caller windows and try to recover an adjacent non-overlapped helper before attempting any boundary repair.
|
||||
16. If the immortality lane is revisited, stay focused on `NPCTRIG` slot `0x0a` first, with slot `0x20` still treated as the typed/setup companion and `EVENT` only as the generic hub baseline; the three currently recovered direct `0005:295f` caller families are now all closed and comment-backed in the live NE program at `10f0:02d9`, `10f0:0379`, `10f0:03c3`, `10f0:03e5`, `1128:0ff0`, and `1138:1384`, so the next defensible step is an earlier producer that assigns subtype `0x20b/0x20c` into field `+0x3c` or otherwise chooses the owner-loaded class family before these generic damage consumers run.
|
||||
17. Use the new Pentagram-derived parser proof of concept as the first tooling bridge for raw class/slot bodies: extend opcode coverage conservatively, emit IR v1 artifacts, and only then prototype a Ghidra-side annotation importer against compiled anchors like `000d:51fd`, `000d:5572`, `000d:46ec`, `000d:22bc`, and `000d:ebe3`.
|
||||
10. Recover the real upstream caller/selector path into `entity_vm_opcode_sequence_run`, most likely by finding the first non-recursive `0x6714` context-method caller or vtable dispatch site rather than by repeating raw xref queries that still return no direct edges.
|
||||
11. Recover real caller roles for `entity_vm_context_try_create_mask_0400_slot0a_with_offset` and `entity_vm_context_try_create_mask_0800_slot0b_with_offset` by treating them as the remaining dark members of the now-verified signed-additive masked-materializer subfamily and comparing them against the newly anchored slot-`0x12` caller pattern.
|
||||
12. Tighten the newly surfaced higher-slot wrapper ladder around `0005:3115..31da`, especially the two slot-`0x12` caller sites at `0005:1776` / `0005:1945` and the slot-`0x10` guarded callsite, so any future promotion to `leaveFastArea` / `func11|cast` / `justMoved` / `AvatarStoleSomething` / `animGetHit` is driven by binary caller behavior rather than by external tables alone.
|
||||
13. Tighten the outward caller chains around the renamed seg006 masked helpers `entity_vm_context_try_create_mask_0008_slot30_with_offset` (`0006:0ba4`) and `entity_vm_context_try_create_mask_0010_slot08_with_offset_if_ready` (`0006:108c`) so the local state-selector lane and the adjacent class-linked value family can be tied back to concrete gameplay subsystems rather than only to class-detail fields.
|
||||
14. Tighten the paired-file-family reading of the seg070 twin loops at `0009:67b6` and `0009:6916` by recovering which temporary buffer and record schema each family populates behind `entity_vm_runtime_owner_resource_create`.
|
||||
15. Promote additional ledger rows where the current docs already justify `Foothold`, `Partial`, or `Deep`.
|
||||
16. If the VM lane stalls again, revisit `000e:ffb0` from the now-verified `00db/00dc` caller windows and try to recover an adjacent non-overlapped helper before attempting any boundary repair.
|
||||
17. If the immortality lane is revisited, stay focused on `NPCTRIG` slot `0x0a` first, with slot `0x20` still treated as the typed/setup companion and `EVENT` only as the generic hub baseline; the three currently recovered direct `0005:295f` caller families are now all closed and comment-backed in the live NE program at `10f0:02d9`, `10f0:0379`, `10f0:03c3`, `10f0:03e5`, `1128:0ff0`, and `1138:1384`, so the next defensible step is an earlier producer that assigns subtype `0x20b/0x20c` into field `+0x3c` or otherwise chooses the owner-loaded class family before these generic damage consumers run.
|
||||
18. Use the new Pentagram-derived parser proof of concept as the first tooling bridge for raw class/slot bodies: extend opcode coverage conservatively, emit IR v1 artifacts, and only then prototype a Ghidra-side annotation importer against compiled anchors like `000d:51fd`, `000d:5572`, `000d:46ec`, `000d:22bc`, and `000d:ebe3`.
|
||||
|
||||
## Remaining Work To Reach A Reasonably Complete Decompilation State
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue