The sound effects stored in the Sound Driver files is similar to the music data stored in M Files.

Extracting the FilesEdit

The sound effects are stored at different places in each driver. For PROMUS from the non-CD version of INTRO.CC, there is an array of offsets beginning at 0x0ADC that give the actual offsets of the sound effects.

FM CommandsEdit

As with the music commands, the high nibble of the command byte is the actual command, while the low nibble is data, typically a channel number. Some commands that are used in M Files appear to not be used in sound effects.

CommandData BytesDescription
00 Unused. Appears in only one effect (015), but it appears to be a typo.
10 0 or 1 Pause execution of commands. If the low nibble is nonzero, it is the number of cycles to skip. Otherwise, the following byte is the number of cycles to skip.
20 22 Loads an instrument into memory, in an index indicated by the low nibble. The 11 bytes of instrument data are duplicated.
30 2 Sets volume. Unsure exactly how this works.
40 Unused.
50 Unused.
60 Unknown functionality, used in only one effect (009). The low nibble indicates a channel.
70 0 Turn off the channel indicated by the low nibble.
80 1 "plays" a note without the 0x2000 bit set, stopping the note. Acts on the channel indicated by the low nibble.
90 1 Play the note indicated by the data byte on the channel indicated by the low nibble.
A0 Unused.
B0 Unused.
C0 1 Sets the instrument indicated by the data byte on the channel indicated by the low nibble.
D0 0 Stops the "growl" command on the channel indicated by the low nibble.
E0 3 "growl" command. Modifies the playing frequency in a complex manner every interrupt, even when command execution is paused. Acts on the channel indicated by the low nibble.
F0 0 Terminate the sound effect and loop if the low nibble is F. Low nibble of E or C indicates non-looping behavior.

Growl CommandEdit

The first data byte is a counter increment value. The second and third data bytes are a 16-bit big-endian signed frequency increment value. The following pseudocode describes the algorithm used. The end effect is a rapidly fluctuating frequency that sounds like a growl.

//increment counter, stop if no overflow
growlCounter[chan] += growlIncrement[chan];
if(growlCounter[chan] <= 0xFF) {
growlCounter[chan] &= 0xFF;

//make this look just like the assembly
int registerB, registerDlow, registerDhigh;

registerB = playingFrequencies[chan];
registerDlow = (registerB >> 8) & 0x1C;
registerDhigh = (registerB >> 8) & 0x20;
registerB &= 0x3FF;

registerB = (registerB + growlParameter[chan]) & 0xFFFF;
if( (growlParameter[chan] & 0x8000) > 0 ) {
	//"negative" parameter
	if( registerB <= 0x0184 ) {
		registerB *= 2;
		if( (registerB & 0x03FF) == 0 ) {
			registerB = 0x03FF;
		registerDlow = (registerDlow + 0xFC) & 0x1C;
else {
	//"positive" parameter
	if( registerB >= 0x02DE ) {
		registerB /= 2;
		if( (registerB & 0x03FF) == 0 ) {
			registerB = 0x0001;
		registerDlow = (registerDlow + 0x04) & 0x1C;

registerB &= 0x03FF;
registerB |= registerDlow << 8;
registerB |= registerDhigh << 8;

playingFrequencies[chan] = registerB;
playChanFreq(chan, registerB);


Sound effect 125, used by the Yak Priest, Sorceress, and Wizard in Clouds, runs from offset 0x23CF to 0x23F4.

CommandData Bytes
20 CE 00 30 00 03 C7 02 30 06 00 00 CE 00 30 00 03 C7 02 30 06 00 00
C8 00
38 03 00
38 04 00
98 E4
10 FF
10 80

An instrument is defined and loaded, volume is set, a note is played, then a pause before termination. This is the simplest possible sound effect.

To actually play the sound effect, it needs to be converted into raw OPL register writes to be sent to an FM synthesizer.

To set the instrument:
32ce 5200 7230 9200 f203 (left)
35c7 5502 7530 9506 f500 (right)
c800 (feedback)

To set the volume: (TODO: is this right? it's what dosbox captures, but I don't know how the values are calculated)
5502 5500

To play the note
a8ce b81d ( 0x1DCE = 0x1C00 + 0x01Ce = (0xE0 << 5) + note_array[0x04] )
a8ce b83d ( 0x3DCE = 0x1DCE | 0x2000 )

The IMF file format is the simplest possible format to support playing such data, as it is simply a list of register writes interleaved with delays between writes. Unfortunately, the wiki doesn't allow uploading IMF files, so here's an ogg: Media:PROMUS_125.ogg

Ad blocker interference detected!

Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.