HUDSON SFX SOUND DRIVER (Super Bomberman 5, etc.) Specification

This document explains about Hudson SFX SOUND DRIVER, through my Super Bomberman 5 analysis knowledge. It also mentions other versions of the driver.

MIDI conversion tool (hudspc) is available at https://code.google.com/p/loveemu/

SNES SPC700 Player and SPC700 Memory Viewer (SPCMEM) was very useful during the analysis.

日本語で読む

Summary

The driver which is used by Super Bomberman 5, is called "SFX SOUND DRIVER". The driver usually writes its version to APU RAM.

Example: SFX SOUND DRIVER Version 1.16 Copyright(c) 1993,94 Hudson Soft Program : LU.Iwabuchi Driver : Kazumi-TYPE

There are a lot of slightly different versions. However, they can be classified roughly in Ver 1.xx and Ver 2.xx.

The following is the list of games which use SFX SOUND DRIVER.

  • No Version String
    • Super Bomberman 2 (mostly 1.xx compatible)
    • Hagane (mostly 1.xx compatible)
    • An American Tail: Fievel Goes West (1.xx compatible?)
  • Version 1.xx
    • Super Bomberman 3 (1.16)
    • Super Genjin 2 (1.16E)
    • Caravan Shooting Collection (1.17s)
  • Version 2.xx
    • Do-Re-Mi Fantasy (2.10)
    • Tengai Makyou Zero (2.27b)
    • Super Bomberman 4 (2.28)
    • Kishin Douji Zenki 3 (2.28)
    • Same Game (2.30a)
    • Super Bomberman 5 (2.32)
    • Bomberman B-Daman (2.32)

This document will show the spec of Ver 2.xx by using Super Bomberman 5 for reference. Then, it will show the difference between Ver 1.xx and Ver 2.xx by using Super Bomberman 3 for reference.

Whole Structure

  • Note: Numbers are stored in little-endian.
  • Note: Addresses ($xxxx) in this document are APU RAM address. You can convert the RAM address to an offset in SPC file, by adding 0x100 to the address.

Whole structure of sound data on APU RAM is something like the following.

[Explanatory Chart]
Region Name ($xxxx : starting address)
  + Address 1: Field Name 1 = $yyyy Example of value
  + Address 2: Field Name 2 = $zzzz Example of value

[Music Data Structure Sample]
Music Data Pointer Region
  + 0803: Music Data Region Pointer = $3000

  Music Data Region ($3000)
    + 3000: Song List Pointer = $3002

    Song List Region ($3002)
      + 3002: Song Header Pointer 1 = $35b6
      + 3004: Song Header Pointer 2 = $xxxx

      Song Header Region ($35b6)
        + 35b6: Header Events (Variable Length)

In the case of Super Bomberman 5, you can access to the song data sequentially from $0803.

Since the driver can have and use multiple songs in APU RAM, it has song list region prior to an individual song. The first song is used in most cases. Some jingles might be at the second song.

You can access a song header from the song list. The next section explain the detail of the header.

Song Header

Like a usual song data, a song header is a collection of header events. The first byte specifies the type of the header event, and the following bytes can be parameters (length depends on the event type). Header event 00 means the end of header.

Score data locations for each channels must be specified by a header event.

The following is the list of song header events.

  • 00 - End Of Header
  • 01 xx .. - Set Channel Addresses
  • 02 xx - Set Timebase
  • 03 xx .. - Set Instrument Table
  • 04 xx .. - Set Rhythm Kit Table
  • 05 xx .. - Set Unknown Table 1
  • 06 xx .. - Set Unknown Table 2
  • 07 xx .. - Set Initial Echo Parameters
  • 08 xx - Set Unknown Byte
  • 09 xx .. - Set Unknown Table 3
01 xx .. [Set Channel Addresses]

This event can specify which channel is used, and set start address of them.

The first byte specifies which channel is used. Each bits is a flag for each channels.

87654321 : bit (channel number)
xxxxxxxx : 1=active, 0=inactive

Address of each channel is located after the first byte. The number of addresses must be determined how many channels will be active. Smallest channel appears at the first.

[Example Of Header Event 01]
Header Event 01
  + 35b5: $01
  + 35b6: Channel Active/Inactive Flags (1 byte) = $ff
  + 35b7: Score Data Address 1 = $4222
  + 35b9: Score Data Address 2 = $4303
                   : (continues for all active channels, maximum count is 8)

Score Data 1 ($4222)
  + 4222: ...
