GitHub - djyt/sonic2mod: Convert SMPS Sonic Music Files to MOD Format

5 min read Original article ↗

Convert Sonic The Hedgehog 1 SMPS assembly music files from the Sega Megadrive to MOD format.

reassembler 2026 | https://youtube.com/@reassembler68k | https://reassembler.blogspot.com

Requirements

  • Python 3.11+
  • GCC or MSVC on PATH (only needed if recompiling the synthesis DLLs — pre-compiled Windows binaries are included)

Installation

git clone https://github.com/djyt/sonic2mod
cd sonic2mod
pip install .

For a development install (edits to source take effect immediately):

This registers two CLI commands: sonic2mod and sonic2mod-analyze.

Quick Start

There are two main components to this package:

1/ A converter to convert SMPS files to MOD, including FM and PSG synthesis.

2/ An analyzer to parse Sonic's SMPS files. (Only required if you're planning to make your own configs from scratch - if you just want to convert the existing Sonic tracks you can ignore this).

Once installed, run the following commands from the repo root:

Convert a song:

sonic2mod configs/02_green_hill_zone.yaml

Or using Python directly:

python convert.py configs/02_green_hill_zone.yaml

Output .mod files are written to output/ and can be opened in Fast Tracker 2 Clone.

That's it - nice and easy. The complexity comes if you want to extend the tool further really.

Sonic Music

Pre-configured conversions are in configs/

Config Song
01_title_screen.yaml Title Screen
02_green_hill_zone.yaml Green Hill Zone
03_marble_zone.yaml Marble Zone
04_spring_yard_zone.yaml Spring Yard Zone
05_lab_zone.yaml Labyrinth Zone
06_star_light_zone.yaml Star Light Zone
07_scrap_brain_zone.yaml Scrap Brain Zone
08_special_stage.yaml Special Stage
09_robotnik.yaml Boss (Robotnik)
10_final_zone.yaml Final Zone
11_stage_clear.yaml Stage Clear
12_ending_theme.yaml Ending Theme
14_invincibility.yaml Invincibility
15_1up.yaml 1-Up / Extra Life
16_chaos_emerald.yaml Chaos Emerald
17_drowning.yaml Drowning
18_continue_screen.yaml Continue Screen
19_game_over.yaml Game Over

Analyze an SMPS file (create a new config that doesn't already exist)

Example: Create a config file from the Green Hill Zone assembly:

sonic2mod-analyze "input/Mus81 - GHZ.asm"

With an existing config to show coverage:

sonic2mod-analyze "input/Mus81 - GHZ.asm" --config configs/02_green_hill_zone.yaml

The analyzer isn't perfect, makes mistakes and bad decisions. Like us all. Expect to hand-tweak its output in certain cases to get the best possible results.

FM/PSG Synthesis

Cycle-accurate YM2612 (FM) and SN76489 (PSG) synthesis is enabled by default. These have been pre-compiled for Windows and included as a DLL file. However, if you're using Linux or a Mac you'll need GCC or MSVC installed and in your path.

I chose to leave both of these emulators as C for performance, ease of future upgrading, and the high chance of introducing bugs if I was to convert them to Python!

To disable synthesis and use pre-rendered .raw sample files from samples/ that you have provided instead, set in configs/settings.yaml:

fm_synthesis:
  enabled: false
psg_synthesis:
  enabled: false

Smoke tests (generate a basic sample):

python ym2612/validate.py
python sn76489/validate.py

Documentation

Document Contents
docs/yaml_config.md Full YAML config schema
docs/pipeline.md Conversion pipeline — SMPS→MOD effect mapping, BPM derivation
docs/smps_driver.md Megadrive Sonic 1 driver reference — all coord flag bytes, timing
docs/fm_synthesis.md YM2612 synthesis pipeline
docs/psg_synthesis.md SN76489 PSG synthesis pipeline

There is also a CLAUDE.md file, so you can experiment with adding functionality (or simply breaking everything) with an AI coding agent. I've found Claude Code to struggle with low-level assembly, but AI is evolving so fast that may have all changed by the time you read this! It's very good at some of the boring Python maintenance, and I used it for the above documentation. It's me writing right now though! :-)

I'm not particularly looking for a load of chaotic AI driven push requests at this moment in time, but I'm happy to get robust and meaningful changes merged in. Or feel free to fork the codebase and do it your own way. Don't let me slow down your dreams!

Limitations

  • Mid-track tempo changes are currently ignored. This impacts Drowning, which should speed up as it progresses.
  • The Credits music is not configured for translation. It's effectively a Megamix of all the existing Sonic music, and I suspect I'll handle that in a different way in the final port of Sonic to the Amiga.
  • Synthesis is performed at the lowest note of the specified range in the current config files. It would be sensible to do this mid-range to minimise timbre changes to the final output.

Future Improvements

  • Support other versions and forks of SMPS
  • Binary input option
  • Tools and helpers to combine samples and channels to target 4 channel MODs

History

I originally coded a similar tool to facilitate the translation of OutRun's music to the Amiga. However, it was hacky, esoteric and probably unusable by anyone other than myself. As such, this is an evolution of that process. I was able to get results I was happy sharing within weeks, partially thanks to this pre-existing codebase and also using AI to handle some of the boring bits involved with releasing software!

Licensing

This is licensed under the GNU LESSER GENERAL PUBLIC LICENSE. This is the same license as the Nuked-OPN2 core, which is included in the codebase.

Thanks & Acknowledgements