Music Notes

By the way, if you want to disable particular channels in a CT SPC file, you can hex edit bytes 01F4 and 01F5 in the SPC file. Those are 00F4 and 00F5 in the SPC700 memory space, representing the communication port with the 65816. Put F4 at 01F4 and a bitmask of the channels to disable at 01F5; F4 05 disables sound channels 0 and 2.

These are the commands I've found. F4 gets the command byte; F5 and F6 are xx and yy respectively. I haven't found anything using zz (F7). Many commands cause playback to stop regardless of parameters; most of these are likely crashes and some are the code going into a wait state.

Note: When Geiger was writing his offsets guide he seems to have mistakenly assumed that the BRR samples start with "(00) Silence". They actually start with "(01) Clap". As a result the labels for the samples in the offsets guide are all off by one. The last valid instrument is actually 3E, which seems to be a cuica.

I put "unused" in quotes because it actually does show up in the instrument table for the "song" "{4C} Lavos Breath", but that song is all crazy noise effects that I don't have a full understanding of. It never actually plays it as a straight instrument sample.

18 - play sound effect
  xx = effect ID
     00 = move cursor
     01 = menu "bzzt"
     02 = miss attack
     03 = high-pitched ding
     04 = bling; sound from acquiring something
     05 = sound from initial activating of time portal
     06 = sound of being healed
     07 = falling pitch bling
     08 = sound of pulling out sword at beginning of battle
     09 = rising sound effect, hard to describe or place
     0A = sound of something moving through bushes
     0B = high-pitched sound to draw your attention to something
     many other sound effects here, with a gap at 0C
  yy = panning for sound effect
     00 = left
     80 = middle
     FF = right

19 - play sound effect; same as 18?

80 - volume control
  xx = number of ticks in which to fade out
     00 = now
     FF = about 7 seconds
  yy = volume
     00 = off
     FF = normal

81 - volume control; same as 80?

85 - song raw speed (tempo and pitch together)
  xx = time to slide to desired setting
     00 = instant
     FF = about 7 seconds
  yy = raw speed modifier
     80 = slowest
     00 = normal
     7F = fastest

86 - song tempo
  xx = time to slide to desired setting
     00 = instant
     FF = about 7 seconds
  yy = tempo modifier
     80 = slowest
     00 = normal
     7F = fastest

87 - song pitch
  xx = time to slide to desired setting
     00 = instant
     FF = about 7 seconds
  yy = tempo modifier
     80 = lowest
     00 = normal
     7F = highest

88 - event control
  xx = event enable
     00 = no event
     01 = event will occur next time mark passes, if one exists

F4 - channel disable
  xx = bitmask of channels to disable

F5 - playback disable
  xx = whether to enable
     00 = enabled
     01 = disabled

F6 - max tempo enable
  xx = whether to enable
     00 = disabled
     01 = enabled

F8 - disable single channel
  xx = channel number

F9 - enable single channel
  xx = channel number

FC - unknown effect on channels
  xx = channel bitmask to enable effect

FE - seems to switch to some kind of download mode

FF - reset
  xx = what to do
    01 = unknown effect
    FF = full reset; jumps to SPC's boot ROM
    other = no effect

I do know from the assembly code that 10-1F, 80-8F and F0-FF are the only valid command ranges. Commands 84, 8A, 8B, 8C, 8D, 8F, F7, FA and FB have blank handlers so do nothing. I found the dispatcher for 8x and Fx but not 1x yet. 00 on the F4 port means no command as a special case.

Geiger: Not sure how the APU handles it, but the preprocessor in the CPU code can handle a much larger range. I'm not sure how many of these commands will get stored to the APU, but the section of code from C70907 to C70912 stores E0 to special registers 2140 and 2141 (which correspond to F4 and F5 respectively in the APU). In order to get to this code, the command issued to the preprocessor must be 70, with the first parameter being different from 7E1E11 (not sure what that is). The preprocessor then sends the APU the FE command first, and then E0.

Thanks to Myria

From: Offsets (Chrono Trigger)