Score Data 2 ($4303)
  + 4303: ...
          :
02 xx [Set Timebase]

This event can set timebase. xx must be in the range of 0-3. Actual timebase value will be (48 >> xx).

03 xx .. [Set Instrument Table]

This event can set instrument table address. An instrument table has SRCN and ADSR information for each instruments.

xx is the number of elements in the table. The table contents continue after it for (xx * 4) bytes.

An instrument table has the following fields.

  • 00: SRCN
  • 01: ADSR(1)
  • 02: ADSR(2)
  • 03: GAIN
04 xx .. [Set Rhythm Kit Table]

This event can set rhythm kit table address. The table is used when rhythm kit mode is turned on by FE 03. It determines instruments, volumes, etc. for each note numbers.

xx is the number of elements in the table. The table contents continue after it for (xx * 4) bytes.

An rhythm kit table has the following fields.

  • 00: Instrument # (same as event D6)
  • 01: Note Number (0-71)
  • 02: Volume (same as event D9)
  • 03: Panpot (same as event DA)
05 xx .. [Unknown Table]

This event can set a table address. The usage of the table is not analyzed yet.

xx is the number of elements in the table. The table contents continue after it for (xx * 2) bytes.

06 xx .. [Unknown Table 2]

This event can set a table address. The usage of the table is not analyzed yet.

xx is the number of elements in the table. The table contents continue after it for (xx * 2) bytes.

07 xx .. [Initial Echo Settings]

This event can set initial echo settings of the song. This event is a variable-length event, and the first byte determines the length.

When the first byte xx is 0, values of echo registers will continue after it. The values will appear in order of EVOL(L), EVOL(R), EDL, EFB, FIR #, EON.

When the first byte xx is not 0, it will take no additional parameters, and it applies a default echo settings. Default echo settings are probably located at $0858.

08 xx [Unknown Byte]

Unknown event.

09 xx .. [Unknown Table 3]

This event can set a table address. The usage of the table is not analyzed yet.

xx is the number of elements in the table. The table contents continue after it for (xx * 2) bytes.

00 [End Of Header]

This event must exist at the end of header.

After the process of those header events, the music engine will start playing the song by parsing the score of each channel addresses set by header event 01.

Score Data

The music engine is internally tick-based. Timebase (TPQN) can be chosen from 48, 24, 12 and 6, and the default timebase is 12. (see header event 02 for details)

The following is the list of score events.

  • 00~CF (xx) - Rest/Note (Variable-Length Event)
  • D0 - ?
  • D1 xx - Set Tempo
  • D2 xx - Set Octave
  • D3 - Octave Up
  • D4 - Octave Down
  • D5 xx - Set Quantize
  • D6 xx - Set Instrument
  • D7 - NOP
  • D8 - NOP
  • D9 xx - Set Volume
  • DA xx - Set Panpot
  • DB xx - Set Reverse-Phase
  • DC xx - Increase/Decrease Volume
  • DD xx - Repeat Start
  • DE - Repeat End
  • DF xx yy - Subroutine Call
  • E0 xx yy - Jump
  • E1 xx - Tuning
  • E2 xx yy zz - Set Vibrato
  • E3 xx - Set Vibrato Delay
  • E4 xx yy - Set Echo Volume
  • E5 xx yy zz - Set Echo Delay, Feedback, FIR
  • E6 - Echo On
  • E7 xx - Key Shift (Absolute)
  • E8 xx - Key Shift (Relative)
  • E9 xx yy zz - Set Attack Pitch Envelope
  • EA - Set Attack Pitch Envelope Off
  • EB - Set Song Loop Point
  • EC - Jump To Song Loop Point
  • ED - Set Song Loop Point (Works Only Once)
  • EE xx - NOP
  • EF xx yy - ?
  • F0 xx - ?
  • F1 xx yy - Set Portamento
  • F2 xx - ?
  • F3 xx - ?
  • F4~FD - NOP
  • FE xx .. - Subevents
  • FF - End Of Subroutine / End Of Track
00~CF (xx) [Rest/Note] (Variable-Length Event)

The note byte itself work as a parameter.

[Bits of Note Byte]
kkkkslll
  k : Key (0~11) 0=C, 1=C# ... 11=B
  s : Slur/Tie (1=on, 0=off)
  l : Length (0~7)

The key of note is specified by bits 4~7. Octave can be specified by another event. (see event D2~D4)

