<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged retro-engineering</title>
<link>https://coderlegion.com/tag/retro-engineering</link>
<description>Powered by Question2Answer</description>
<item>
<title>Porting Test Drive II from SNES to PC, Part 4: Validation, cleanup, and current blockers</title>
<link>https://coderlegion.com/13287/porting-test-drive-ii-from-snes-to-pc-part-4-validation-cleanup-and-current-blockers</link>
<description>&lt;h2 id=&quot;porting-test-drive-ii-from-snes-to-pc-part-4-validation-cleanup-and-current-blockers&quot;&gt;Porting Test Drive II from SNES to PC, Part 4: Validation, cleanup, and current blockers&lt;/h2&gt;
&lt;p&gt;By the second week of this repo, the technical risk had changed.&lt;/p&gt;
&lt;p&gt;The problem was no longer &quot;we do not have enough scripts.&quot; The problem was &quot;we have enough moving pieces that incorrect progress can look convincing.&quot;&lt;/p&gt;
&lt;p&gt;That is why the March 6 to March 19 history matters so much. This is the phase where &lt;code&gt;asmdump&lt;/code&gt; turns archaeology results into contracts, turns renderer bugs into isolated fixtures, and starts cleaning up its own generated noise.&lt;/p&gt;
&lt;h3 id=&quot;validation-became-executable&quot;&gt;Validation became executable&lt;/h3&gt;
&lt;p&gt;Commit &lt;code&gt;c5ec8be&lt;/code&gt; on 2026-03-06 added the first real validation policy layer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tools/check_regression_gates.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tools/validate_callback_contracts.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;validation/regression_gates_intro.jsonc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rom_analysis/docs/callback_state_contracts.jsonc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rom_analysis/docs/validation_gates.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is a major change in the repo's engineering model.&lt;/p&gt;
&lt;p&gt;Before that point, progress was mostly tracked through:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;rendered outputs&lt;/li&gt;
&lt;li&gt;trace logs&lt;/li&gt;
&lt;li&gt;prose notes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After that point, the repo could encode claims like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;this frame or transition is allowed to drift only within a known bound&lt;/li&gt;
&lt;li&gt;this callback and state tuple must still be true at this checkpoint&lt;/li&gt;
&lt;li&gt;this promoted scene window has a machine-checkable gate&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As of the March 19 roadmap snapshot, the current validation baseline is concrete:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;callback contracts: &lt;code&gt;18/18&lt;/code&gt; pass&lt;/li&gt;
&lt;li&gt;regression gates: &lt;code&gt;6/6&lt;/code&gt; pass&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That does not mean the intro is solved. It means the repo now has a protected floor. Future archaeology and runtime work can move without silently breaking the windows that are already understood.&lt;/p&gt;
&lt;h3 id=&quot;renderer-bugs-got-synthetic-fixtures-instead-of-ad-hoc-screenshots&quot;&gt;Renderer bugs got synthetic fixtures instead of ad hoc screenshots&lt;/h3&gt;
&lt;p&gt;The cleanup commit &lt;code&gt;1663f43&lt;/code&gt; on 2026-03-19 is easy to misread as housekeeping. It is more important than that.&lt;/p&gt;
&lt;p&gt;It added focused renderer checks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tools/check_obj_vertical_flip.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tools/check_bg_layer_priority.py&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Those scripts generate tiny scenes with one narrow purpose:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;prove the non-square vertically mirrored OBJ path&lt;/li&gt;
&lt;li&gt;prove BG4 and tile-priority ordering&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is the right kind of renderer test for this project. Large captured frame windows are useful, but they are bad at isolating a single rule. Small synthetic scenes are much better at answering one question at a time.&lt;/p&gt;
&lt;p&gt;The repo now checks those fixtures across multiple renderers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Python simple path&lt;/li&gt;
&lt;li&gt;Python &lt;code&gt;mode7-ppu&lt;/code&gt; path&lt;/li&gt;
&lt;li&gt;SDL runtime&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is exactly the kind of cross-checking a port project needs when the same scene can be exercised through more than one implementation.&lt;/p&gt;
&lt;h3 id=&quot;cleanup-was-part-of-the-product-work&quot;&gt;Cleanup was part of the product work&lt;/h3&gt;
&lt;p&gt;The current repo state makes the cleanup motivation obvious.&lt;/p&gt;
&lt;p&gt;The worktree already contains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;mutable &lt;code&gt;.mesen-config&lt;/code&gt; outputs&lt;/li&gt;
&lt;li&gt;large &lt;code&gt;tools/out&lt;/code&gt; trees&lt;/li&gt;
&lt;li&gt;generated design packs&lt;/li&gt;
&lt;li&gt;probe logs&lt;/li&gt;
&lt;li&gt;frame dumps&lt;/li&gt;
&lt;li&gt;scratch bridge outputs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Without active cleanup, the difference between a committed result, a disposable intermediate file, and a stale experiment gets blurry fast.&lt;/p&gt;
&lt;p&gt;That is what &lt;code&gt;1663f43&lt;/code&gt; and &lt;code&gt;6076df3&lt;/code&gt; were fixing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;tighter ignore policy&lt;/li&gt;
&lt;li&gt;generated-artifact cleanup targets&lt;/li&gt;
&lt;li&gt;removal of tracked build and cache artifacts&lt;/li&gt;
&lt;li&gt;pressure to remove hard-coded personal paths from promoted scripts&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is not cosmetic. Port work slows down badly when the repo stops making it obvious which artifact is authoritative.&lt;/p&gt;
&lt;p&gt;The current roadmap treats that explicitly as a first-class execution track, alongside the ongoing archaeology lanes. That is the correct call.&lt;/p&gt;
&lt;h3 id=&quot;the-remaining-blocker-is-a-composition-problem-not-a-vague-unknown&quot;&gt;The remaining blocker is a composition problem, not a vague unknown&lt;/h3&gt;
&lt;p&gt;Commit &lt;code&gt;31f3ac7&lt;/code&gt; on 2026-03-19 added &lt;code&gt;tools/analyze_oam_delta.py&lt;/code&gt; and promoted late-intro OAM delta diagnostics into the main workflow.&lt;/p&gt;
&lt;p&gt;That matters because the late intro gap is now described with much better precision.&lt;/p&gt;
&lt;p&gt;The repo's current reading is roughly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;queue-driven and bridge-visible native coverage extends through frame &lt;code&gt;1093&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;frame &lt;code&gt;986&lt;/code&gt; is no longer a generic mismatch; the BG path is close and the remaining error is in the OBJ/composition side&lt;/li&gt;
&lt;li&gt;frame &lt;code&gt;990&lt;/code&gt; behaves similarly when compared against bridge-visible output&lt;/li&gt;
&lt;li&gt;by frame &lt;code&gt;994&lt;/code&gt;, the committed scene variants no longer show a distinct probe-vs-bridge OAM fork&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That last point is important. It rules out one tempting explanation and keeps the next work item honest.&lt;/p&gt;
&lt;p&gt;The repo can now say:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the bridge-visible path is real through &lt;code&gt;1093&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;the screenshot gap after &lt;code&gt;982&lt;/code&gt; is still open&lt;/li&gt;
&lt;li&gt;the unresolved part is not &quot;some random late intro behavior&quot;&lt;/li&gt;
&lt;li&gt;the unresolved part is mostly in Mode 7 OBJ composition and presentation timing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is the kind of blocker description that leads to fixes.&lt;/p&gt;
&lt;h3 id=&quot;what-the-project-looks-like-today&quot;&gt;What the project looks like today&lt;/h3&gt;
&lt;p&gt;From the initial import on 2026-02-26 to the current snapshot on 2026-03-19, this repo has moved from a reverse-engineering base to a working port workbench:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;deterministic Mesen capture and probe scripts&lt;/li&gt;
&lt;li&gt;extraction tooling for palettes, VRAM, chunks, and frame windows&lt;/li&gt;
&lt;li&gt;a modular C/SDL runtime that can replay native and extracted intro slices&lt;/li&gt;
&lt;li&gt;trace-backed provenance tooling for bank 30 and tilemap windows&lt;/li&gt;
&lt;li&gt;deterministic gameplay seed windows&lt;/li&gt;
&lt;li&gt;machine-checkable regression gates and callback contracts&lt;/li&gt;
&lt;li&gt;synthetic renderer fixtures for known correctness bugs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is solid progress for 45 commits in just over three weeks.&lt;/p&gt;
&lt;p&gt;It is also still clearly a port in progress.&lt;/p&gt;
&lt;p&gt;The active blockers in the roadmap are sensible and specific:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;close the &lt;code&gt;958..977&lt;/code&gt; bootstrap gap&lt;/li&gt;
&lt;li&gt;resolve the &lt;code&gt;986+&lt;/code&gt; final-screen composition gap&lt;/li&gt;
&lt;li&gt;keep replacing sampled attract windows with native callback/state playback&lt;/li&gt;
&lt;li&gt;continue the bank 30, bank 10, and bank 11 contract work needed for gameplay&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is where this series leaves the repo for now.&lt;/p&gt;
&lt;p&gt;The important point is that the project is no longer trying to solve all of that with one tool or one style of evidence. It has separate surfaces for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;extraction&lt;/li&gt;
&lt;li&gt;runtime playback&lt;/li&gt;
&lt;li&gt;archaeology&lt;/li&gt;
&lt;li&gt;validation&lt;/li&gt;
&lt;li&gt;cleanup&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That separation is what makes the current state believable. The repo is not just producing images that look close. It is building a system that can explain why a frame is right, detect when it stops being right, and keep moving when only part of the game is ready for native code.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/13287/porting-test-drive-ii-from-snes-to-pc-part-4-validation-cleanup-and-current-blockers</guid>
<pubDate>Sat, 21 Mar 2026 13:48:16 +0000</pubDate>
</item>
</channel>
</rss>