Porting Test Drive II from SNES to PC, Part 7: Making frame 998 a real ownership anchor
The previous checkpoint extended live late-window producer tracing through frame 994.
That was useful, but it still left one soft spot in the story:
frame 998 was documented as part of the same 01:9FE5 callback family, and the repo already had a direct bridge-extracted block for 998..1005, but the ownership evidence at the start of that block was still indirect.
It was mostly a continuity claim:
- the earlier late-window probes stayed inside
01:9FE5 - the direct bridge-extracted
998..1005block already existed - the bridge-visible docs already said the renderer stayed close there
That is good context. It is not the same thing as a live ownership proof on 998 itself.
So this checkpoint did the smallest thing that closes that gap:
it turned frame 998 into a real producer-trace-backed visual contract.
Why 998 matters
998 is not just “the next frame after 994.”
It is the start of the first direct bridge-extracted continuation block:
998..1005
That makes it the first place where the repo can say, with direct live evidence, that the ownership model from the earlier late attract window really carries into the next extracted state block instead of only appearing to do so.
That distinction matters because the archaeology lane is no longer asking only:
- does the frame look close?
It is asking:
- is the same producer family still active?
- do the write domains change?
- does the visible overlay change while ownership stays stable?
Those are stronger questions.
The checkpoint
The workflow stayed intentionally small:
- extract frame
998 - build a design pack
- run a bounded write-point probe for
994..998 - merge that probe into a visual contract
The exact commands were:
MESEN_RELEASE_DIR=/home/nivando-soares/Mesen2/bin/linux-x64/Release \
make -C tools mesen-design-pack MESEN_FRAME=998
MESEN_RELEASE_DIR=/home/nivando-soares/Mesen2/bin/linux-x64/Release \
MESEN_TIMEOUT_SECONDS=120 \
TD2_BOOT_PROBE_OUTPUT_PREFIX=tools/out/visual_contract_probe_998_live/td2_boot_probe \
TD2_BOOT_PROBE_TOTAL_FRAMES=999 \
TD2_BOOT_PROBE_TRACE_START_FRAME=994 \
TD2_BOOT_PROBE_TRACE_END_FRAME=998 \
TD2_BOOT_PROBE_TRACE_WRITE_POINTS='objsel=00:2101,oamaddl=00:2102,oamaddh=00:2103,oamdata=00:2104,vmaddl=00:2116,vmaddh=00:2117,vmdatal=00:2118,vmdatah=00:2119,cgadd=00:2121,cgdata=00:2122' \
TD2_BOOT_PROBE_WRITE_POINT_MAX_HITS=8192 \
./validation/run_mesen_probe_boot.sh
python3 tools/build_mesen_visual_contract.py \
tools/out/design_frame998 \
tools/out/visual_contract_frame998_live_probe.json \
--probe-json tools/out/visual_contract_probe_998_live/td2_boot_probe.json
The promoted artifacts are now committed:
tools/out/visual_contract_probe_998_live/td2_boot_probe.jsontools/out/visual_contract_frame998_live_probe.json
What the trace showed
The probe recorded:
-
4020write hits -
0drops - exact trace window
994..998
The important part is not just the raw count. It is that the domain split does not change from the previous late-window proof.
The active domains are still only:
- OAM:
2730writes across994..998 - VRAM:
1290writes across994..998
The dominant callsites remain the same:
- OAM:
00:824Fand00:8257 - VRAM:
00:81E5and00:81F2
And the callback pair still does not move:
- active main callback:
01:9FE5 - active IRQ callback:
00:835F
That is the key result.
998 does not open a new ownership regime. It confirms that the earlier late-window regime survives into the start of the direct bridge-extracted block.
What changed anyway
Ownership stayed stable, but the frame did not stay visually static.
The fresh design pack for 998 reports:
-
32visible sprites
That matters because frame 994 had 19 visible sprites under the same ownership family.
So from 994 to 998, the useful reading is:
- producer traffic stays flat
- visible overlay expands
- callback family stays the same
That is the kind of separation the repo needed to make explicit.
Without a producer-trace-backed contract, that kind of change is easy to misread as a code-path change. At 998, the repo can now say that it is not.
Validation
The fresh Mesen frame was first checked against the local screenshot-backed capture:
python3 tools/compare_frames.py \
tools/out/intro_loop_frame_00998_frame.png \
tools/out/mesen_frame998/main_visible.ppm \
--diff-out tools/out/mesen_frame998_vs_intro998_diff.ppm
That landed at:
-
3119mismatched pixels (5.439104%)
That is not a solved screenshot-exact frame. But this checkpoint was not trying to prove that.
The more relevant bounded validation was to check the extracted frame against the repo's stable Python mode7-ppu surface:
python3 tools/render_mesen_snes_bg.py \
tools/out/mesen_frame998/vram.bin \
tools/out/mesen_frame998/cgram.bin \
tools/out/mesen_frame998/ppu_state.json \
tools/out/mesen_frame998_mode7ppu.ppm \
--oam tools/out/mesen_frame998/oam.bin \
--obj-renderer mode7-ppu \
--json-out tools/out/mesen_frame998_mode7ppu.json
python3 tools/compare_frames.py \
tools/out/mesen_frame998/main_visible.ppm \
tools/out/mesen_frame998_mode7ppu.ppm \
--diff-out tools/out/mesen_frame998_mode7ppu_vs_mesen998_diff.ppm
That compare landed at:
-
4mismatched pixels (0.006975%)
This is exactly the kind of validation that matters for this lane.
It says the frame is still sitting on the same practical bridge-visible render surface the repo already expected for the 998..1005 block.
Why this checkpoint is better than skipping to 1005
It would have been tempting to jump straight to 1005, because that closes the first direct bridge-extracted block.
But that would have skipped the more important question:
does the ownership model actually survive the handoff into that block?
Now the answer is yes, and it is backed by a live trace on the first frame of the block itself.
That makes 998 a stronger anchor than just “the first frame in a sequence we already extracted.”
It is now:
- a direct bridge-extracted frame
- a live producer-trace-backed visual contract
- a continuity proof for the same late
01:9FE5ownership family
That is enough to move the lane forward without pretending the final screenshot gap is solved.
What comes next
The next step is now obvious:
- extend the same live ownership surface to frame
1005
That closes the first direct bridge-extracted 998..1005 block under the same callback family and should say whether the ownership story is still flat across the whole block or whether a later internal split appears.
The headline for this checkpoint is simple:
frame 998 is no longer only the documented start of a direct bridge-extracted block. It is now a real ownership anchor.
Top comments (0)