Slue/Tie bit is used when the note will be combined to the next note. (the next note will just change the pitch and keep volume envelopes)

If the length field is 0, the next byte (xx) is the actual note length (in ticks).

If the length field is not 0, it will not take an additional parameter, and the note length is determined from the following table.

Value Length Ticks (in case of TPQN=48)
1 Whole Note 192
2 Half Note 96
3 Quarter Note 48
4 Eighth Note 24
5 Sixteenth Note 12
6 Thirty-second Note 6
7 Sixty-fourth Note 3

If timebase is halved (TPQN=24), ticks are halved like the following.

Value Length Ticks (in case of TPQN=24)
1 Whole Note 96
2 Half Note 48
3 Quarter Note 24
4 Eighth Note 12
5 Sixteenth Note 6
6 Thirty-second Note 3
7 Sixty-fourth Note 1.5

Note that the music engine will handle the decimal part of 1.5 ticks. Do not use sixteenth note if TPQN is less than 24, or the music engine will read the out of table range and perform unexpectedly.

The actual "duration" of the note can be adjusted by quantize event. (see event D5)

D0 [?]

Unknown event.

D1 xx [Set Tempo]

Set tempo in BPM. Default value is 120.

D2 xx [Set Octave]

Set octave in the range of 0~5.

D3 [Octave Up]

Increase octave, if the current octave is not 5 (maximum value).

D4 [Octave Down]

Decrease octave, if the current octave is not 0 (minimum value).

D5 xx [Set Quantize]

Set quantize (duration rate of note).

xx=0~8
Duration will be (L * xx / 8). (where L is the full length of a note, in ticks)
xx=9~
Duration will be (L - (xx - 8)).
D6 xx [Set Instrument]

Set instrument. Actual sample number and ADSR envelopes are obtained from xxth element of instrument table. (see header event 03)

D9 xx [Set Volume]

Set channel volume. xx is treated as a signed value, and is clipped in the range of 0~79.

Actual volume amount is determined by the following table.

const byte volTableV2[] = {
    0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02,
    0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03,
    0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05,
    0x05, 0x06, 0x06, 0x06, 0x07, 0x07, 0x08, 0x08,
    0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0d,
    0x0e, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
    0x15, 0x17, 0x18, 0x1a, 0x1b, 0x1d, 0x1e, 0x20,
    0x22, 0x24, 0x26, 0x28, 0x2b, 0x2d, 0x30, 0x33,
    0x36, 0x39, 0x3d, 0x40, 0x44, 0x48, 0x4c, 0x51,
    0x56, 0x5b, 0x60, 0x66, 0x6c, 0x72, 0x79, 0x80,
};
DA xx [Set Panpot]

Set panpot. xx is treated as a signed value, and is clipped in the range of 0~30. 0 is the most right, 15 is the center, and 30 is the most left. (note that the direction is opposite from MIDI)

Actual volume balance is determined by the following table.

const byte panTable[] = {
    0x00, 0x07, 0x0d, 0x14, 0x1a, 0x21, 0x27, 0x2e,
    0x34, 0x3a, 0x40, 0x45, 0x4b, 0x50, 0x55, 0x5a,
    0x5e, 0x63, 0x67, 0x6b, 0x6e, 0x71, 0x74, 0x77,
    0x79, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x7f,
};
DB xx [Set Reverse-Phase]

Set reverse-phase switch for left/right speaker (per-channel event). 0 for no-reverse, +2 for reverse-left, and +1 for reverse-right.

DC xx [Increase/Decrease Volume]

Increase or decrease volume which is set by event D9. xx is a signed value, and it is added to the current volume (clipped to 0~79).

DD xx [Repeat Start]

Repeat playing the phrase surrounded by event DD and DE for xx times (0 means 256 times). Those events can be nested.

This event will push 3 bytes to the return address stack. Since the stack size is 16 bytes, maximum nest level is 5. Also, the stack is shared with Call-Return events.

DE [Repeat End]

Specifies the end of repeat. (see event DD)

Jump to the repeat start address, until the phrase is repeated for specified times.

DF xx yy [Subroutine Call]

Jump to $yyxx, and can return from there by event FF.

This event will push 2 bytes to the return address stack. Since the stack size is 16 bytes, maximum nest level is 8. Also, the stack is shared with Repeat events.

FF [End Of Subroutine / End Of Track]

Jump to the return address saved by event DF. If it's not in subroutine, stop the activity of the channel.

E0 xx yy [Jump]

Jump to $yyxx (goto).

