In sometime between January 6th-7th I figured out the format of pointers to 68K banks. As you can realize from Tweaker's guide, banks are always multiple of $8000, and there's nothing in 68K to change them. That's because they are stored in Z80 RAM. I disassembled S2 sound driver and I can tell you, for instance, it's nothing like setting a variable to $1F that'll make Z80 acceess bank stored as 68K's $F8000 ($8000 x $1F). I got the Sega2f doc, and it only helped to find the actual Z80 address that does bank switching. The explanation there, though, wasn't in English for me. :P
First, let's put straight how music is accessed in S2. 68K code sets a RAM address ($FFFFFFE4) to have the value of the desired music. Somewhere else, one of those permanent functions checks that address to see if it has changed since last time. If so, it writes the music value to Z80 RAM ($A01B88). This last step involves more than a single move.b d0,$A01B88, because it's needed to stop Z80 processing before attempting to handle its data. After that, 68K makes Z80 resumes its operation. Z80 also has a constant function which checks to see if 1B88h is something but $80 (no music). Depending on that value, Z80 switches bank in order to play musics ($F8000), continue music (if $9C; F0000) or sound effects ($F8000). The bank is nothing but a space of $8000 bytes that is mirrored from a certain 68K memory space, so that's why music pointers in S2 are little-endian.
The bank switching, as said previously, isn't done by a single value assignment. On the other hand, it's done by a single memory address, which happens to be $A06000, or just 6000h for Z80. That's exactly what's written in Sega2f document:
What such masterpiece of English language is saying is that bank is determined by a sequence of 9 values written one after other to 6000h. It sounds strange, but it works, believe me :P. Now, why is it a sequence of 9 values? As banks rely on multiples of $8000, it was not hard for me to fugure what they mean. Heh, they're indeed bits, and as you know (I hope), a bit can be one out of two values: 0/1, yes/no, true/false, etc. So they're nothing but a bunch of flags for the following bank values:
$8000
$10000
$20000
$40000
$80000
$100000
$200000
$400000
$800000
Sum everything and you'll have $FF8000 which is the hightest bank Z80 can access (and also the last $8000 bytes of Genesis memory). Yes, Z80 can access 68K RAM, but I don't see any practical use for it, as it would limit working space for 68K. I'm not sure about 68K SRAM, but it should be accessible too.
So how S2 sound driver does bank switch? It's actually something weirder than a "move.b #1, 6000H", but it follows such pattern. Let's see part of a Z80 disassembly from S2:
This is always used for bank switching in S2. This part refers to the bank for musics but continue ($9C). LD (HL),E does the role of 1 and LD (HL),A does the same for 0. In byte terms, 73 is 1 and 77 is 0, for this case (and the rest of S2 sound driver). If you align that with the bank values you'll get $F8000, which is where music is stored in S2. During the Z80 halt in 68K code, before writing the value at 1B88h, you can put a check to see if certain condition is true, so you can alternate between one bank or other in order to play more musics than $1F - you still use the same values for music; the use of unused values like those after $70 in Sound Test is possible, but it requires Z80 reprogramming which I'm not able to do with my current knowledge, plus this method is enough for all S2 hacks that demands more musics.
Using the code shown above as "guinea pig", here's the code for a little music hack I did:
http://www.sonicforc...S/soundplay.txt - the code was compiled and inserted into unused space in ROM, and in $1084 I put a jmp code location.
http://www.sonicforc...JS/soundfix.txt - this is a fix for when musics are played through FFE2 due to SEGA's bad programming, because the funtion at $1376 is supposed to play SE. This will redirect sound requests lower than $A0 to 135E. Just compile and put a jmp code location in 1376. If this fix is not applied, sound $98 will fuck up at certain events when new music is playing. The previous code only sets bank when music is requested at FFE4. This isn't a bad fix, because you can't hear two musics at the same time anyway. :P
http://www.sonicforcecorp.talkhost.info/Er...s2musichack.rar - the ROM, with a new music for testing. First, play all songs from 01 to 1F in Options screen to make sure every original is still there. Then, enter DEZ by any way, or set level RAM address to 0E and play music 0A.
Now, here are the locations for all groups of 9 flags that serves to bank switching:
009Ah: SE
00D2h: DAC
062Ch: SE
06FAh: SEGA
097Bh: SE
0C6Fh: Continue
0C7Fh: Musics
0F3Fh: SE
If you want to make permanent changes in bank switching (in order to reallocate music), do the following:
- decompress sound driver with SDC;
- using a hex editor, go to a flag group location and change them;
- recompress the edited sound driver using SDC;
- put the new compressed sound driver back into the ROM, overwritting the old one in $EC0E8;
- fix the size of compressed sound driver at $EC050;
Side info:
- Z80 RAM's 0000-1FFF is 00474-02473 in GST savestates;
- You can use Korama's GSavestate for easy editing of Z80 RAM;
Special thanks to (no particular order):
drx - hosts Sega2f doc - http://www.hacking-cult.org
R. Solaris - helped me figuring out the meaning of bank switching in Sega2f doc
Tweaker - great music guide, plus sent me a music to test my sound driver experiments
M' (aka Kusanagi) - Portuguese friend. He gave me webspace at Sonic Force Corp.
MSN contacts who played my music hack and didn't leaked it (you know who you are)
First, let's put straight how music is accessed in S2. 68K code sets a RAM address ($FFFFFFE4) to have the value of the desired music. Somewhere else, one of those permanent functions checks that address to see if it has changed since last time. If so, it writes the music value to Z80 RAM ($A01B88). This last step involves more than a single move.b d0,$A01B88, because it's needed to stop Z80 processing before attempting to handle its data. After that, 68K makes Z80 resumes its operation. Z80 also has a constant function which checks to see if 1B88h is something but $80 (no music). Depending on that value, Z80 switches bank in order to play musics ($F8000), continue music (if $9C; F0000) or sound effects ($F8000). The bank is nothing but a space of $8000 bytes that is mirrored from a certain 68K memory space, so that's why music pointers in S2 are little-endian.
The bank switching, as said previously, isn't done by a single value assignment. On the other hand, it's done by a single memory address, which happens to be $A06000, or just 6000h for Z80. That's exactly what's written in Sega2f document:
Quote
2) BANK
From 8000H - FFFFH is window of 68K memory. Z-80 can access all of 68K memory by bank switching. bank select data create 68K address from A15 to A23. You must write these 9 bits one at a time into 6000H serially, byte units, using the LSB.
From 8000H - FFFFH is window of 68K memory. Z-80 can access all of 68K memory by bank switching. bank select data create 68K address from A15 to A23. You must write these 9 bits one at a time into 6000H serially, byte units, using the LSB.
What such masterpiece of English language is saying is that bank is determined by a sequence of 9 values written one after other to 6000h. It sounds strange, but it works, believe me :P. Now, why is it a sequence of 9 values? As banks rely on multiples of $8000, it was not hard for me to fugure what they mean. Heh, they're indeed bits, and as you know (I hope), a bit can be one out of two values: 0/1, yes/no, true/false, etc. So they're nothing but a bunch of flags for the following bank values:
$8000
$10000
$20000
$40000
$80000
$100000
$200000
$400000
$800000
Sum everything and you'll have $FF8000 which is the hightest bank Z80 can access (and also the last $8000 bytes of Genesis memory). Yes, Z80 can access 68K RAM, but I don't see any practical use for it, as it would limit working space for 68K. I'm not sure about 68K SRAM, but it should be accessible too.
So how S2 sound driver does bank switch? It's actually something weirder than a "move.b #1, 6000H", but it follows such pattern. Let's see part of a Z80 disassembly from S2:
00000C79: AF XOR A 00000C7A: 1E 01 LD E,01h 00000C7C: 21 00 60 LD HL,6000h 00000C7F: 73 LD (HL),E 00000C80: 73 LD (HL),E 00000C81: 73 LD (HL),E 00000C82: 73 LD (HL),E 00000C83: 73 LD (HL),E 00000C84: 77 LD (HL),A 00000C85: 77 LD (HL),A 00000C86: 77 LD (HL),A 00000C87: 77 LD (HL),A
This is always used for bank switching in S2. This part refers to the bank for musics but continue ($9C). LD (HL),E does the role of 1 and LD (HL),A does the same for 0. In byte terms, 73 is 1 and 77 is 0, for this case (and the rest of S2 sound driver). If you align that with the bank values you'll get $F8000, which is where music is stored in S2. During the Z80 halt in 68K code, before writing the value at 1B88h, you can put a check to see if certain condition is true, so you can alternate between one bank or other in order to play more musics than $1F - you still use the same values for music; the use of unused values like those after $70 in Sound Test is possible, but it requires Z80 reprogramming which I'm not able to do with my current knowledge, plus this method is enough for all S2 hacks that demands more musics.
Using the code shown above as "guinea pig", here's the code for a little music hack I did:
http://www.sonicforc...S/soundplay.txt - the code was compiled and inserted into unused space in ROM, and in $1084 I put a jmp code location.
http://www.sonicforc...JS/soundfix.txt - this is a fix for when musics are played through FFE2 due to SEGA's bad programming, because the funtion at $1376 is supposed to play SE. This will redirect sound requests lower than $A0 to 135E. Just compile and put a jmp code location in 1376. If this fix is not applied, sound $98 will fuck up at certain events when new music is playing. The previous code only sets bank when music is requested at FFE4. This isn't a bad fix, because you can't hear two musics at the same time anyway. :P
http://www.sonicforcecorp.talkhost.info/Er...s2musichack.rar - the ROM, with a new music for testing. First, play all songs from 01 to 1F in Options screen to make sure every original is still there. Then, enter DEZ by any way, or set level RAM address to 0E and play music 0A.
Now, here are the locations for all groups of 9 flags that serves to bank switching:
009Ah: SE
00D2h: DAC
062Ch: SE
06FAh: SEGA
097Bh: SE
0C6Fh: Continue
0C7Fh: Musics
0F3Fh: SE
If you want to make permanent changes in bank switching (in order to reallocate music), do the following:
- decompress sound driver with SDC;
- using a hex editor, go to a flag group location and change them;
- recompress the edited sound driver using SDC;
- put the new compressed sound driver back into the ROM, overwritting the old one in $EC0E8;
- fix the size of compressed sound driver at $EC050;
Side info:
- Z80 RAM's 0000-1FFF is 00474-02473 in GST savestates;
- You can use Korama's GSavestate for easy editing of Z80 RAM;
Special thanks to (no particular order):
drx - hosts Sega2f doc - http://www.hacking-cult.org
R. Solaris - helped me figuring out the meaning of bank switching in Sega2f doc
Tweaker - great music guide, plus sent me a music to test my sound driver experiments
M' (aka Kusanagi) - Portuguese friend. He gave me webspace at Sonic Force Corp.
MSN contacts who played my music hack and didn't leaked it (you know who you are)


00