139 lines
5.2 KiB
Markdown
139 lines
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.
|