Crusader_Decomp/docs/remorse-first-class-authoring-checklist.md
2026-04-05 18:27:09 +02:00

139 lines
No EOL
5.2 KiB
Markdown

# Remorse First Class-Authoring Checklist
## Purpose
This note turns the current class-lift preparation into a concrete execution checklist for the first real Ghidra/MCP authoring batch.
It is intentionally operational. The goal is to remove startup cost once the necessary MCP class/vtable/datatype tools exist.
## Recommended First Pilot Order
Current best pilot ranking:
1. `EntityDispatchEntry`
2. `SpriteNode`
3. `EntityVmOwnerResource`
Why this order:
- `EntityDispatchEntry` has strong ctor/release and field-group evidence
- `SpriteNode` has a compact, visible virtual surface
- `EntityVmOwnerResource` is structurally bounded but still slightly more loader-schema-sensitive
## Batch 0: Preconditions
Before touching class ownership in Ghidra:
1. re-read [docs/remorse-class-lift-index.md](docs/remorse-class-lift-index.md)
2. re-read the target family note
3. confirm the ABI note and compatibility-header draft are still aligned with the intended source track
4. confirm the MCP tool surface actually supports namespace/class creation, datatype authoring, and method ownership changes
Do not start with authoring if any of those are still missing.
## Batch 1: Authoring Rules
These rules should hold for the first pilot family regardless of which family is chosen:
1. move only strongly owned methods first
2. preserve raw slot order in provisional vtables
3. keep uncertain fields explicit as padding or unknown words/bytes
4. prefer conservative owner names over polished but speculative subsystem names
5. add provenance comments when a layout or slot label is imported from an earlier note rather than re-derived in-session
## Pilot A: `EntityDispatchEntry`
Use [docs/entity-dispatch-entry-class-layout.md](docs/entity-dispatch-entry-class-layout.md) as the source note.
### Minimum Ghidra/MCP deliverables
1. create owner namespace/class for the base family
2. create provisional instance struct for the base layout
3. create provisional vtable datatype with stable known slots only
4. move base ctor/release methods under that owner
5. keep subtype/overlay-specific methods outside the base owner until the split is tighter
### First methods to move
- base ctor at `0008:ba00`
- release/destroy surface at `0008:dbec`
- runtime-state init/release pair `000d:7e00` / `000d:8078` only if the owner relationship is still judged direct in-session
### Fields that should stay visible immediately
- type and subtype-related words near `+0x04/+0x06/+0x08`
- active/hold/runtime flags around `+0x16/+0x18`
- runtime-state and paired resource lanes around `+0x3c/+0x40`
### Things to avoid in the first pass
- flattening every derived constructor into one base class
- forcing final names for every slot in the vtable
- pretending all runtime-state fields belong to the same subtype
## Pilot B: `SpriteNode`
Use [docs/sprite-node-class-layout.md](docs/sprite-node-class-layout.md) as the source note.
### Minimum Ghidra/MCP deliverables
1. create owner namespace/class for `SpriteNode`
2. create provisional vtable with only the slot order and best current role labels
3. move destructor and event-dispatch surface under that owner
4. create instance struct with the known layout anchors and visible unknown regions
### First methods to move
- `000b:326e sprite_node_destroy`
- `000b:3ab2 sprite_node_dispatch_event`
- `000b:3380 sprite_node_is_dirty`
- `000b:33a6 sprite_node_mark_dirty`
### Things to avoid in the first pass
- pushing traversal helpers into the class just because they walk the tree
- overcommitting to child/sibling field semantics beyond the already-noted anchors
## Pilot C: `EntityVmOwnerResource`
Use [docs/entity-vm-runtime-owner-resource-layout.md](docs/entity-vm-runtime-owner-resource-layout.md) as the source note.
### Minimum Ghidra/MCP deliverables
1. create helper class owner
2. create compact helper instance struct
3. create provisional method table for the `+0x04` and `+0x0c` helper callbacks
4. move create/destroy pair under that owner
### Things to avoid in the first pass
- baking in final file-family schema labels
- collapsing the helper into the runtime object as anonymous fields
## Source-Emission Readiness Gate
Do not emit the first C++ skeleton immediately after Ghidra authoring.
Only emit when all of these are true:
1. owner namespace/class exists
2. provisional instance struct exists
3. provisional vtable exists when relevant
4. top 3-5 strongly owned methods are moved
5. unresolved fields remain explicit instead of silently renamed away
6. Track A versus Track B assumptions are recorded for that family
## Success Criteria For The First Real Batch
The first class-authoring batch is successful if:
1. one family becomes visibly easier to navigate in Ghidra
2. method ownership is improved without speculative over-grouping
3. instance layout is more explicit than raw offset math
4. the result can drive one hand-maintained C++ header/source skeleton with the compatibility layer
## Bottom Line
The first class-authoring batch should be judged by structural clarity, not by how polished or object-oriented the output looks.
`EntityDispatchEntry` remains the best first pilot because it offers the highest ratio of stable object evidence to remaining subtype ambiguity.