Crusader_Decomp/docs/ne-hole-filling-priorities.md

220 lines
No EOL
16 KiB
Markdown

# CRUSADER.EXE Hole-Filling Priorities From CRUSADER-RAW.EXE
## Purpose
This note tracks the highest-value places where the NE-loaded `CRUSADER.EXE` project is still materially unclear, but the older `CRUSADER-RAW.EXE` project already holds enough verified structure to close the gap.
The goal is not to duplicate the raw notes. The goal is to rank the NE-side holes that are most likely to collapse quickly once the raw-side evidence is ported carefully.
Evidence used here:
- live Ghidra MCP checks in the open `CRUSADER.EXE` session
- `plan-mid.md`
- `crusader_segment_coverage_ledger.csv`
- `docs/raw-porting-progress.md`
- `docs/raw-0007-rendering.md`
- `docs/raw-0008-000c.md`
- `docs/raw-000a-000d.md`
- `docs/raw-000e.md`
- `docs/crusader-disasm-reference.md`
## Priority 1: VM / USECODE Selector And Owner-Loaded Runtime Lane
### Why it is still unclear in `CRUSADER.EXE`
- The NE project already carries the main structural names, but the actual upstream selector into the VM sequencer is still unresolved.
- The dark wrappers around slot `0x0a` / `0x0b` are named structurally, not behaviorally.
- The owner-resource helper is partially understood, but the exact class-family selection and configured owner-file naming are still open.
- Coverage ledger state is still only `Partial` for segments `133`, `134`, and `135`.
### What the raw project already knows
- `000d:463a` is now a verified generic masked-create hub: `entity_vm_context_try_create_masked_for_entity`.
- `000d:45c5` is a three-way category mapper: `entity_vm_slot_index_from_entity`.
- `000d:4c99` and `000d:7000` classify the runtime bootstrap and owner-resource creation path.
- `000d:ebe3` is a verified ordered opcode sequencer: `entity_vm_opcode_sequence_run`.
- `0005:2c35` is already narrowed to `entity_vm_context_try_create_mask_0400_slot0a_with_offset`, but its outward caller role is still dark.
- The raw-side docs also already carry the exact `NPCTRIG` / `EVENT` body-window fits, referent-registry model, and the current selector blocker.
- `docs/crusader-disasm-reference.md` already identifies the best auxiliary corpus for this lane: `usecode_opcodes.txt`, `map-item-dump.txt`, `shapedata_more_complete.txt`, and the `unkcoffs/` dumps.
### Porting work that should close the gap
- Port the raw-side selector, context, and owner-loader comments into the NE project at the same segment:offset anchors.
- Keep the slot-`0x0a` / slot-`0x0b` wrappers conservative until real caller roles are recovered.
- Use the external opcode list and map/shape corpus only as hint generators while reconciling the live NE caller path.
- Prioritize recovery of the first caller that turns the category spans from `000d:45c5` into a concrete class-family choice.
### Live anchors in the open NE project
- `000d:45c5` -> `entity_vm_slot_index_from_entity`
- `000d:463a` -> `entity_vm_context_try_create_masked_for_entity`
- `000d:4c99` -> `entity_vm_runtime_create`
- `000d:ebe3` -> `entity_vm_opcode_sequence_run`
- `0005:2c35` -> `entity_vm_context_try_create_mask_0400_slot0a_with_offset`
### Latest verified NE pass
- `0005:295f` is now the only recovered non-hub consumer of `entity_vm_slot_index_from_entity` in the open NE session. It recomputes the slot index, tests owner-row bit `0x0040` directly, exposes that result to the caller, and only then optionally calls `entity_vm_context_try_create_masked_for_entity` with slot `0x06` and mask `0x0040`.
- The direct NE callers currently recovered for `0005:295f` are still only `0006:43c3`, `0006:c5f0`, and `0007:3584`, but they are now all structurally classified in the live NE session instead of only enumerated as open caller families.
- The first anchored caller family is now structurally classified in the live NE session. Repaired wrapper `0006:4379` is a seg031 dispatch-entry subtype gate over objects built by `0006:42d9`: event type `0x236`, source type `8`, subtype/tag at `+0x3c`, dword payload/source far pointer at `+0x32`, and aux words at `+0x36/+0x38`.
- In that wrapper, subtype `0x20c` at `0006:43c3` routes into `0005:295f`, while nearby sibling subtype `0x20b` at `0006:43e5` routes into `0005:2918` (`slot 0x05` / `mask 0x0020`) using the same `+0x36/+0x38` aux pair. The split is therefore local to one dispatch-entry family, not a direct compiled `NPCTRIG` / `EVENT` class-family selector by itself.
- The `0006:43c3` lane now shows where the owner-row bit-`0x0040` probe is consumed locally: inside a subtype-`0x20c` dispatch-entry object rather than at a generic descriptor-choice site. That improves caller provenance for `0005:295f`, but it still does not prove which owner-loaded class family seeded the later VM data.
- The second direct caller family is now closed too. Old `0006:c5f0` lands at live call site `1128:0ff0` inside `Item_ReceiveHit`, where the non-NPC item path calls `Item_GetDamaged` with hitter sentinel `0x4000`, packed damage `(damagetype << 8) | damage_lo`, and a local flag-out byte that records the returned owner-row bit-`0x0040` capability before the local destruction / impact follow-up.
- The third direct caller family is now closed too. Old `0007:3584` lands at live call site `1138:1384` inside `SuperSprite_HitAndFinish`, where the non-NPC collision lane probes `Item_GetDamaged` with hitter sentinel `0x4000` and packed damage `(firetype << 8) | damage`; only when that flag-out byte stays clear and the target is not fixed does the lane fall through into the local `Item_ReceiveHit` knockback path.
- `0005:2c35` remains outward-dark in the current NE session: instruction search still shows no recovered code or data xrefs, and its proven local role is still only `sign-extended additive word -> slot 0x0a / mask 0x0400 -> generic masked hub`.
- The live `CRUSADER.EXE` integration batch is now extended for this lane. Comment-backed anchors were already present at `1420:0dc5` (`Item_GetUsecodeClassId`), `1420:0e3a` (`Usecode_ItemCallEvent`), `10a0:2718` (`Item_Hit`), `10a0:275f` (`Item_GetDamaged`), `10f0:02d9` (`StorageDataProcess_Create`), and `10f0:0379` (`StorageDataProcess_Run`), with branch comments at `10f0:03c3` and `10f0:03e5` preserving the verified `0x20c` / `0x20b` split; new live comments now also anchor the remaining direct caller sites at `1128:0ff0` and `1138:1384`.
- Result of this pass: all currently recovered direct `0005:295f` caller families are now closed, but the compiled-side selector evidence still bottoms out at subtype-gated dispatch or generic gameplay damage consumers plus owner-row capability bits, not a concrete `NPCTRIG` / `EVENT` class-family choice. The next defensible NE step is therefore 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.
## Priority 2: Rendering / Camera / Tile-Visibility / Watch-Controller Lane
### Why it is still unclear in `CRUSADER.EXE`
- The raw rendering/camera work is one of the strongest finished structural maps, but the NE ledger still shows only `Partial` coverage for the watch-controller lane (`seg049`) and `None` for several related render-heavy segments.
- The exact controller-versus-watched-entity ownership label around `0x2bd8` is still open.
- The NE side still does not have the same whole-lane readability that the raw `0007` rendering notes already provide.
### What the raw project already knows
- The raw notes already define the draw-list node format, tile visibility pipeline, screen/global state, scroll/camera globals, and the watch-controller family.
- `0007:ba00`, `0007:ba45`, and `0007:baea` already have conservative structural names and caller contracts in the raw project.
- The coordinate-transform lane is also already documented in a way that can be reused safely for the NE segments that call into it.
### Porting work that should close the gap
- Port the controller/object comments around `0x2bd8`, `0x2be0`, and the scroll globals before attempting any more aggressive renames.
- Carry the draw-list, tile-grid, and viewport/global names into the NE lane where the same DS globals and call shapes match.
- Use `map-item-dump.txt` and `shapedata_more_complete.txt` to explain object-heavy camera/trigger placements only after the binary side matches the raw lane.
### Evidence anchors
- Ledger: `seg049` = `Partial`, `seg053` = `None`, multiple surrounding render-heavy segments remain `None`
- Raw-side anchor doc: `docs/raw-0007-rendering.md`
## Priority 3: Startup / Display Transition And Active-Hold Lane
### Why it is still unclear in `CRUSADER.EXE`
- The NE startup/display lane is structurally strong, but one of the key bodies is still overlap-damaged.
- `000c:db68` currently resolves to `cursor_nav_update_and_dispatch`, but boundary analysis still shows an obviously oversized body spanning `000c:5b68 - 000c:ff1c`.
- The renderer-pair role at `0x8c5c/0x8c60` and the exact higher-level label for some preset paths remain open.
### What the raw project already knows
- The raw project already separates the seg126/127/136/137/138 transition helpers into a usable startup/display model.
- The `0x6828 + 0x40` borrowed hold byte is already separated from the seg108-local `0x4f38` bit-`0x40` lane.
- The fade-controller behavior and the shared break/hold state around `0x31a2` are already documented tightly enough to guide NE cleanup.
### Porting work that should close the gap
- Use the raw-side boundary and caller notes to split `000c:db68` back into the real local helper bodies before promoting any more labels.
- Port the hold-token provenance and the seg108-versus-seg136 separation comments into the NE database.
- Keep the remaining renderer-pair naming conservative until the overlap is repaired.
### Live anchors in the open NE project
- `000c:db68` -> `cursor_nav_update_and_dispatch`
- Boundary analysis for `000c:db40..000c:dc40` still reports `cursor_nav_update_and_dispatch @ 000c:db68 body 000c:5b68 - 000c:ff1c`
- Ledger: `seg126`, `seg127`, `seg136`, `seg137`, `seg138` are all only `Partial`
## Priority 4: `0x4588` Callback / Allocator / Palette Cleanup Lane
### Why it is still unclear in `CRUSADER.EXE`
- Many helpers in this lane are already named in the NE project, but the actual subsystem identity of the `0x4588` object is still unresolved.
- The same blocker is repeated across the ledger for segments `80`, `82`, `91`, `95`, and `138`, which means the NE project has structure but still lacks the final behavioral classification.
### What the raw project already knows
- The raw project already has a stable lifecycle map for `runtime_callback_object_init_once`, `runtime_callback_object_teardown_once`, `allocator_phase_finalize_pass`, and `entity_cleanup_resources_and_dispatch`.
- The raw notes already constrain the video-state snapshot pair, one-time guards, vtable call slots, emitted payload pairs, and the relationship to the watch-controller release path.
### Porting work that should close the gap
- Port field-level comments around `0x4588`, `0x4590`, `0x4594`, `0x4595`, `0x45a6`, and the emitted payload pairs before attempting any subsystem rename.
- Reconcile the raw callback emissions with the NE caller windows in segments `91`, `95`, and `138`.
- Only promote a behavior-level subsystem name once those emitted payload pairs and caller families converge in the NE project too.
### Live anchors in the open NE project
- `000a:4913` -> `runtime_callback_object_init_once`
- `0009:b1c3` -> `allocator_phase_finalize_pass`
- `000d:9afd` -> `entity_cleanup_resources_and_dispatch`
## Priority 5: Parser / RIFF / Animation Video-Subframe Lane
### Why it is still unclear in `CRUSADER.EXE`
- The main parser and animation entrypoints are already named in the NE project, but the surrounding segment coverage is still weak.
- The ledger still shows `None` for the raw-`000e`-mapped segments `99` through `103`.
- `000e:ffb0` is still only a positional function object and remains overlap-damaged.
### What the raw project already knows
- The raw notes already define the parser cluster, RIFF chunk matching, animation ring-buffer model, and the audio/video split.
- The raw-side caller proof already ties `000e:ffb0` to the `00db` / `00dc` video-frame lane paired with `anim_load_audio_frame`.
- The raw notes also already separate the text-oriented parser usage from the binary owner-loaded USECODE lane.
### Porting work that should close the gap
- Port the parser and animation comments into the NE segment windows that still show no formal coverage.
- Keep `000e:ffb0` conservative, but import the raw-side comment that it is the unresolved video-side subframe loader for the `00db` / `00dc` chunk lane.
- Normalize the segment-to-topic mapping for the `000e` range in the NE coverage ledger once those comments are in place.
### Live anchors in the open NE project
- `000e:2104` -> `animation_start`
- `000e:3639` -> `record_table_parse_buffer`
- `000e:ffb0` -> `FUN_000e_ffb0`
- Boundary analysis for `000e:ff90..000f:00f0` still reports `FUN_000e_ffb0 @ 000e:ffb0 body 000e:ffb0 - 000f:00e0`
## Priority 6: Gameplay / Input / Projectile Expansion Into Adjacent NE Lanes
### Why it is still unclear in `CRUSADER.EXE`
- Segment `1` itself is already deep, but the adjacent event/dispatch and targeting lanes are not equally complete.
- The ledger still shows only `Partial` coverage for `seg021` and `seg043` even though the raw project already holds stronger gameplay-side anchors.
- The old disasm corpus has shape and event-code evidence that can explain object-heavy gameplay lanes, but that evidence has not yet been turned into a disciplined NE crosswalk.
### What the raw project already knows
- Verified raw imports already exist for `shot_entity_alloc`, `projectile_update_tick`, and the rest of the main projectile chain.
- `seg021` already has a verified direct raw import anchor via `entity_count_by_type_a`.
- The external corpus adds key/event notes such as `CTRL-Q = 0x410` and map-backed shape examples like `STEAM2` and `SnapEgg`.
- The raw side also already narrowed the seg043 start-of-segment hole enough to reject the earlier bad mapping.
### Porting work that should close the gap
- Extend from the already-verified gameplay names into adjacent NE dispatch/targeting callers only when the segment:offset and caller role match directly.
- Build one conservative shape-id / map-placement crosswalk for trigger-heavy or object-heavy gameplay lanes before promoting new names.
- Use the old key/event notes as lead generation only, not as direct rename authority.
### Live anchors in the open NE project
- `0007:28ce` -> `shot_entity_alloc`
- `0007:371d` -> `projectile_update_tick`
- `0007:5a00` has no current symbol
- Boundary analysis for `0007:59e0..0007:5b40` still reports `0007:5a00` as a candidate entry and keeps the earlier rejected mapping explicitly closed
## Secondary Structural Gaps To Keep On The Tracker
These are real NE holes, but they are weaker `old -> new` closure candidates than the priorities above because the raw-side model is still not strong enough to drive safe naming by itself.
### `000b:2e00`
- Still a high-traffic gap in the NE project.
- Live symbol lookup returns no symbol at `000b:2e00`.
- Boundary analysis for `000b:2de0..000b:3050` shows a missing top-level entry at `000b:2e00` plus several later artificial subfunctions.
- Keep it on the list, but do not treat it as the first raw-to-NE porting target.
## Immediate Actions Justified Now
- Create and maintain this tracker document.
- Use it as the ranked starting point for the first focused `CRUSADER.EXE` porting batch.
- Avoid immediate new Ghidra renames in the listed holes unless a pass first repairs the overlapping function objects or recovers the missing callers.
- Conservative comments are justified before renames in the VM, transition, and animation lanes because the remaining uncertainty is mostly about caller provenance and boundaries, not about the already-known local contracts.
## Progress Estimate Impact
This note still does not justify a headline percentage change by itself.
The `plan-mid.md` progress estimates should stay unchanged until one of these prioritized NE passes produces verified new symbol, boundary, or ledger promotions beyond this local caller-family classification.