SMPS Direct Porting Guide

Discussion in 'Tutorials' started by ProjectFM, Apr 1, 2019.

  1. ProjectFM

    ProjectFM Optimistic and self-dependent Member

    Joined:
    Oct 4, 2014
    Messages:
    794
    Location:
    Portland, Maine
    Introduction:
    SMPS is one of the most common sound drivers used for the Sega Genesis with over 100 games making use of it, including most of the ones developed in-house at Sega. Many of these games feature stellar soundtracks. Because the Sonic games also use this sound driver, that music could potentially be part of anyone’s ROM hack. The issue with this is that many games use different variations of the driver, and those differences result in the song being played incorrectly. Fortunately, the program SMPS2ASM makes understanding and editing the music easy, allowing adjustments in order to make these songs compatible. SMPS porting will require some practice and problem solving, but ultimately you can get a satisfying result and be more knowledgeable about working with the sound driver.

    Warning:
    This guide is not for beginners. It will require knowledge of the basics of how the driver works so you can work through the issues that arise. I can’t cover every solution in this guide, so occasionally you will have to use lateral thinking to make use of the tools available and work through your problem.

    Recommended: Learn about SMPS with Sonic Retro's Music Hacking Guide

    Requirements:
    Steps:
    1. Grabbing Music Files
      1. (Z80 Only) Finding the Pointer
    2. Porting to address $8000 in Z80
      1. 68k File
      2. Z80 File
    3. Converting to ASM
    4. Fixing the File
      1. Grabbing References (inc_ file, S&K DefCFlag, Game’s DefCFlag)
      2. Common Fixes and special Cases
      3. Changing the PSG & Drums
    5. (Optional) Converting Back To .bin
    1. Grabbing Music Files
    ValleyBell’s SMPS Research Pack is incredibly useful because it has almost every song used by the driver already ripped from the game. First, just find a good song that you’d like to port over. You will have to use one that can be found in either the Z80 or 68k folder. The music in the other three folders use versions of the driver that are too different to work with.

    1a. (Z80 Specific) Finding the Pointer
    The Z80 version of the driver differs from the 68k version in that the pointers for locations in the file are relative to the start of the sound bank rather than the start of the file. Because of this, the offset of the song will have to be found. There are a multitude of ways to do this:

    The most reliable way is to download the ROM of the original game, go into a the find option, and paste the contents of the song file into the bar. Then, find the location of the start of the song’s location in the game file, and write down the four least significant digits of that location. If the result is less the $8000, add $8000 to it.

    Another way is to look at the value at offset $06 and $07 of the song file. First, flip the bytes, then subtract the value at offset $02 times 4 plus the value at offset $03 times 6 plus $06. So if the value at $06 and $07 is $9C83 and the value at $02 is $07 and the value at $03 is $03, then $839C - ($07x4 + $03x6) = $8368. That is often, but not always the correct offset. The hexadecimal calculator will useful here.

    The third way is to just check the “Other Games” section of the SMPS guide, which lists some games' offsets.

    2. Porting to address $8000 in Z80
    Before importing our song into SMPS2ASM, we need to put it in a format so the program will read it as a song from Sonic & Knuckles. The reason for this being that Sonic 1 and 2 will only use coordination flags from $E0-$F9, so if your game uses any flags from $FA-$FF, they will be replaced with a dummy flag. We’ll also have to make the address $8000, because SMPS2ASM won’t convert files with different addresses correctly.

    2a. 68k File
    Start up “Music Pointer Fixer” and open up your song file in it. Then, press “Scan.” This will load every location in the file which includes an address must be fixed. When asked the format, choose “Sonic 1.” Pick “S1 to S2B/S3K” and press “Fix!” Save your file, and when asked for the location, type “8000.” Click no for the next two prompts.

    2b. Z80 File
    Start up “Music Pointer Fixer” and open up your song file in it. Then, press “Scan.” This will load every location in the file which includes an address must be fixed. When asked the format, choose “Sonic 2B/3K.” Type your song’s offset as the music’s original location. Pick “S2B/S2F/S3K fix” and press “Fix!” Save your file. Choose “S3K to S3K,” type your song’s offset in the left box and “8000” in the right box.]

    3. Converting to ASM
    Create a .bat file in the same folder as smps2asm containing this: “smps2asm -v 4 -o $8000 input.bin output.asm name,” then run it. This will let the program know that the format is Sonic & Knuckles, offset is $8000, the input file’s name, what to save the files as, and the name that will be used to mark locations.

    4. Fixing the File
    This is where experience will widely vary depending on the song chosen. You will need a disassembly with an SMPS2ASM-compatible driver in order to test your song.

    4a. Grabbing References
    In ValleyBell’s SMPS Research Pack, go to the Sonic & Knuckles folder open up the file “DefCFlag.txt.” Then, go to the folder for the game you’re porting the song from and open the file there with the same name. These contain each game’s coordination flags and will be important for finding differences between each game’s drivers. The length column will be particularly useful for seeing how many bytes after the flag should be considered part of that flag’s function. Another useful file is “_smps2asm_inc.asm,” which contains the name of every coordination flag in SMPS2ASM and what value they represent.

    4b. Fixing Differing Flags
    The goal will be using the “find” function to look for every instance where a coordination flag differs between drivers and either find an alternative or delete it. Use the differences in flag length to discriminate between which bytes are for the flags and which aren’t.

    4bi. Common Fixes and Special Cases
    • The Hybrid Front uses the flag $FF $07 to set an FM voice’s volume to a certain value. S&K has a similar flag at $E4. Replace “smpsResetSpindashRev” with “smpsSetVol” and have the following byte share its line. The two flags differ in that HF uses the actual volume value, while S&K XORs the value with $7F, meaning that you should subtract the following byte from $7F to get the correct value.
    • Many games use $E4 as the “Pan_Anim” flag which S&K lacks, so its uses should just be deleted. In SMPS2ASM, it will be portrayed as “smpsSetVol.” The flag has 5 bytes following it unless the first byte is $00. In that case, there’s only 1.
    • Many games use $FD for “Mods_Off” while S&K uses $FA. It will be portrayed as “smpsAlternateSMPS” in SMPS2ASM. Move the following byte to the next lines, and replace the flag with “smpsModOff.”
    • Some games will use the “Mods_On” flag, which is portrayed in SMPS2ASM with “smpsContinuousLoop.” The following two bytes will be an address, so you won’t know what those bytes are. The solution is to go into you pre-ASM .bin file, find every use of $FC, and replace it with a flag that isn’t used in the song which doesn’t use an address, such as $FB, and reconvert the file. Then, find that flag, move the following bytes to the next line, and replace it with “smpsModOn.” Keep the previous version of the asm file in case the byte replacement breaks an address or something so you can fix it.
    4c. Changing the PSG & Drums
    PSG envelopes and DAC samples vary among games. Unless the PSG in the song has a unique sound, setting the envelope in the header and each “smpsPSGvoice” to $00 is good enough. Special cases will require trial and error, going through each of S3K’s psg envelopes until you hear the one that sounds the most accurate.

    Drums are just a matter of mass replacing to work with S&K’s samples. Many games use little more than Sonic 1’s DAC setup. As a result, kick will be portrayed as “dSnareS3,” snares as “dHighTom,” and timpanis as “dMidTomS3,” “dLowTomS3,” and so on. More varied DAC sets will require trial and error to find the best replacements for.

    5. (Optional) Converting Back To .bin
    To convert your song back to a hexadecimal format in case your game’s driver isn’t compatible with SMPS2ASM, first build a ROM using a disassembly with an SMPS2ASM-compatible driver and your song. Then, find your song in the ROM by searching for some bytes specific to your song. Most SMPS songs have “0603” or “0703” as the third and fourth bytes, making it easy to find the start of them. Keep that starting offset in mind if the ROM has a Z80 driver. Finding the end of that song is a matter of searching for those next “0603” or “0703” bytes or an empty space if it’s the final song in the bank. Once you extract the song, you can use MusicPointerFixer to change the offset, or SMPS Converter to port it to Sonic 1’s driver. Both of these will require knowing the offset. Alternately, you can arrange your game’s soundtrack in the disassembly, then separate the songs from the ROM without having to change the pointers and put them in your game, as long as you have a Z80 driver in your game.

    With that wall of text ran-through, your result should be a successfully ported song. Keep in mind that this will require some skill and you may find yourself unable to get it to sound right. In that case, find a different song. Once you’ve worked through a few songs, go back to the ones you couldn’t do and you might do better. There are a couple songs that just won’t sound right no matter what, such as “Mountain Peak” from Yu Yu Hakusho: Makyo Toitsusen. Another note is that sometimes importing your song to SMPS2ASM through Sonic 1’s format will make the process more doable, like with some Michael Jackson’s Moonwalker songs.
     
    Last edited: Apr 4, 2019
    EMK-20218, maple_t and KCEXE like this.
  2. Clownacy

    Clownacy Forever Grumpy Staff

    Joined:
    Aug 15, 2014
    Messages:
    875
    Er... what? I've been using SMPS2ASM for years, and I've never had a problem with this.
     
  3. ProjectFM

    ProjectFM Optimistic and self-dependent Member

    Joined:
    Oct 4, 2014
    Messages:
    794
    Location:
    Portland, Maine
    From my experience that was the case. I haven't done this in a couple years actually, so I may have misremembered or something. I'll read it over later and see if everything's correct.
     
  4. ValleyBell

    ValleyBell Well-Known Member Member

    Joined:
    Dec 23, 2011
    Messages:
    150
    My thoughts when reading the requirements:
    • SMPS Research Pack - okay
    • Hex Editor - a low-level porting guide? nice
    • SMPS2ASM - also a good choice
    • Music Pointer Fixer - erm... nope, WHY?
    Music Pointer Fixer performs a very simple (and stupid) search-and-replace algorithm on what it thinks are offsets. And if you're unlucky, this includes data from the FM instrument block, so it may or may not break your instruments.
    I really recommend against using it.

    smps2asm is a bit counter-intuitive when it comes to specifying the address, IMHO. It sort of auto-detects whether or not the song is placed in the Z80's RAM section (bit 15 clear) or in the ROM window (bit 15 set) and adds the offset specified by the -o parameter to either $0000 or $8000.
    So if your song is stored at Z80 RAM at offset $1380, you write "smps2asm -o $1380 ..." and if your song is stored in the ROM window, offset $9380, you write "smps2asm -o $1380 ..." as well.
    I remember that I couldn't get this to work at all until I asked flamewing about it.

    To be fair, the help screen clearly says
    so I was to blame for not reading properly.
     
    ProjectFM likes this.
  5. Natsumi

    Natsumi Phoenix egg Member

    Joined:
    Oct 7, 2011
    Messages:
    695
    Location:
    Long and dangerous river
    One thing that sticks out to me, is all that jazz with incompatible coord flag disassembly that comes with using Flamewing's SMPS2ASM, it seems horribly convoluted, difficult, and very error-prone way of doing this.
     
    ProjectFM likes this.
  6. ProjectFM

    ProjectFM Optimistic and self-dependent Member

    Joined:
    Oct 4, 2014
    Messages:
    794
    Location:
    Portland, Maine
    So I was working on revising this guide, and I decided to give your version of SMPS2ASM a try, and it turns out it does this entire thing for me, which came as a complete surprise! I've been using flamewing's version for 4 years to do this by hand, and in the time since then that I've procrastinated on making this guide, you've automated the process. That's really cool and I wish I knew about it earlier.

    My plan now is to rewrite this guide, but use the shortcuts your version provides. Then, I can include sections I've already written to any special cases there are in which just using your scripts won't completely fix things. Examples would be The Hybrid Front with its set volume flag or editing drums and psg and stuff. I haven't tested it enough to really know how well it works, so I have yet to find out what to include.
    I tried it out recently, even downloading the latest version, and it hasn't been able to convert right without moving the offset to $8000, no matter if you subtract $8000 or not.
     
    Natsumi likes this.
  7. Natsumi

    Natsumi Phoenix egg Member

    Joined:
    Oct 7, 2011
    Messages:
    695
    Location:
    Long and dangerous river
    Bear in mind, you can do basic arithmetic or even specific replacements with the macro definitions, in case that would help you to automate it. S3K is a good example where I turn the strange values in the absolute volume flag into 'real' volume values used by the code.
     
    ProjectFM likes this.