This is the third post in the series. The first post is the high-level introduction; the second post is the technical deep dive into the workflow. This one is a progress report: what the two ports do today, what broke on the way, which problems I caught and which the tooling caught, and what the work has cost so far.

The DDR EXTREME title screen in the native runtime
DDR EXTREME title screen.
The beatmania IIDX 9th style title screen in the native runtime
beatmania IIDX 9th style title screen (including some unfixed visual glitches at the bottom).

Both captures are from current development builds of the still work-in-progress lifted source code.

A word on “LLM-assisted writing”

This post was written with the support of an LLM. However, this here, is actually me, the human writing this section to be transparent about it. I did review this post prior publishing and also tweaked several things by hand.

My goal is to share the ideas, principles and concepts that I applied in these projects. I believe this knowledge can benefit similar use-cases, and in general help others in figuring out how to make hopefully better use of LLMs in doing great and meaningful things.

LLMs didn’t make writing this post possible, but rather lowered the bar for me to spend that extra time and effort in getting this out. I hope the result, no matter how and who/what wrote it, is what counts and achieves on the knowledge sharing aspect. Because in the end, that’s what I believe does actually matter.

A note on the screenshots

All screenshots in this post are from development builds of the lifted source code unless noted otherwise. Their runtimes still contain visual bugs and glitches, and several screens have not received another bugfix or fidelity pass. From a progress perspective, a screenshot shows that a screen is reachable and that a path works; it is not a claim that the screen is finished, yet. The captions call out known defects where they matter.

The short version

Dance Dance Revolution EXTREME now plays a complete three-stage Beginner session in the native runtime with the source lifted game code, from the title screen through song selection, gameplay, results, the ending, and back to attract. It also supports the entire attract loop and test/operator menu. The code doing that is reconstructed C running on native platform services, driven by real inputs.

beatmania IIDX 9th style now boots through the entire startup sequence to the first warning screen, full attract loop, title screen and starting a session, card entry, mode select, options, the song list, and the confirmation screen. It stops at the pre-gameplay fade. There is no IIDX (main) gameplay yet.

There is no public build and no date for one at this stage.

More updates follow as development progresses and when I decided how to publish any tooling or releases of the projects.

DDR EXTREME: one player session, start to finish

The interesting unit of progress is not a function count or a screenshot. It is a player’s game session that starts at the title screen, accepts inputs, and reaches a natural end/game over.

The latest retained run did that. A 1,165-command script supplied canonical cabinet inputs; the runtime advanced exact frames and captured checkpoints. The script played three Beginner stages and finished after advancing 34,525 game frames/ticks.

DDR Extreme main music select screen with song wheel.
DDR Extreme main music select screen with song wheel. Some slight visual artifacts near the groove radar's "AIR" and "FREEZE" attributes and to the right of the song banner
DDR Extreme song result screen of the final stage (out of 3 total stages/songs) on beginner difficulty.
DDR Extreme song result screen of the final stage (out of 3 total stages/songs) on beginner difficulty
DDR Extreme main gameplay on beginner difficulty.
DDR Extreme main gameplay on beginner difficulty reached from the reconstructed application, after 6,979 game frames/ticks. Visual glitches with additional arrows rendered at the top and bottom of the main gameplay area

That establishes a connected path, not parity, as evident by the visual artifacts. The run is a native diagnostic with deterministic inputs and retained artifacts. It does not by itself prove that the original arcade board would produce the same pixels, the same audio, or the same timing at every step. The next section is about why that distinction matters and what it takes to make a claim smaller and more useful.

The ordinary launcher also runs the full attract loop and test/operator menu without the control session, so the application is not only usable under a game-loop debugger.

What “exact” means here for visual output

A screen can look convincing and still contain rendering errors. For a visual comparison, I can make “exact” more concrete: at a particular checkpoint, do the reconstructed runtime and the original game produce the same pixel values? That is a much narrower question than whether the whole port is faithful, but it is one the tooling can answer.

