# Remorse C++ Compatibility Header Draft ## Purpose This note defines the minimum compatibility/support layer that future hand-maintained Remorse C++ skeletons should target. It is not a final header and it is not a compiler lock-in decision. It is a draft contract so early class-emission work does not silently drift into host-only modern C++ assumptions. This note should stay paired with [docs/remorse-rebuild-abi-notes.md](docs/remorse-rebuild-abi-notes.md). ## Why This Layer Is Needed Current rebuild notes already make three constraints clear: - Track A original-style executable reconstruction remains in scope - the executable is shaped by segmented pointers and far-call conventions - host compilation success is not enough if layout, slot order, or call shape drift That means the first C++ skeletons should compile against a compatibility layer that makes these constraints explicit even before the exact compiler/toolchain decision is closed. ## Minimum Header Categories ### 1. Exact-width integer aliases Needed because: - field maps are being recovered by offset - slot/value and save/load structures use exact-width arithmetic - sign extension versus zero extension matters repeatedly in the current notes Current draft surface: ```cpp using u8 = std::uint8_t; using s8 = std::int8_t; using u16 = std::uint16_t; using s16 = std::int16_t; using u32 = std::uint32_t; using s32 = std::int32_t; ``` ### 2. Packing controls Needed because: - object and save-state layouts are currently tracked by exact offsets - future vtable-bearing structs must not silently pick host-default padding Current draft surface: ```cpp #define CR_PACK_PUSH_1 #define CR_PACK_POP #define CR_PACKED ``` The final spelling can change per compiler. The important part is that early source slices already depend on named packing controls rather than ad hoc pragmas in every file. ### 3. Calling-convention markers Needed because: - later method and helper promotion will need to distinguish ordinary helpers from call-shape-sensitive surfaces - Track A may need explicit far/near or compiler-family-specific conventions Current draft surface: ```cpp #define CR_CDECL #define CR_STDCALL #define CR_THISCALL #define CR_FARCALL ``` `CR_FARCALL` is intentionally placeholder-level today. The current value is in making far-call-sensitive surfaces visible in source, not in pretending the final compiler spelling is already known. ### 4. Segmented pointer helper types Needed because: - several notes still preserve segment:offset provenance directly - owner-loaded VM source pairs and some callback/resource lanes should not be flattened too early Current draft surface: ```cpp struct FarPtr16 { u16 offset; u16 segment; }; template struct FarPtr { u16 offset; u16 segment; }; ``` Current rule: - use these first as evidence-preserving placeholders, not as proof that final emitted code must literally use this exact host representation everywhere. ### 5. Vtable and slot-order helpers Needed because: - current family notes still treat slot order as evidence, not cosmetics - later MCP or hand-authored promotion should preserve raw order even when names are provisional Current draft surface: ```cpp #define CR_VSLOT(index) ``` This can stay documentation-only at first if needed. The point is to keep raw slot numbering visible in provisional class headers. ## First Skeleton Rules When the first class family is emitted to source, the compatibility header should enforce these rules: 1. every field uses exact-width aliases 2. every packed layout is explicit 3. every unresolved far/segment-sensitive pointer uses a named placeholder type 4. every provisional virtual surface keeps raw slot order visible 5. Track A-only assumptions are marked instead of being silently baked into Track B-style cleanup ## Families Most Likely To Need This Immediately 1. `EntityDispatchEntry` 2. `SpriteNode` 3. `EntityVmRuntime` 4. `EntityVmOwnerResource` 5. `EntityVmContext` `Entity` will also need it, but its family split is large enough that it should probably not be the first source-emission pilot. ## What This Draft Deliberately Avoids - picking one final compiler family now - pretending near/far semantics are already solved - turning unresolved imported-runtime calls into polished modern interfaces - flattening segment:offset provenance into generic host pointers too early ## Proposed Next Step Once the first pilot family is chosen, convert this note into a real minimal header with: - exact-width aliases - packing markers - calling-convention placeholders - one segmented-pointer placeholder type - one comment block explaining Track A versus Track B expectations ## Bottom Line The compatibility header should exist before the first C++ skeleton is emitted, not after. That keeps early source work honest and preserves the option of an original-style rebuild instead of quietly drifting into a pure host-port codebase.