DEV Community

Nivando Soares
Nivando Soares

Posted on

Porting Test Drive II from SNES to PC, Part 20: Closing the 1102..1117 late attract continuation

Porting Test Drive II from SNES to PC, Part 20: Closing the 1102..1117 late attract continuation

The previous checkpoint split the late attract continuation after frame 1093 into real behavior windows.

That was useful, but it still left one important question open:

was the 00:8029 tail still changing internally in ways that explained the renderer gap, or was it already one stable surface with one remaining bug?

This checkpoint answers that more cleanly.

What changed in the pipeline

Two small tooling changes mattered here:

  • the visual-contract builders can now merge a normalized activity trace directly
  • the compare rubric for these late windows is now a dedicated reusable builder instead of a pile of one-off commands

The new helper is:

  • tools/build_mesen_window_compare.py

That matters because the late attract lane can now line up three things in one pass:

  • visible surface
  • callback and activity shape
  • renderer mismatch

The bounded run

I kept the run exactly on the 00:8029 continuation:

  • 1102..1117

The promoted commands were:

python3 tools/build_mesen_visual_contract_range.py \
  tools/out/design_mesen_range_1102_1109_v1 \
  tools/out/visual_contract_range_1102_1109_activity \
  --provenance-json rom_analysis/maps/tilemaps/mesen_range_1102_1109_provenance.jsonc \
  --probe-json tools/out/activity_trace_1094_1117/td2_boot_probe.json \
  --activity-trace-json tools/out/activity_trace_1094_1117/activity_trace.json \
  --clean-out

python3 tools/build_mesen_visual_contract_range.py \
  tools/out/design_mesen_range_1110_1117_v1 \
  tools/out/visual_contract_range_1110_1117_activity \
  --provenance-json rom_analysis/maps/tilemaps/mesen_range_1110_1117_provenance.jsonc \
  --probe-json tools/out/activity_trace_1094_1117/td2_boot_probe.json \
  --activity-trace-json tools/out/activity_trace_1094_1117/activity_trace.json \
  --clean-out

python3 tools/build_mesen_window_compare.py \
  tools/out/post_1093_compare_1102_1117/summary.json \
  tools/out/mesen_range_1102_1109_v1 \
  tools/out/mesen_range_1110_1117_v1 \
  --activity-trace-json tools/out/activity_trace_1094_1117/activity_trace.json \
  --markdown-out tools/out/post_1093_compare_1102_1117/summary.md
Enter fullscreen mode Exit fullscreen mode

What the window looks like now

Across the whole 1102..1117 block, the visible presentation surface stays flat:

  • bgMode = 7
  • main screen layer: bg1
  • visible sprites: 61
  • main callback: 00:8029

That is already useful.

The callback handoff at 1102 is real, but it is not a visible-surface handoff.

What still changes internally

The normalized activity trace still finds one internal boundary:

  • 1102..1113: one per-frame OAM DMA
  • 1114..1117: no OAM DMA

But the rest of the shape stays flat:

  • no direct VRAM/CGRAM writes
  • same Mode 7 event count
  • same Mode 7 write count

So the 1114 boundary is narrower than it first looked.

It is an OAM DMA shutdown, not a larger ownership or state fork.

What the compare summary proved

The export-surface explanation from the previous block survives intact:

  • main_visible.ppm is still the top 224 lines of main.ppm
  • not a different scene export

That holds for every frame 1102..1117.

The more interesting result is the renderer side.

Base render vs main_visible.ppm:

  • 1102: 838 mismatched pixels
  • 1103: 1061
  • 1104: 1798
  • 1105..1117: 2698

Visible-state render vs main_visible.ppm:

  • 1102: 6082
  • 1103: 5958
  • 1104: 6292
  • 1105..1117: 2698

That means the old visible-state substitution problem only survives for:

  • 1102..1104

By 1105, the base and visible-state Mode 7 coefficients already agree.

And from there on, the remaining gap is just one stable plateau:

  • 2698 mismatched pixels

Why this checkpoint matters

This is the important change in reading:

before this checkpoint, the 00:8029 tail still looked like it might hide another ownership or upload transition.

After this checkpoint, the sharper reading is:

  • the whole tail is one stable surface
  • the 1114 OAM DMA shutdown is real but not causal for the compare gap
  • the visible-state Mode 7 disagreement is already gone by 1105
  • the remaining problem is one stable renderer/composition plateau shared by 1105..1117

That is much better than "something still changes later."

Now the next step is narrower and more honest:

find the composition semantics behind that stable 2698-pixel plateau, instead of chasing more hidden uploads or callback forks.

Top comments (0)