For DDR, the reference is the original game running in MAME. Lua scripting provides controls on that side, while the native runtime exposes corresponding game-loop debugger controls. These let the agent supply inputs, advance execution, and capture output for comparison. An automated pixel comparison then measures differences that a side-by-side inspection might miss.

The useful part is the investigation this enables. In one comparison, correcting the operator-text rendering reduced the differences but did not eliminate them. A suspected display-mode issue was tested and made no difference. Further investigation showed that some captures had been taken after entering the screen under different display conditions. Those captures were not a valid like-for-like test: changing the renderer to make them match would have been chasing the wrong problem.

Once that setup was corrected, the compared image matched pixel for pixel outside a deliberately excluded footer containing version and machine-identity information that differed between the two runs. The comparison also accounted explicitly for the two runtimes’ different pixel representations. Neither step was permission to blur away rendering errors.

That is what “exact” means in this example: the same pixel values in the compared region, at the selected checkpoint, under the stated comparison conditions. It does not establish matching audio, input timing, other screens, or the picture produced by a physical arcade board. The reference here was MAME’s selected video-memory image, not a measurement of the cabinet’s display.

The agent’s value was not simply judging whether two screenshots looked alike. The tooling gave it a way to investigate differences, test hypotheses, and measure the outcome—including discovering when the comparison itself was misleading.

A matched checkpoint used for comparison: original runtime (left) and native runtime (right).
A matched checkpoint used for comparison: MAME runtime (left) and source lifted runtime (right). Notice the visual artifacts near the groove radar's "AIR" and "FREEZE" attributes and to the right of the song banner

Defects, and who caught them

I care about who or what caught a defect because it says something about the workflow. A human noticing a broken screen is valuable but expensive. A runtime or comparison tool used by an automated agentic workflow catching the same class of problem is “cheaper” and repeatable. The goal is to move defects from the first category to the second without pretending that either category disappears.

What I, the human, caught

Code path defect that didn’t matter to the agent

The source-lifted IIDX application produced a black screen and appeared stuck after pressing Start at the title. The agent had created separate startup paths for its controlled runs and the normal application launcher. Its specialized path worked, but the normal entry point had not been connected correctly. I hadn’t tested the application myself until then, so this gap survived the agent’s checks. After I encountered it, a brief code review and feedback were enough for the agent to correct it. Testing the game through a development interface had not established that launching it normally worked.

Different rendering modes

DDR had a different kind of gap. The test menu appeared as a small image in the middle of the window, while the title screen’s credit counter was misplaced near the center. I pointed out that the original game switches between low- and high-resolution rendering (320x240p and 640x480i modes), and suggested investigating whether those mode changes explained the symptoms.

DDR test menu before correction, with small text confined to the center of the window
Test menu before correction: low-resolution content occupies only the center of the window.

That gave the agent a concrete direction, but it wasn’t the diagnosis by itself. The investigation found two reconstruction mistakes: leaving attract mode updated the wrong resolution field, and the credit-text code read a separate field that did not track the frame’s actual mode. Correcting those paths restored the menu’s full-window presentation and the title credits’ placement, which I then checked visually. We had initially discussed changing the port’s resolution handling, but that turned out not to be necessary for these defects—the reconstructed code needed to preserve the original behavior correctly.

DDR title screen before correction, with small credit counters misplaced over the logo
Before: the credit counters use the wrong size and position, appearing over the logo.
DDR title screen in a later development build, with correctly sized credit counters along the bottom
After: a later development capture shows the correctly sized credit counters along the bottom.

Incorrect texture addressing

On the Dancemania screen which is part of the attract loop, the artwork appeared repeated and discontinuous. Investigation with the actual image resource found that the reconstructed renderer calculated the texture-page origin incorrectly. PlayStation texture addressing combines a page location with coordinates inside that page; getting that relationship wrong made the native renderer read a different part of the artwork. Understanding the original graphics conventions mattered here, even though the replacement renderer ran on modern hardware. That established a concrete defect, but did not by itself prove that every discontinuity in the screenshot had been resolved.

