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

5.2 KiB

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.

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
  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 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 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 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.