During the last week I worked on a tool to convert S3K/S3D/... SMPS files to the Sonic 1 format.
There was a need for it, because MFP doesn't do its job very well. (It converts only a few coordination flags and sometimes changes pointers at places with no pointers at all.)

The tool does not only convert S3K songs to S1 fully automatically (that includes the missing-note fix), but it also allows you to change all DAC sounds and PSG instruments by simply editing two ini-files. That should make porting songs a piece of cake.
(If you want to find matching PSG envelopes, you can use my PSG Envelope Editor. I used it to make the current PSGMap file.)

Notes and bugs:
- Just change the Z80 ROM bank offset if you're sure that the tool detects it wrong. Don't mess with it or you'll get bad conversions.
- The tool prints a message for every ignored command. (Some of the commands may cause it to stop processing the current track. But I don't know any songs that have such ones.)
- The conversion of the modulation/vibrato effect (F0) is still wrong. S3K seems to do that completely different to S1. (very noticable in the S&K spheres bonus stage)
- I know that S3's LBZ1/2 don't really work. That's because LBZ1 has some data of LBZ2 and vice versa.

If there are other bugs (or even crashes), please report it and I'll try to fix it.

As usual, ValleyBell, awesome work. I tried a vary of S3K songs and they all worked perfectly! I tried FBZ2, Final boss, S3 credits, and the miniboss ad all worked perfectly. I tried DDZ2 and the betaboss from build 825 from Sonic3D and both sounded really good, although not exactly the same as the original. I think it's just one or two PSG's out/wrong but guessing because the PSG's aren't exactly the same as S3K.

Well done though, keep up the good work and hope to see your bug list shrink.

Unfortunately this doesn't work for the PSG modulation. (FM modulation works very well with your fix)

I made 2 VGMs of the S&K bonus stage song where it's very noticable. (I stripped all but the PSG data.)
S3K_* is the original, S1_* is the converted version (with 'fixed' modulation parameters).

One thing I noticed is, that S3K seems to invert the change-per-step parameter for PSG modulation. (e.g. a positive value makes the pitch go up for FM and PSG, in S1 it goes up for FM and down for PSG)

Can you recommend a good VGM player? Everyone I tried has failed me, from no output to crashing on load.

Edit: looking over the code from the sound drivers, modulation works as follows in the relevant drivers:

If wait period has not expired, do nothing*;

if speed timer has not expired, do nothing**;

restore speed timer from modulation data;

in S1/S2 ONLY, if number of steps is zero, restore from modulation data, multiply the frequency delta per step by -1 and stop***;

in S1/S2 ONLY, decrement the number of steps***;

add the (sign extended) frequency delta per step to the cumulative frequency change for the modulation and store it***;

add the cumulative frequency change to the frequency of the current note (this will later be uploaded to the FM/PSG channels)***;

in S1/S2 ONLY, the modulation function ends here***;

in S3/S&K/S3D ONLY, decrement the number of steps and return if the result is not zero***;

in S3/S&K/S3D ONLY, restore the number of steps from track data and negate the frequency delta per step***.

The same function is used for FM and for PSG tracks in all these drivers. The difference I can think of that could be responsible is that there is a 12 semitone (1 octave) difference between PSG frequencies in S1/S2 and S3/S&K/S3D drivers; but if this isn't being handled, it should be noticeable in more than just modulation.

* = S1/S2 check for zero before decrementing; S3/S&K/S3D decrement and check if the result is zero, adding 1 back if it is (so it is decremented back to zero in the next update). This is the root of the +/-1 difference I mention.

** = All drivers (S1/S2/S3/S&K/S3D) decrement then check if the result is zero.

*** = The different order of these steps in the drivers is dealt with by the +/-1 I mentioned for the number of steps. There is a slight inaccuracy in this for an even number of steps, but I doubt anyone can notice it.

Can you recommend a good VGM player? Everyone I tried has failed me, from no output to crashing on load.

Sorry, I forgot to mention that there's 20 seconds of silence before the PSG begins. The song doesn't use the PSG a lot, just for 15 seconds in the middle of the song.

flamewing, on 15 December 2011 - 12:31 PM, said:

*** = The different order of these steps in the drivers is dealt with by the +/-1 I mentioned for the number of steps. There is a slight inaccuracy in this for an even number of steps, but I doubt anyone can notice it.

The modulation flag is F0 0D 03 02 0A, so this may be one of the cases that make a difference.

btw: Although VGMPlay is for Windows, I successfully compiled it with openSUSE and it worked well, so it's a little cross platform. (It also compiled under Ubuntu, but it seems to either crash or refuse to play anything.)

Audio Overload does not work for me -- it does not produce sound in Linux and crashes on startup on my XP VM. I finally managed with VGMPlay. I then used my ASM'ed version to port the song to S2 driver (using only the PSG tracks to see the difference) and heard the same problem.

Weird stuff: actually flipping the sign of the modulation delta in the track gave a sound much closer to the original. But this is coincidence -- other PSG sounds I tried resulted in wrong sounds.

Anyway, after digging through the drivers trying to see what was going wrong, I got nothing -- I found nothing that can explain the difference. Dammit, the PSG and FM channels should either both work or both fail!

Edit:

ValleyBell, on 15 December 2011 - 07:18 PM, said:

The modulation flag is F0 0D 03 02 0A, so this may be one of the cases that make a difference.

It isn't; I tried modifying the sound driver to account for it, and it still sounds wrong.

Project:Part of Team Megamix, but haven't done any actual work in ages.

Wiki edits:51

flamewing, on 15 December 2011 - 08:04 AM, said:

ValleyBell, on 07 December 2011 - 03:20 AM, said:

- The conversion of the modulation/vibrato effect (F0) is still wrong. S3K seems to do that completely different to S1. (very noticable in the S&K spheres bonus stage)

I found out about that when I did my SPMS2ASM tool. You can fix it by doing this:

Song from S3/S&K/S3D to S1: subtract one from modulation wait and step parameters (first and last parameters);

Song from S1/S2 to S3/S&K/S3D: add one to modulation wait and step parameters (first and last parameters);

All other cases: leave those parameters untouched.

The way the S1/S2 drivers handle both of these parameters is different from the way S3/S&K/S3D do, making them off by one (as described above) in a raw conversion.

IIRC, S3K allows you to set the number of steps to 0 to make it infinity or something (or am I confusing the values; I never remember what each value in the modulation flag means) and S1 does not, which is what allows the S&K Title Screen song to work at all -- I think I had to edit Sonic 1 SMPS to get that song to play right.

IIRC, S3K allows you to set the number of steps to 0 to make it infinity or something (or am I confusing the values; I never remember what each value in the modulation flag means) and S1 does not, which is what allows the S&K Title Screen song to work at all -- I think I had to edit Sonic 1 SMPS to get that song to play right.

Looking over at the title song, I see that they use modulation with all zeroes 3 times, and twice with 1,0,0,0. In either case this effectively disables modulation, but with a caveat: if the next note is preceded by a no attack ($E7), then the total cumulative modulation from the previous note will not be cleared (and neither will the parameters of the modulation be updated to the new ones, in fact). This is exactly what happens in some of the cases. In one case, it is a more stupid way of doing $FA. In the next-to-last, it is just stupid, and whoever did it should have been shot.

Project:Part of Team Megamix, but haven't done any actual work in ages.

Wiki edits:51

Also, other differences between S3K and S1 SMPS, in S3K, doing "note,duration1,$80,duration2,duration3" plays note for duration1, stops for duration2, plays note again for duration3. In S1 SMPS, it plays note for duration1, stops for duration2+duration3 ("rest" is saved as a note in S3K but not in S1). This is used a lot in S3D's Rusty Ruin song, for instance -- port it to S1 and it will sound wrong.

Ah yes, that S3&K driver bug; it is one of a legion. S3&K also has a problem with rest,[duration,]$E7,note -- the note will simply not play at all in this case. I fixed both (and a host more) in my modified S3&K driver (in the thread I linked to in my other post) as these bugs caused some songs from S1 and S2 to sound horribly wrong and had little to no effect on S3/S&K/S3D songs (edit: not true, as you said).

Edit: Hm. I wonder if these fixes are what was causing the problem Tiddles reported.

Edit 2: Yes, it was -- he had reported problems exactly in those songs that relied on the bug to play correctly.

I took some time and improved my SMPS converter. And I renamed it.
Now it can't just convert from S3K to S1, it can convert from S1 to S3K, too.
Also I added support for late SMPS 68k variants and Ristar. (Please note that you should take care of the second DAC channel before using this tool!)

The tool can convert between every supported format directly, but I only tested S1->S3K and [all]->S1.
You can also use it to recalculate the Z80 pointers or changing DAC sounds by converting S3K to S3K or S1 to S1.

And I finally figured out how to correctly convert between S3K and S1 modulation settings. (There may be some inaccuracies when converting S3K to S1 because of some dividing, but S1 to S3K is 100% accurate.)

The most important difference is, that modsteps is always decremented in S3K, but S1/2 decrements it only when modspeed = 0.
So if you want to convert between the two games, you need to multiply or divide modsteps (coord. flag F0, fourth parameter) by modspeed (second parameter) to convert S1->S3K or S3K->S1, respectively.
And both, modwait and modsteps are one lower in S1 compared to S3K, so you need to take care of that, too.

It's still not 100% accurate, because S1 does nothing when moddelta changes its sign, but that should be barely noticeable.