DDR Dancemania attract screen with repeated and discontinuous artwork
Dancemania: artwork repetition and discontinuities. Investigation found an incorrect texture-page calculation in the reconstructed renderer.

When several defects combine

The ranking screen was not one isolated graphics bug. Its reconstruction had incomplete font handling and used the wrong drawing method for the background: a single wrapping primitive where the original split the image across texture pages. A later investigation also found that it selected artwork from assumed resource slots instead of resolving it through the game’s shared resource map. Earlier screens could change those allocations, leaving the ranking renderer drawing valid—but unrelated—image data. Correcting text rendering alone therefore did not fix the screen: the connected resource-loading path mattered too. These were defects found during the investigation, not proof that each stripe in the earlier screenshot had the same cause. Interlace handling was an early hypothesis, not an established explanation.

DDR ranking screen obscured by severe cyan, magenta, and black striped rendering corruption
Ranking screen: severe rendering corruption. The investigation uncovered separate drawing, font, and resource-binding defects—not a confirmed interlace problem.

These cases show why “LLM-assisted” is an important distinction. I supplied observations from actually running the game, context about its original display behavior, and direction about which failures mattered. The agent then used the binary, original resources, tests, and runtime comparisons to investigate those reports. My resolution-mode suggestion helped focus the menu and credit-text investigation, but it was a hypothesis to test—not an instruction to make every rendering problem fit the same explanation.

The tooling’s coverage also shaped what the agent could establish. A successful build or an isolated screen test did not prove that the normal application path worked, that earlier screens had left the right resources available, or that the rendered output matched the original. Human feedback helped expose those gaps and steer the next experiment; repeatable checks then made the supported corrections verifiable. The useful division of work was not just me spotting defects and the agent fixing them: I helped choose the relevant path and question, while the agent investigated the evidence and tested the answer.

What the runtime caught

A scripted DDR session initially stopped after the second stage. Another run reached the ending but aborted because an ending resource, was not connected through the reconstructed loading path. These were integration gaps: individual screens could work while the transitions and resource loading needed for a complete session were still incomplete.

Running the game through a full session gave the agent a repeatable way to encounter those gaps, investigate where execution stopped, and replay the affected path after a correction. The later run completed all three stages, showed the ending, and returned to attract. That verified the exercised sequence—not every possible session—but it covered behavior that testing screens individually would miss.

The same approach also exposed a defect in the testing interface itself. The game completed the scripted inputs, but an undersized response buffer prevented the controller from receiving the completion status. The failure was in the tooling, not the game. Reliable runtime feedback depends on checking that distinction rather than treating every failed script as a reconstruction defect.

What the comparison tooling caught

The image comparisons helped the agent measure whether rendering corrections actually reduced the differences. They also prompted an investigation into whether the two runs were comparable in the first place. In one case, the native capture had inherited a different display configuration, so the apparent rendering mismatch was partly a setup problem. The correct response was to fix the comparison conditions, not change the renderer to compensate.

The reference capture needed scrutiny too. At one checkpoint, MAME’s screenshot still showed the previous screen even though the selected image in video memory had already advanced. Inspecting that buffer exposed the discrepancy. For that comparison, the reference became the selected video-memory image, with the limitation that this checked rendered content rather than the final display output.

The useful feedback was therefore more than a count of different pixels. Captures and runtime observations gave the agent a way to distinguish a reconstruction defect from a mismatched scenario or an unsuitable reference.

What static analysis caught

A broken IIDX mode-select screen came from loading the wrong asset set. The reconstructed code selected a neighboring resource descriptor, bringing in artwork and animation data of the main gameplay screen instead of the intended mode select screen. The data was valid enough to render and not crash the application, so the application drew unrelated artwork just fine and even menu selection mechanics were actually working and controllable with player inputs.

Comparing the reconstructed resource-selection code with the original binary identified the wrong descriptor. That explained why the screen could run while still being incorrect: successful loading did not mean the right data had been loaded.

This is where static analysis complements runtime testing: the rendered screen exposes the symptom, while tracing the original code and data can establish why it happened.