This event is usually not used, because some other events are available for setting an infinite loop.

EB [Set Song Loop Point]

Set loop point to this position. (see event EC)

EC [Jump To Song Loop Point]

Jump to the loop point set by event EB. If no loop point is set, it will jump to the beginning.

ED [Set Song Loop Point (Works Only Once)]

Set loop point to this position. This event works the same as event EB, except it only works the first time. Event EB can work regardless of this event.

E1 xx [Tuning]

Adjust the pitch of note. Amount is (xx / 256 * 100) cents.

E2 xx yy zz [Set Vibrato]

Set vibrato (pitch LFO).

xx
Vibrato Speed ?
yy
Vibrato Depth ?
zz
?
E3 xx [Set Vibrato Delay]

Set vibrato delay, the amount of time that elapses from when a key is played to when the Vibrato effect starts. The higher the value, the longer the delay before the onset of the Vibrato effect.

E4 xx yy [Set Echo Volume]

Set echo volume.

xx
Echo Volume (L)
yy
Echo Volume (R)
E5 xx yy zz [Set Echo Delay, Feedback, FIR]

Set echo parameters.

xx
Echo Delay
yy
Echo Feedback
zz
Echo FIR # (0~17?)

I'm not sure about the valid range of FIR #, but I think the following ones are allowed.

00: 7f 00 00 00 00 00 00 00
01: 58 bf db f0 fe 07 0c 0c
02: 0c 21 2b 2b 13 fe f3 f9
03: 34 33 00 d9 e5 01 fc eb
04: 23 ca f8 2c eb 08 fb 02
05: 04 f9 f8 27 27 f8 f9 04
06: 14 ff da 1d 1f e0 ff 0c
07: 1b db 33 f2 fd 0e fc fd
08: 3b ba 13 1b 02 f6 fd 01
09: 29 b9 fd 24 0d f7 fa 00
0a: 35 a8 ff 1a 12 04 f8 fb
0b: 1c cc 2f ec f8 12 00 fa
0c: 3b ba 13 1b 02 f6 fd 01
0d: fa 00 1c 29 29 1c 00 fa
0e: fe fd 16 34 34 16 fd fc
0f: fe fb 10 3a 3a 10 fb fe
10: 48 26 0a dd 08 0d f9 00
11: 38 48 14 e6 01 0a fe fe
E6 [Echo On]

Enable channel echo. To disable echo, use event FE.

E7 xx [Key Shift (Absolute)]

Set the transpose amount to xx semitones, where xx is a signed value.

E8 xx [Key Shift (Relative)]

Increase (Decrease) the transpose amount to by xx semitones, where xx is a signed value.

E9 xx yy zz [Set Attack Pitch Envelope]

Turn pitch slider on, to make the pitch change at key-on.

xx
Pitch Envelope Speed
yy
Pitch Envelope Depth
zz
Direction (0=from up to down, otherwise=from down to up)
EA [Set Attack Pitch Envelope Off]

Disable the pitch envelope set by event E9.

F1 xx yy [Set Portamento]

Set portamento (also called as slide, sweep).

xx
Portamento Speed (0=portamento off)
yy
Not Used? (usually 0)
FE xx .. [Subevents]

Do various operations specified by xx. Valid range of xx is 0x00~0x1f. The length of event depends on xx.

NOP (No Operations)

Do nothing.

Subevents (vcmd FE)

FE 00

Stop activity of the channel. This event works the same as event FF with no subroutines.

FE 01

Disable channel echo. To enable echo, use event E6.

FE 03

Turn rhythm kit mode on. When it is on, each note numbers can have a different sample, just like MIDI drums. See header event 04 for detail of note-instrument mappings.

FE 04

Turn rhythm kit mode off.

NOP (No Operations)
  • FE 05
  • FE 06
  • FE 07
  • FE 0E
  • FE 0F

Do nothing.

