Have fun, read the README.txt, don't bother me for feature requests.
Fixes a lot of bugs, does not improve the core or Sonic 1 tempo. You guys can take care of that, I have other things to tend to.
OLD POST TO FOLLOW:
Okay, so here's the basic premise -- I spent some time to learn and understand the almost entirely undocumented (as of s2dasm2007) Sonic 2 Z80 playback engine. This resulted in a heavily commented and relabeled edition of the assembler currently held only privately on my side. And really the only reason for that is I did a few test hacks to disable Saxman compression and have it read from ROM in bank form (more or less S2B style, but I hadn't actually known that's what S2B did before I did it.)
But anyway, after successfully figuring out about 95% of the disassembly, I then decided to reprogram it in C, in hopes to maybe make it clearer to others plus possibly provide "preview" functionality to music editors. The YM2612 and SN76496 emulation sources (each a single C file) were pulled from an old DOS GYM player (MSP anyone?), so they're probably not top of the line, but they were easy to integrate. The DAC decoding is a direct C implementation of jman2050's decoder logic (even performed in realtime so it stays in sync properly), the Saxman decoder is a fresh version mostly based on the Z80 code with just a little help from KENS, and the main SMPS guts are my own reproduction from the Z80. Using a little load-time logic, it successfully plays almost all Sonic 1 and Sonic 2 tunes very well, though not quite flawlessly yet.
Download SMPS Demo
This includes direct-from-disassembly Sonic 1 and Sonic 2 SMPS songs. I have not tried 3rd party music yet. If you have some laying around, let me know how it goes. You will need to give it the proper file extension (listed below) because the player does NOT autodetect yet and WILL crash on a bad read. :P Press UP/DOWN to select, ENTER to play, ESCAPE to quit.
- Periodically, I seem to lose a track somewhere; Super Sonic for example is missing a base or something
- Sonic 1's tempo is NOT right yet; the Ending song is the most dramatic example of it going waaay wrong!
I have not yet thought of a foolproof autodetection system, so the player currently uses the file extension to determine the SMPS data variant, and supports the following without modification:
- ".smp" -- Sonic 1 68K relative-addressing SMPS
- ".sax" -- Sonic 2 Saxman compressed music (assumes the 1380h fixed starting position)
- ".rom" -- Music pulled from ROM bank (a few Sonic 2 Final songs use this; automatically finds their original bank offset and 'relativizes' them.)
I have implemented the full coordination flag set from the Music Hacking page, including the Sonic 3 ones. I believe this will be able to play Sonic 3 tunes with little additional work (the larger DAC set and the universal table would need to be implemented, obviously.) Speaking of which, just a few CF notes from my journey that I'd like verified or something:
- E1 -- "Alter note values by xx???"; specifically, this adds a raw signed value to the frequency of the FM or PSG, sort of a pitch bend
- E2 -- ALSO exists in Sonic 1/2 and does take a parameter; in S2, it sets zComRange+6 based on the supplied parameter, though I don't see any purpose for it? Possibly used for timing? (E.g. it appears in the Ending music and might be used to sync it) This explains why Sonic 3 supplies E2 FF probably; it's still a flag write, but I guess 'FF' means fade-in for Sonic 3 only.
- E7 -- listed, likely by mistake, to take a parameter; it does not
- EC --"Change channel volume to xx; xx is signed"; this is not quite correct. This actually only adds to (not "change it to") the volume like E6, but won't take effect until the next FM voice change (it sets the internal volume level but does not apply it to the TL registers)
- EE -- listed with a vauge "something to do with voice selection", which I'm not sure where that came from? In reality it's unimplemented in Sonic 2... in fact, erroneously implemented such that using it would skip the next command byte!
- Does anyone know what Sonic 1's tempo value means? Sonic 2's is simply a ratio of the 60Hz clock, with 0x40 = 15Hz, 0x80=30Hz, 0xC0 = 45Hz, 0xFF = ~60Hz; right now I'm using a guessed "sounds good" equation to convert it, but it's obviously wrong in a few cases (the "Drowning" song and the "Credits" song are the most clear examples... listen to the latter just take off!)
- My DAC is a little fast... I was trying to coordinate it with the clock of the SN76496 since the Z80 engine busy-waits to slow down the playback rate, but it does seem to have a little more control than that somewhere. Anyone know exactly how it's timed? Failing that, anyone know the normal base rate (in Hertz) of the full-speed (rate 0) DAC playback?