IIDX mode-select screen before the resource-selection correction, displaying unrelated artwork
Mode select before the resource-selection correction. The mode9/bank21 selection is corrected in source; a fresh post-fix capture and the mode-label rendering remain outstanding.

The lesson is not “the agent was careless”. The lesson is that a plausible-looking lookup that resolves to the wrong bank is exactly the kind of defect that a rendered screen can hide, and that a regression tied to the original descriptor is what makes the correction durable.

IIDX: the first visible path

IIDX is slightly behind DDR as I started that project after I reached a high degree of agentic automation with DDR, and also figured out several important fundamentals that I could apply to IIDX immediately. However, everything from initial startup/boot to the screens on the screenshots is working regarding rendering, sound and inputs.

Since I already covered various LLM-related aspects with DDR above, the following is simply a few screenshots showing progress and also a few more defects.

IIDX attract loop game intro sequence
IIDX attract loop game intro sequence.
IIDX Options menu on the title screen once coins are inserted
IIDX Options menu on the title screen once coins are inserted and before starting the game session. The menu is visibly glitched;
IIDX Card entry screen
IIDX Card entry screen.
IIDX Music select screen with song wheel
IIDX Music select screen with song wheel.

What works as of October 18–19, 2026

This is the snapshot for this article, not a rolling list of later progress. “Works” means the listed screen or feature is connected and exercised within the described scope; it does not mean every mode is complete or every visual and audio detail matches the original.

Dance Dance Revolution EXTREME

  • Attract mode: warning and logo screens, Dancemania artwork, the title screen, How To Play, demonstration gameplay, BEST RANKING, hidden-element availability, and Memory Card Information. The ordinary launcher runs the repeating sequence without a debugger directing screen changes.
  • Credits and controls: coin and service credits, Start, menu navigation, and player dance-panel inputs, with keyboard mappings for both players. Input controls work across the implemented screens, including the game menus, song selection, gameplay, and test/operator menu. Having both sets of controls does not establish a complete two-player game.
  • Starting a game: the title-to-game menus and song-selection wheel, including browsing and confirming a song on the demonstrated Beginner route.
  • Beginner gameplay: a complete three-stage session with scrolling arrows, input judgments, score and combo tracking, and progression from one song to the next. The retained end-to-end run uses scripted inputs, rather than establishing every song, difficulty, or play mode.
  • Results and game completion: individual stage results, Total Result, ending credits, and return to attract mode after the third stage. The failed-session return path is also connected.
  • Test/operator menu: the main menu and settings/check screens, including game and coin options, bookkeeping, sound options, and memory-card options. Sound options supports playback, cancellation, and return/re-entry; memory-card options works in the native no-card-inserted scenario, not as real card read/write support. Cabinet-check screens are not proof of physical arcade hardware operation.
  • Audio: attract playback, fades, and silence behavior are connected, including the attract-sound setting and its once-every-four-cycles policy. Audio verification was still lagging behind the screen and input work at this point; comprehensive playback and fidelity verification across the implemented game flow remained outstanding.

beatmania IIDX 9th style

  • Startup and attract screens: boot/loading and system checks, the warning and title screens, and the reconstructed attract sequence, including How To Play/demo and ranking paths. Coverage includes connected component tests; it is not a claim that every attract branch has been visually verified in the full application.
  • Credits and session entry: coin-up and credit display, Start, the ACCESS sequence, and the offline PLAYER01 participant/card-entry screens. This does not establish online services or working physical card readers.
  • Mode selection: the mode-select screen and its transition into music selection. The resource-selection correction is in source, but a fresh post-fix visual capture is still outstanding.
  • Game options: opening and changing the option menu, including applying RANDOM. The retained screenshots still show rendering defects.
  • Music selection: browsing the real song catalogue, version and difficulty categories, song details, selection countdown, and song confirmation, followed by the fade toward gameplay.
  • Audio and input controls: audio is fully working for the implemented screens and flows, as are the input controls used to navigate them, change options, and select and confirm songs. This does not extend the working scope into playable stages.

