Niblet ←

trace recorded 20 october 2026 - time to read: 7 min

Recompilation Part 3 - Gone Native

code AI gba development recompilation decompilation

Recompilation Part 3 - Gone Native
In the previous part of this series we'd ended up with a native version of 'Training 1' with a custom UI and graphics extracted from the ROM, closer to a fully native port than the wrapped runtime from part 1  but worlds away from the full retail experience.

It felt like at this point we'd crossed the biggest hurdle and that it was likely we'd be able to iterate towards a finished product. I was feeling a little giddy by now since things were moving very quickly. I realised that I'd want to document this process and so that's exactly what I asked Nibs to do:

This is incredibly exciting... I would like to make sure that each of these prototypes is somehow saved - can you ensure I can easily find these builds as we go - I want to document this process for a blog post

And so that's what he did. He saved the three milestones that had taken place up to now and created an HTML file documenting what each one had added.

Once satisfied, I posed the next question:

Ok, so this latest version is obviously only one level but it works. What do we do next?

He's always got the answers:

Next, I’d make the first training world playable from start to finish in the native engine.

I'll spare you from the subsequent back and forth but once the training courses were complete, we continued in the same fashion. 

Training 1 is the most basic level possible in Kururin and implementing level by level would soon introduce new mechanics that the engine couldn't handle - healing zones, springs, rollers and pistons and more all needed to be implemented to properly represent the retail experience. I suggested that GPT audit batches of levels and stop once a new element was encountered. 

Once a level had been implemented, it needed verification - a visual check is not enough, I wanted to be sure that the behaviour in the true native version was identical to the source material - Nibs was able to automate this process to a level of precision far beyond what could be visually confirmed. 

How this happened in reality was that Kurubot solutions (some normal gameplay, some using absurd glitches), generated routes (GPT used automated searches of possible movements) and specific micro-experiments would be executed using both the previous runtime-assisted version and the new engine. After each frame, game state values were compared between the two. Matching values gave us confidence that the engine performed correctly under the tested conditions.

This methodology worked really well for many levels but for some reason or another Nibs got stuck at 'Ice 3', and I noticed him starting to consider developing another breadth-first search (BFS) routine and it got me thinking - I'd seen a 100% no damage clear video by mohoc so suggested he find the inputs from that video and use those to validate real world clears - a full level cleared in a no damage way would be good verification. I'll have to be completely honest here, things are confusing - mohoc collaborated with E-Sh4rk during the development of Kurubot and it's quite possible that the inputs from his TAS are also included in that project, it's not clear to me why providing the TAS suddenly got us over the hump. I have interrogated Nibs about this but haven't really managed to get an answer that fully satisfies me.

This process repeated until all courses had been implemented, the game for the most part playable but lacking audio, animations, world map and various flourishes. I won't bore you with all of the details of the implementation but archivist-Nibs has created an incredible amount of records explaining his process. 

It's time to talk about audio - It should've been obvious but I didn't really consider the fact that, like the Game Boy before it, the GBA uses an audio synthesis chip to generate sound using a combination of waves. In addition, It also has a couple of sample playback channels. This means that audio extraction from the ROM wouldn't capture music, since it's stored a series of commands rather than MP3/WAV, for example. Nibs had already implemented a native sound engine that used GPT generated audio for a couple of triggers - the spring contact sound was an early example. I wanted to hear proper music and in order to do so, it needed to be converted into a Windows friendly WAV format. This task fell to the import tool, previously responsible for extracting level data & graphics it now needed to render approximate audio based on the instructions usually sent to the GBA sound hardware (or in this case, the GBARecomp runtime). This happens once during import and the native game engine replays and loops the results during gameplay.

I thought this would be a perfect example of how different the resulting code would be and so I asked for a comparison of the same section in the original runtime version versus the native audio engine - this was partly for my own understanding but also to prove that we really were moving away from simulating the GBA hardware and creating something I was happy to call a 'windows port'

The game is tied together with a menu, cutscenes, a world map etc and they were not fully represented in the native version. In a similar way to implementing the levels, we took an iterative approach - I'd cheese-bribe Nibs asking for 'the world map fully implemented' and he'd negotiate me down to 'I'll do Grassland', before returning with a new build. Again, there's little benefit in me explaining every step but as an example of our collaboration, I noted after one build:

Ok, I also notice the z order seems incorrect for the blue level markers - do you see?

To which he replied:

We currently draw every level marker over the flattened map image, so they can appear in front of scenery that should obscure them.

A little evasive perhaps but eventually he relented and logged this in the development notes:

It's this sort of work that's still taking place. As far as I know, the game can be completed (I'm not actually that good at the game!) but there are bits and pieces that still need to be done, controller support is key, for example.  Unfortunately the desire for cheese is strong in this one and so I'm battling with GPT usage limits but I feel like we're close to a release.

One thing I haven't mentioned at all is the Versus mode. KuruKuru Kururin is compatible with the GBA link cable and multitap, allowing for up to 4 players to race to complete course from the games challenge mode. I have never played that and was unable to test it in emulation but I've decided that the best way to implement it here is to provide a split-screen option - I don't think users will be clamouring for network multiplayer on this title. That will be the last thing I do with this 'retail' version, though. I'll call this complete when the TAS runs from power-on complete. I want to be in a position where a proper 100% no damage run completes but also the turbo-glitch-out-of-bounds run too. Once that's possible I will publish the result to GitHub.

One thing that I have kept returning to during this process, though, is what this native implementation opens up for us and that's the ability to free us from the copyrighted ROM and produce original content for this engine. I've got lots of ideas for that but I'll save it for part four...



comments

0 comments

no comments yet.