Operator Events
  • FE 10 xx yy (mov rxx, #yy)
  • FE 11 xx yy (mov rxx, ryy)
  • FE 12 xx yy (cmp rxx, #yy)
  • FE 13 xx yy (cmp rxx, ryy)
  • FE 14 xx yy (bne $yyxx)
  • FE 15 xx yy (beq $yyxx)
  • FE 16 xx yy (bcs $yyxx)
  • FE 17 xx yy (bcc $yyxx)
  • FE 18 xx yy (bmi $yyxx)
  • FE 19 xx yy (bpl $yyxx)

Do pseudo CPU operations. Pseudo registers r00~r07 can be used for operation. Registers are shared with each channels.

ADSR Envelopes
  • FE 1A xx (AR)
  • FE 1B xx (DR)
  • FE 1C xx (SL)
  • FE 1D xx (SR)
  • FE 1E xx (pseudo release-rate using GAIN)

Set ADSR envelopes. Though hardware envelope of DSP does not have Release Rate, the music engine will set (0xa0 | xx) to GAIN at the software key-off timing.

Unknown Events
  • FE 02
  • FE 08
  • FE 09
  • FE 0A
  • FE 0B
  • FE 0C
  • FE 0D xx

Differences from Super Bomberman 3

This section explains about the differences between ver 1.x and ver 2.x, through my Super Bomberman 3 analysis knowledge.

Root Address

In the case of Super Bomberman 5, you can access to the song data sequentially from $0803.

In the case of Super Bomberman 3, the root address is $07c2.

In the case of Super Bomberman 2, the root address is $000d.

Song Header

In ver 2.xx, channel addresses are defined through the header event 01. In ver 1.xx, the parameter part of header event 01 must come at the beginning of header, and additional header events continue after it.

[Example of Song Header 1.xx]
ff          ; same as header event 01 of ver 2.xx (bitflags and addresses)
   00 40
   00 41
   00 42
   00 43
   00 44
   00 45
   00 46
   00 47
01 02       ; header event 01 (timebase)
00          ; header event 00 (end of header)

Also, header events are listed in a different order. Ver 1.xx has less events.

  • 00 - End Of Header
  • 01 xx - Set Timebase
  • 02 xx .. - Set Instrument Table (Old)
  • 03 xx .. - Set Rhythm Kit Table (Old)
  • 04 xx .. - Set Instrument Table
  • 05 xx .. - Set Unknown Table
02 xx .. [Set Instrument Table (Old)]

This event can set instrument table address. xx is the length of the table (in bytes).

03 xx .. [Set Rhythm Kit Table (Old)]

This event can set rhythm kit table address. xx is the length of the table (in bytes).

Score Data

Some events have different behavior.

  • D0 - NOP
  • D7 xx - NOP (2 bytes)
  • D8 xx - NOP (2 bytes)
  • D9 xx - Set Volume
  • DA xx - Set Panpot
  • E2 xx yy - Set Vibrato
  • EE xx - Set Volume From Table
  • F2~FD - NOP
  • FE xx .. - Subevents
D9 xx [Set Volume]

Set channel volume. xx is treated as a unsigned value.

Unlike ver 2.xx, it does not use any tables and it sets volume value directly. Event EE is more similar to ver 2.xx, which sets the volume from a table. (Super Bomberman 3 prefers event EE rather than this event)

DA xx [Set Panpot]

Set panpot. xx is must be in the range of 0~30.

This event works the same as ver 2.xx, except the range check. When xx is more than 30, the music engine will perform unexpectedly.

E2 xx yy [Set Vibrato]

Set vibrato (pitch LFO). Parameters are less than ver 2.xx.

xx
Vibrato Speed
yy
Vibrato Depth
EE xx [Set Volume From Table]

Set channel volume. xx is treated as a unsigned value, and is clipped in the range of 0~90.

Actual volume amount is determined by the following table.

const byte volTable[] = {
    0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
    0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
    0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
    0x06, 0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09,
    0x09, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0d, 0x0e,
    0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
    0x17, 0x18, 0x1a, 0x1b, 0x1d, 0x1e, 0x20, 0x22,
    0x24, 0x26, 0x28, 0x2b, 0x2d, 0x30, 0x33, 0x36,
    0x39, 0x3c, 0x40, 0x44, 0x48, 0x4c, 0x51, 0x55,
    0x5a, 0x60, 0x66, 0x6c, 0x72, 0x79, 0x80, 0x87,
    0x8f, 0x98, 0xa1, 0xaa, 0xb5, 0xbf, 0xcb, 0xd7,
    0xe3, 0xf1, 0xff,
};
FE xx .. [Subevents]

Do various operations specified by xx. Valid range of xx is 0x00~0x09. The following events are different from ver 2.xx.

  • FE 05
  • FE 06
  • FE 07

Set vibrato type to 0, 1 or 2. Actually vibrato type 2 works the same as type 1.

0
Full form, pitch changes up and down from the base pitch.
1
Half form, pitch changes up from the base pitch, but will never change down than base pitch. (vibrato speed will also be faster)