962e55b43d30bbdac741d781dcf6ca6a3fcdc112
The retained-mode "2nd CG renders off-screen" bug: GfxState conflated two distinct native structures. It assigned a fabricated AcquireSlot() slot on every GetOrCreate (called by all geometry/draw ops) and returned it from QuerySlot (op 0x215). But Ghidra (gfx_op_0x215_register_query @0x42a0b0 / gfx_op_0x1a2_registry_insert @0x42d360) shows 0x215 does map.find(handle) over a registry populated ONLY by op 0x1a2 -- it never allocates a slot. So a CG handle (never 0x1a2-registered) read back as "existing", took the existing branch of label_12649, ran get-texture-size on the wrong slot (0), got size 0, and computed dst = pos(0,0) - (w/2,h) = (-400,-600) -> off-screen. The real engine returns -1 -> the fresh branch -> anchor from the INIT2 arrays -> dst=(0,0). Fix: GfxState keeps a separate _registry (HashSet) populated only by Register() (op 0x1a2); QuerySlot returns the handle if registered else -1, and no longer consults the geometry store or invents slots. Drop AcquireSlot / GfxObject.Slot / the free-list. Verified: Age.Cli gfx --boot SC0000.BIN -> all event CGs dst=(0,0), zero (-400,-600) draws; Godot --boot pages 1/2/4 render opening CGs full-screen; engine 44/44; sweep parity 284 exit / 13 STEP-LIMIT unchanged. Docs: engine-re.md (query-registry-vs-geometry-store section), opcodes.toml 0x1a2/0x215 rebuilt; Ghidra helpers gfx_registry_map_find/hash_insert annotated + saved. Tests rewritten to the native contract. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Description
Open Maid Engine v0.3.3
Latest
Languages
C#
60.4%
Python
36.8%
C
1.3%
Shell
1%
PowerShell
0.5%