Amy Farbright

Sonic 1 C Port

Source here.

This is a work-in-progress full port of Sonic the Hedgehog (revision 1) for the Mega Drive to C, designed and built over the course of roughly 14 months as of writing (December 2024).

The intent of this project is to provide a base from which the game and its mechanics can be experienced and ported to a variety of platforms, without any compromise to how the gameplay handed in the original. The version of Sonic 1 currently promoted by Sega is not a port but a remake of the original, made with a completely different game engine (in fact, it's the same Retro Engine that I've hacked on in my other hobby projects, go figure). Unlike that version, this project is built off of the original Mega Drive game's machine code, with as few changes made as possible.

I accomplished this by writing a program (asmconverter in the source) that generates "nearly-correct" C code from all the code it can find in the original ROM, assisted by a symbol map from an existing disassembly and a few heuristics. Then, I go through all the generated code and manually fix any issues from the generator that would be too complex to fix automatically (dynamic jumps, complex control flow, code that wasn't picked up by the converter). I compile the resulting C (sonic1c in the source) with TCC (though other compilers will probably work) into a library, and load it through a separate program written in Rust (sonic1 in the source).

The program acts as a specialized "frontend" for Speedshoes (speedshoes in the source), a Mega Drive emulation framework I wrote for this project. Speedshoes contains a minimal implementation of the Mega Drive hardware bus and Video Display Processor (VDP). It is capable of running the original ROM, albeit with some slight runtime patching to accomodate for extra features. Notably, it can detect whenever 68k subroutines are called, and is able to intercept or "hook" those calls with calls into C "scripts". For the sake of accuracy with the game, the C scripts all share a separate RAM area and set of registers from the emulator, and after every hook, the state of the C side is compared with the emulator. Additionally, Speedshoes supports checking accuracy at the level of individual instructions, allowing one to recreate a perfect reimplementation of a Mega Drive game down to the CPU register, without interpreting a single byte of code in ROM.

I intend to do more with the port once everything is successfully converted. Work on those things will come in due time...