More on using a smaller FM frequencies table, this time for S2's driver. Also, info on a strange bug in S3K's driver.
Because of the nature of SMPS Z80 drivers, you may prioritise size over speed. If so, you may want to use a much smaller FM frequencies table, as seen in S3K's driver (modified SMPS Z80 Type 2). Despite being cousins in terms of relation (S2's driver is a Z80 port of an evolved SMPS 68k), S3K's code works near-perfectly in S2's driver, so we'll see about porting across this feature, using the very code S3K uses.
First, you need to follow the driver-related instructions
here to relocate the frequency tables, otherwise the DAC playback will be broken. Note that adding the S3K frequencies is optional, and not required for this.
zFMSetFreq, in s2.sounddriver.asm. Above 'add a,a', add this code:
ld d, 8 ; Each octave above the first adds this to frequency high bits
ld e, 0Ch ; 12 notes per octave
ex af, af' ; Exchange af with af'
push af
xor a ; Clear a (which will clear a')
- ex af,af' ; Exchange af with af'
sub e ; Subtract 1 octave from the note
jr c,+ ; If this is less than zero, we are done
ex af,af' ; Exchange af with af'
add a,d ; One octave up
jr - ; Loop
+
add a,e ; Add 1 octave back (so note index is positive)
(You can find the unmodified version of this code in S3K's driver under
zGetNextNote_cont)
This is responsible for the bulk of the calculation. In S2's driver, af' is used by the DAC playback, so we'll need to preserve its contents, as done by the 'push af'.
After 'ld de,(zFrequencies)', add in this code:
ex af, af' ; Exchange af with af'
or d ; a = high bits of frequency (including octave bits, which were in a)
ld d, a ; h = high bits of frequency (including octave bits)
pop af
ex af, af' ; Exchange af with af'
This code has seen significant modification from its source: using the correct register for the pointer, and restoring af'.
Now navigate to zFrequencies, and remove all but the first line of values.
You should now be clear to build and test. However, you will likely notice one strange bug: the spin dash release sound will play incorrectly. Analysis of S3K's copy of this sound shows that it has been modified from its S2 form. The most notable change is this:
In s2.asm, go to Sound3C. The value '$9000' has been changed to '$0000'. Making this change to your sound will fix the bug. But we will not leave it at that. Let the value remain $9000.
What that modification does is change the FM5 channel's pitch from $90 to $00. This pitch of $90 is unusual, as most other SFXs use values much closer to $00. It is possible that this value is a mistake.
You see, $90 is $10 with the sign bit set. $10 being much closer to $00, and even sounds exactly the same if used instead of $90. What pushes the idea of this being an error further is that, in an unmodified zFMSetFreq, the sign bit would be lost in the calculations. Most obviously at 'add a,a', where the sign bit would be lost to overflow. Our problem is that the code we ported from S3K doesn't have a chance to remove the sign bit, so it counts the value's octave incorrectly, leading to the sound playing incorrectly. While we could change the pitch value of the sound itself, a safer, more effective solution would be to modify S3K's code to remove the sign bit of the value:
Back in zFMSetFreq, above 'ld d, 8', add the instruction 'res 7,a'. This will remove the troublesome bit before the calculations are made. Test this new build to find that the bug has been fixed.
Note that this bug exists in S3K's driver. This can be seen by importing S2's spin dash release sound to the driver, and trying to play it.