IIDX’s boundary at this point is before gameplay: no playable stage, player-session results, or complete game session is established. DDR is further along, but its demonstrated Beginner session is still a bounded working path, not a claim that the entire game is finished. The visual defects shown earlier remain part of this snapshot.

Time, LLMs, and money

I did not track human hours. I could reconstruct some of it from session timestamps, but that measures session length, not my actual attention and any cognitive energy I spent.

The shape of the human work changed, though. In the first weeks I watched runs, read diffs, stopped and steered the agent often. The early sessions needed a lot of babysitting because the environment, the evidence boundaries, and the definition of a good stopping point were still being discovered. Later I could leave a bounded job running and review the outcome. That shift came from better contracts and better evidence, not from a single model upgrade.

The session database records the machine side more precisely. These are summed request durations, not wall-clock time; parallel sessions overlap, so the hours add up to more than the elapsed calendar period.

  DDR EXTREME IIDX 9th style
Requests 249,152 119,264
Sessions (subagents) 5,036 (3,770) 1,466 (1,378)
Prompt tokens 9.36 B 5.15 B
Cache-read tokens 17.62 B 8.76 B
Output tokens 62.1 M 33.6 M
Reasoning tokens 43.0 M 23.3 M
Cache share 65.3% 63.0%
Summed model time 2,186.9 h 1,276.3 h

Combined, that is 368,416 requests and 3,463.2 hours of summed model time across both projects, from late July to mid-October 2026.

The following lists the various models I used with a pre-configured agent roster assigning different models so different tasks. Though, the majority of the work was done by sol.

Model Requests Summed model time
gpt-5.6-sol 128,907 1,916.9 h
gpt-6-sol 187,081 1,260.4 h
gpt-5.6-terra 36,321 229.1 h
gpt-5.6-luna 3,892 24.2 h
gpt-6-luna 6,412 15.7 h
deepseek-v4-flash 5,687 16.3 h
gpt-5.4-mini 116 0.6 h

The most interesting observation is not a ranking. gpt-6-sol handled 45% more requests than gpt-5.6-sol in about two-thirds of the summed model time: 187,081 requests and 1,260.4 hours, against 128,907 requests and 1,916.9 hours. Average request duration fell from 53.7 seconds to 24.2 seconds. Prompt tokens per request were roughly comparable, around 117k versus 110k, while the cache share fell from 79.1% to 48.2%.

I would not call that a controlled benchmark. The workflow, prompt structure, and task mix changed between those periods, and a shorter request can mean a smaller task rather than a better model. It is a reason to keep measuring, not a conclusion about which model is “best”.

On money: I run two OpenAI Pro subscriptions at €229 per month each, so €458 per month. The period spans roughly three billing cycles, which is about €1,374. If I allocate that by summed model time, DDR accounts for about €867 and IIDX about €507. That is an allocation, not metered spend. The recorded cost fields in the session database are zero because this is subscription usage, not API billing.

I also started experimenting with DeepSeek V4 Flash near the end of this period: 5,687 requests and 16.3 hours of recorded model time. It is too early to judge. The OpenAI plans had several usage resets, banked resets, and a token credit when the plan changes, which makes a simple “cost per game” comparison even more difficult at this time.

What’s next

Work on both projects is continuing. My immediate goal is to complete the source lifting for DDR EXTREME and beatmania IIDX 9th style, building on the working paths shown here until the remaining screens, game modes, and features are reconstructed.

I also want to source-lift other versions of both games. That makes model time and cost more than a retrospective curiosity: I want to understand what makes this work more efficient and how much of the tooling and knowledge carries over to the next game.

The longer-term vision is to use that reconstructed source as the foundation for remasters of these games and eventually release them. There is still plenty of work between the development builds shown here and something ready to share, but that is the direction I want to take.

This is a personal project, done entirely in my spare time and funded out of my own pocket. I am not announcing a release date, feature checklist, or support commitment. There is no public build yet, and I am not recruiting testers at this point in time.

I’ll keep working on it at my own pace and share further updates as it progresses.

Earlier posts