Me and MarkeyJester were working on documenting the Westone sound driver during our vacation. We documented most of the driver par a few confusing details, and I continued work on disassembling the tracker data and documenting the bank itself. Here is all the information we have about the driver. I realize this is quite a TL;DR topic, so I don't expect anyone to read this fully. What I suspect you'd be most interested in, is the sound test mod, source code, tracker data disassembler, and information about instruments. We have disassembled the Wonderboy in Monster World version of the driver, although I have noticed some improvements in Monster World IV and Mega Bomberman drivers; These versions of the drivers are still undocumented so not all changes are found more than likely. I will not explain the differences past few interesting tidbits. Also, all offsets and specific info will be based on the Wonderboy in Monster World version of the driver. Spoiler: 68000 side The 68000 side of the driver is slightly interesting compared to many other drivers I've seen. The sound driver is loaded at $306, which is pretty standard-looking routine, with the exception it reads the size of the sound driver from the uncompressed sound driver binary itself. The main sound driver binary starts at $98000, which is also the data bank used in the game. The size of the sound driver is reported to be 1A77h bytes long, however last 2 bytes do not seem like they are used by the sound driver in any way. Music loading is an interesting bit; Instead of using the normal 2-4 bytes for sound ID's, it actually uses $10 bytes, with a rotating buffer. The music loading subroutine at $366 basically first checks if Z80 is accessing the sound queue. If so, it waits until Z80 is not accessing it. Then it reads the position of where Z80 is accessing the queue, adds the counter (number of sounds played that Z80 has not processed yet), wraps it around by $F, and then adds in the sound queue position. Then, it uses that as an index to Z80 memory, writes the ID, and increments the counter by 1. Complicated, I know, but it allows you to have a lot of sounds played during the same frame, and as the driver uses slotted channels instead of static ones, it can play more sounds generally. There is also a subroutine at $D9A2, which seems to manually control music volume. The purpose of this subroutine is still unknown. Spoiler: Sound Test + ID's I have made a sound test hack for Wonderboy in Monster World, and along with it, extracted all the sound effects I am familiar with. Here is a list of those: Code: -Music- 00 - Cave 1, Mushroom cave 01 - Beginning music 02 - Lilypad and Childam 03 - Sky, before sky fortress 04 - Desert 05 - Castle and outside the castle in the beginning 06 - Pyramid 07 - Cave after Queen Eleanora 08 - Generic boss theme used by Gragg & Glagg, Ice Bomber, 09 - Jungle music before beating the tribe 0A - Alsedo, and the underwater temple 0B - Eleanora 0C - Beach areas 0D - Jungle, normal 0E - Boss theme used by Tyrant Dragon 0F - Begonia 10 - Generic boss theme used by Mushroom boss, Sphinx, Almighty Demon King, and final boss 11 - Sky castle 12 - Underwater areas, ice areas 13 - Unknown jingle 14 - Title screen 15 - Spaceship 16 - End credits 17 - Final dungeon -SFX- 18 - Ocarina button A 19 - Ocarina button B 1A - Ocarina button C 1B - Ocarina tune 1 1C - Ocarina tune 2 1D - Ocarina tune 3 1E - Jump 1F - Firestorm hit 20 - Sword 21 - Get magic(?) 22 - Door close 23 - Door open 24 - Firestorm fire 25 - Pause screen move selection 26 - Pause screen select 27 - Coin drop (from enemy, chest, etc) 28 - Pick up an item (coin?) 29 - Pick up a heart 2A - Press a switch (such as right before Gragg and Glagg) 2B - Dragon grandson fire 2C - Found a heart from a chest 2D - Found the ocarina 2E - unknown 2F - A big rock hitting the floor (such as in the dungeon near Lilypad) 30 - Arrow hits a shield 31 - unknown 32 - A big door opens 33 - Bounce on a jellyfish 34 - unknown 35 - Not enough money 36 - Hurt 37 - unknown 38 - A sound that plays when you enter a boss room 39 - unknown 3A - unknown 3B - unknown 3C - Using vertical teleporters (like the one in the middle of Alsedo) 3D - Using a potion 3E - Empty sound effect 3F - unknown 40 - unknown 41 - Elevator 42 - Elevator stopped? 43 - Maybe used by the green underwater enemies? 44 - Getting shrunk or grown (Pygmy armour) 45 - Longer version of 44 46 - Splash 47 - unknown 48 - unknown 49 - unknown 4A - Swimming 4B - Block falls (such as right before Gragg and Glagg) 4C - Duplicate of 4B 4D - unknown 4E - unknown 4F - Speaking 51 - A "Dom" sound when the glass of the spaceship is put in or taken out 52 - A sound played when your health has been restored and final boss starts 53 - Game Over jingle 54 - Inn jingle 55 - Old Axe being repaired 56 - Game being paused 57 - Old man's little brother destroying a wall If you are curious about how I did the hack, I simply injected this piece of code into unused ROM memory ($A47C8) Code: moveq #0,d6 ; D6 = Sound ID lea $C00000.l,a5 ; VDP DATA lea 4(a5),a6 ; VDP CTRL lea .hex(pc),a3 ; hex numbers array move.w #$8164,(a6) ; enable display move.l #$C01E0000,(a6) ; write pal0 entryF move.w #$EEE,(a5) ; white moveq #0,d0 move.l #$54000003,(a6) ; HSCROLL move.w d0,(a5) move.l #$40000010,(a6) ; VSCROLL move.w d0,(a5) move.l #$41860003,(a6) ; 3x3 lea .sndtst(pc),a0 ; sound test text moveq #14-1,d7 ; 14 letters .write move.b (a0)+,d0 ; get letter move.w d0,(a5) ; write next letter dbf d7,.write .loop stop #$2300 ; SYNC jsr $51C6.w ; read joy data move.b $FFFF8A7F+2.w,d7 ; get button presses or.b $FFFF8A82+2.w,d7 ; '' btst #0,d7 ; check if pressed up beq.s .noup ; if not, branch subq.b #1,d6 ; sub 1 from ID cmp.b #$FA-1,d6 ; check if we are out of the commands area bne.s .noup moveq #$58,d6 ; force to max song ID .noup btst #1,d7 ; check if pressed down beq.s .nodwn ; if not, branch addq.b #1,d6 ; add 1 to ID cmp.b #$58+1,d6 ; check if we are out of the music ID's bne.s .nodwn moveq #$FFFFFFFA,d6 ; force to commands .nodwn move.l #$419E0003,(a6) ; 3x15 moveq #0,d5 move.b d6,d5 ; copy num lsr.b #4,d5 ; get 4 high bits move.b (a3,d5.w),d5 ; get hex char move.w d5,(a5) ; save to VDP move.b d6,d5 ; copy num and.w #$F,d5 ; get 4 low bits move.b (a3,d5.w),d5 ; get hex char move.w d5,(a5) ; save to VDP and.b #$70,d7 ; check if A/B/C are pressed beq.s .loop ; if not, branch move.b d6,d0 pea .loop(pc) ; keep looping jmp $366.w ; but play a sound first .hex dc.b "0123456789ABCDEF" .sndtst dc.b "Sound Test: 00" Spoiler: Z80 bank Before we get to the juicy stuff, I want to talk about the data bank itself. The bank is nothing impressive, but it does contain something quite interesting. That is, pointers! At 9A77h, you can see a little pointer table, containing of following data in order: Music tracker Z80 address Instrument table Z80 address (in sound driver in Wonderboy in Monster World, in ROM in other games) Instrument rate list (YM regs 5xh, 6xh, 7xh, and 8xh used by instruments) Z80 address Envelope data Z80 address Envelope "tracker" data Z80 address Frequency modulation "tracker" data Z80 address Volume modulation "tracker" data Z80 address Next, we have some null bytes. I do not think they are ever used and is merely padding. Next is a byte that denotes the number of entries for the next table. If instrument table is in ROM, the next 19*numentries bytes will be the instrument table. Curiously, instrument rate list is in Z80 RAM. The next bytes will likely be the drum mappings table. In any case. next byte again tells the number of entries for the next table, which is the music & sfx table! This time, it will just be a table of offsets to the music data. Then, there may be some unknown data at the end, and/or padding to end of bank. Spoiler: Tracker format Ok, so lets dive head first into the tracker, which may be the most interesting portion (or not, a lot of stuff is of interest here!) So, in order to understand the format, we must start at the core; The music & sfx table. This table is simply Z80 word pointers to music and data. Nothing special. The header of each music consists of following; A priority byte, that is higher than or 80h. Higher number determines a higher priority. This priority will be used particularly when finding hardware channels to play the music. a Z80 word containing the initial frequency of the channel Any number of Z80 words, containing the addresses of slot channels. However, be mindful that there is only 0Ah slot channels available. a Z80 word that is 0h. This is the end token, and tells the driver to stop reading new channels. While, the header of each SFX consists of following; A priority byte, that is lower than 80h. Higher number determines a higher priority. This priority will be used particularly when finding hardware channels to play the music. a byte, containing the slot channel ID we intend to load to. No clue why they'd do this, instead of dynamically finding a free slot, but whatever. If this byte is 0FFh, it is an end token instead of being an ID. Stop trying to read new channels. a Z80 word, that contains the address of the slot channel. Last two may be repeated for any number of times, being mindful that there are only 0Ah slot channels available. The tracker data itself will be the same for each channel, regardless of type (with some exceptions listed appropriately). The following list all the possible bytes you may encounter: Code: $00-$5F - Play a note, and stop reading the tracker. We read tracker next time tempo counts down. $60-$BF - Play a note, but keep reading the tracker anyway. $C0-$CF - Read a value from table at 0E35h, multiply it by 3, a save it to the channel timer $D0-$D7 - Initializes a loop with counter of flag-$D0, and a Z80 word is supplied as an address to jump to each loop time, when paired with flag $FF $D8-$DF - Initializes a loop with counter of flag-$D8, and stores the next address as the loop back point, when paired with flag $FE $E0 - Enable frequency modulation. Also sets the speed of modulation. $E1 - Disables frequency modulation. $E2 - Set timer to a byte value $E3 - Set timer to a word value $E4 - Loads music tempo $E5 - Loads a sound ID (but not any special sounds). This is only available on Mega Bomberman. $E6-$EF - Not used. $F0 - Set instrument or envelope ID $F1 - set tempo divider of the channel $F2 - Sets channel frequency to word value $F3 - Adds a word value to channel frequency $F4 - Sets channel volume $F5 - Adds to channel volume $F6 - Selects channel type. $00 -> FM, $02 -> PSG, more than $02 -> PSG4 $F7 - Select hardware channel mask. Basically, what channels can this slot play on? $F8 - Enable drum channel mode. Each note now instead sets the panning, tempo, and instrument. FM only. $F9 - Set panning. Only controls panning, no AMS/FMS $FA - Stop reading tracker. We read tracker next time tempo counts down. $FB - Stop hardware channel. $FC - Currently unknown. Seems to be a similar deal as the no attack mode in SMPS (Flag $E7) $FD - Jump to location pointer by a Z80 word $FE - If loop counter is not 0, loop back to the last $D8-$DF flag $FF - If loop counter is not 0, loop back to the location pointed by previous $D0-$D7. If there were no loop flags in the stack, instead stop slot channel (end of stream) Phew, that was a lot to type. Now, for your convenience, I have made a disassembler for the sound data, along with macros for ASM68K. Z80 sound driver Now we're getting somewhere! I decided to section this off, as there is so much to get into. As you are reading, I will refer to things inside the Z80 driver. In case you are interested, I have supplied a disassembly of the driver in idb and asm. However, do keep in mind, that there are some things that are named funnily. Hardware channel modulation is actually frequency modulation, and LFO is just volume/amplitude modulation. These both are software modulation and are named incorrectly during making the disassembly. I am simply too lazy to come up with better names and rename a lot of things. Without further ado, lets dig into it; Spoiler: Slot channels Since, we have been talking about the tracker, lets segway into the slot channels! Slot channels read the tracker, and control hardware channels. Each slot channel is 20h bytes, and there are 0Ah channels in total. The first thing a slot channel does after being started, is initialize itself at 0BAEh. Thats right, music loading does not initialize channels, the channel does it itself. It does nothing special, just clears some flags and sets some others. After initialization, it always starts reading tracker instead of doing tempo. The tempo algorithm for slot channels works off of a tempo accumulator in the main loop. More specifically, music uses it, while SFX use a hardcoded value of 9. The tempo accumulator is a multiple of 3 of the tempo, as its incremented 3 times before slot channels are run. This means, hardware channels run 3 times as often as slot channels. The channel tempo timer is then decremented by the tempo accumulator, and if it is 0 or less, the tracker is read. The backup timer is not copied to main timer until we finish reading tracker. I have already touched quite bit on the tracker format, but I will give some complementary information. When the tracker read ends, the timer is saved, and it sets or clears bitfields bit 4 (no-attack?), according to if flag 1C1Ah is not clear. It also stores how many notes we have played that tracker read. Playing notes (0CA5h) themselves is a little more complex, so I will let you go into the dirty and complicated details, but here is an overview of the process. If the drum channel mode is set, each note will contain some information, such as the instrument ID and base frequency of that note. It also seems like frequency modulation is disabled too. This mode allows you to play drums with just playing notes, instead of setting up all these values each time you want to play a single drum(!). Since the sound driver does not support DAC, FM drums are used often. If the channel is in normal mode, the note ID is added to the high byte of frequency. Then the channel will either try to find the last note playing on hardware channel by this slot channel, and stop the channel, or find a new, free channel. If modulation, the frequency we calculated is the target frequency, and last frequency is current, and the difference is divided by a speed divider, resulting is the modulation speed. If we are not modulating, the calculated frequency will be the current frequency.TL levels or PSG volume will get updated, tempo will be divided by a tempo divider and saved to hardware channel, and hardware channel bits will be set accordingly, and the number of notes played will get incremented. Now, here is all the bytes of each slot channels RAM, for your convenience; Code: 00 - bitfield. bit 00 - Drum channel bit 01-03 - unused? 04 - unknown (suspecting no-attack bit) 05 - modulation bit 06 - Initialized bit 07 - Running bit 01 - Loop offset 02-03 - Tracker timer 04-05 - Backup of timer 06-07 - Tracker address 08 - Section ID. 00 = FM, 02 = PSG, more than 02 = PSG4 09 - Instrument or PSG volume envelope ID 0A - Hardware channel mask 0B - Tempo divider 0C-0D - Frequency 0E - Volume 0F - Frequency modulation speed divider 10 - Priority 11 - Panning flags, also some other bits(?) 12 - a note counter 13 - num of notes played when reading tracker 14-1F - Loop data. 4 total entries, 3 bytes per entry. First 2 bytes are address, third byte is loop counter. Spoiler: Hardware channels Hardware channels are a little bit more involved than slot channels, as such, I've created a few different sections to allow easier explanation of the processing of these channels. Spoiler: Initialization The very first thing a hardware channel does after being activated, is initialize itself, much like a slot channel. FM, PSG, and PSG4 channels have their own initialization routines. I will divide up FM and PSG as separate, because PSG4 is almost identical to PSG. Spoiler: FM FM channels use the instrument/envelope as an index to the instrument table. Each instrument is $13 bytes large, but do not get fooled, the instruments do not hold same data as SMPS does. Instead, here is their format; Code: 00 - algorithm + feedback 01 - Key on operators (can not key on operators individually!) 02 - Panning + AMS/FMS. If Panning control is not 0, instrument does not have control over panning. 03 - Total level op1 04 - Detune + Multiple op1 05 - ID in table with Attack rate + rate scale, decay rate 1, decay rate 2, decay level + release rate for op1 06-0E - 03-05, for op3, op2, and op4 in that order 0F-10 - modulation frequency offset 11 - frequency modulation tracker ID 12 - volume modulation tracker ID As these values are loaded, the game checks for last values, to avoid writing to YM if the values did not change. However, TL values are always written. They use slot operator system, much like SMPS, hence op2 and op3 are swapped. Last, the key on operators are loaded, and keyed on. Spoiler: PSG PSG4 channels have a little bit before main PSG stuff; It mutes PSG3 volume and saves the previous hardware volume to mute too. PSG channels use the instrument/envelope as an index to the envelope data table. Each envelope data is 6 bytes. The format goes as follows; Code: 00 - Destination volume 01 - Volume envelope timer 02 - Volume speed 03 - Volume envelope tracker ID 04 - Frequency modulation tracker ID 05 - Volume modulation tracker ID When the PSG channel loads the envelope tracker address, it also reads and processes the first byte. The PSG volumes actually work on range of 00-7F instead of 00-0F like you'd expect. The 3 least significant bits are ignored, and as the volume is sent to the chip, the volume is shifted down thrice. This bigger range of volumes allows for smoother volume effects. Modulation frequency offset is set to -$1800 ($E800). After this, it will follow to a piece of code the FM will go at some point too, but instead PSG will terminate here. Spoiler: Keying off The tempo algorithm is almost the same as in slot channels, with the exception that the values are much smaller. The hardcoded value for SFX is only 1, and music uses another byte for tempo accumulation. If timer has timed out, PSG is told to start releasing, and FM is keyed off. Curiously, the code checks for FM twice, once it will just jump to key off, second time call. The second time should never be able to occur any way, but this is not fixed in later versions of the driver at all. Spoiler: Frequency modulation tracker If timer has not expired or we are a PSG channel, another timer is decremented. If its not 0, it jumps to do final modulation stuff. Else, the modulation frequency offset is added to the base frequency, and is saved back to the base frequency. The tracker timer is then checked for 0, and if so, no tracker reading can occur again. Else, it is decremented, and if its nonzero, tracker is not read. Else, it is, this is the format; Code: 00 - Finish tracker read 01-F7 - Set modulation frequency offset to a word value (next byte is high byte) F8 - Load modulation shift counter and a new timer (other method of modulating?) F9 - Load timer FA - Finish modulating FB - Load a new base frequency FC - Negates the modulation frequency offset, and loads a new timer FD - Loop initialization. Contains a loop counter FE - Decrement loop counter. If not 0, jump to address FF - Jump to address Next, we do more modulation code. The current modulation frequency is loaded, and modulation speed is added to it. Next, it checks if we finished the modulation, and if so, stop modulating completely. If mod shift counter is nonzero, it uses some very strange code to calculate the base frequency, which is otherwise loaded from RAM. These are then added together with frequency offset into a final modulation frequency value. Spoiler: About the 'strange code' We tried to figure out this piece of code (08A6h) with Markey, but we could not come up with any pattern or find out what it would be used for or how it would affect the frequency. It seems completely irregular, and always drifts off by -$80 each $100 values calculated. I do not know if it means anything, but sharing it here. Here is the piece of code I used to calculate the drift: Code: public static void main(String[] asd) throws IOException, InterruptedException { int a = 0x32, b = 0; for(int i = 0;i < 0x100;i ++){ a = calc(a); b += ((a & 0x80) == 0 ? a : a | 0xFF00); System.out.println(String.format("%03X", i + 1) +" = "+ String.format("%04X", b & 0xFFFF)); } } private static int calc(int i) { boolean[] x = { true, true, false, true, true, false, true, false, true, false }; int a = i, c = i; for(int z = 0;z < x.length;z ++){ if(x[z]){ c <<= 1; } else { a += c; } a &= 0xFF; c &= 0xFF; } return (a + 0x7F) & 0xFF; } As seen on the code above, the frequency base number is multiplied by 75h, and 7Fh is added. My only guess it is to do something with a kind of harmonic sound, but I have no clue further than that. Spoiler: Volume modulation tracker After processing frequency modulation, then volume modulation is processed right after it. Volume modulation uses a timer much like what frequency modulation does at the start. If timer has not expired, all the code is skipped. Otherwise, volume offset is added to the current volume, and saved to current volume. Then the tracker timer is checked for 0, and if it is, no tracker read may occur anymore. Else, it is decremented, and if is 0, tracker is read. The format is as follows; Code: 00 - Finish tracker read 01-F7 - Set modulation frequency offset to a word value (next byte is high byte) F9 - Load tempo FA - Finish modulating FB - Load a new base volume FC - Negates the modulation volume offset, and loads a new timer FD - Loop initialization. Contains a loop counter FE - Decrement loop counter. If not 0, jump to address FF - Jump to address Curiously, nothing special related to volume modulation happens before we update the volume later on. Spoiler: PSG volume envelope tracker Whoop-dee-doo, still more tracker like systems to dive into. Fun, isn't it? This is a PSG-specific one though, and quite interestingly different. It is done in 2 parts; when note is on, the tracker format is read, when when note is off, it then does a little sequence of releasing. Lets first talk about note on. We use our familiar timer ritual here; if timer is initially 0, no read may ever occur, else it is decremented and checked for 0. Only if latter case holds true, then the tracker is read. The format goes as follows; Code: F0 - End marker, channel is stopped anything else - Lower 4 bits are the timer value, and upper 4 bits are shifted down once, main volume is added, and then it is saved to the current volume. At the end, the modulated volume is added to current volume, and saved as the final volume. After some time, the channel informs the note has released, and another process occurs inside this piece of code. When we initially start releasing, a release destination volume is checked against current volume, and if they match, and destination volume is nonzero, the release is immediately halted. After initialization, it is checked if the releasing is done, or if the timer had reached 0 or less. If so, the next step of release is executed. Current volume is added to the release volume speed. Destination volume is checked for 0, and if it is, volume is checked for a negative value. If it is, the hardware channel is stopped for good. Meanwhile, if destination volume was nonzero, the code checks if volume had reached its value, and the volume is adjusted to exactly it and releasing is stopped. Then finally, the modulated volume is added to current volume, and saved as the final volume. Spoiler: Updating frequency This code is still a mystery to me, and I could not unfortunately explain how it works. Would be great if someone has any ideas of how it would work, will update the post when an explanation is figured out! The code is located at 053Ch. Spoiler: Updating volume Updating volume between FM and PSG is quite different, so I'll split them into two. PSG4 is basically same as PSG, except it does not check for last value, and uses another flag to store volume. Spoiler: FM Channel loads the slot operators bits, loads main volume and adds volume modulation volume. Then it checks if it is running a music track. If so, master volume is loaded, else 0 is loaded. That is added to the calculated volume, and limited to max of 7Fh. Next it enters a loop, to process op1, op3, op2 and op4 in that order. In the loop, TL level is loaded, and it is checked if this is a slot operator. If so, calculated volume is added to TL level, and is capped to 7Fh. The volume is compared to the last volume, and if they do not match, the volume is written to YM. Then it loops for all of the 4 ops before terminating. Spoiler: PSG Channel checks if it is running a music track. If so, master volume is loaded, else 0 is loaded. Then, current volume is added, and limited to max of 7Fh. 3 least significant bits are cleared, and then is compared to last volume. If not same, volume is saved back, and shifted down onto its place (00-78 -> 00-0F). Next, the channel ID is shifted onto its place too, volume update bits and the volume is added, and the final value is put into PSG. That marks the end of our journey with hardware channels. What a mess it was, writing it took forever. Moving right along! Spoiler: Main loop We are almost through everything, finally! We are discuss the rest of the logic right here, separated into nice little sections. But first, the main loop. The first part is run thrice, to process hardware, and sound queue 3x faster than slot channels. The code first runs the timer B synchronization routine, to keep everything nice and tidy. Then, volume control (fading etc) is processed, and music/sounds are loaded. Then, main tempo and tempo accumulator's fraction is added together, and saved to tempo accumulator. After, the high byte of tempo accumulator, aka the quotient, is added to the tempo count variable. After which hardware channels get processed. After that is done 3 times, slot channels are processed and tempo count is cleared, main loop is started again. Spoiler: Timer B sync During driver initialization, Timer B is set to 0EDh. First, the driver checks a debug access flag, and if nonzero, it will in addition do some strange debug stuff. I will not explain what it does, because we have been unable to find the 68000 code controlling this. It seems completely unused code and does not seem to hold much purpose. There is a flag that controls how often the code will wait for Timer B. Usually it is set to 1, which means it will wait every single time. However, a bit of the pause control flag will also allow the timer to be set to 4, which would mean each 3 times Timer B is waited for. This features seems to be unused in Wonderboy in Monster World however. If the timer will be waited for, it will loop until YM tells the Timer has expired, and after it, it is reloaded. Spoiler: Volume control Volume control has 2 modes; User control, and fade control. In user control, the 68000 will dictate the volume to the driver, and it sets it as the master volume. In fade control mode, fade counter is checked for 0, and if not, the fading is in process. Fade amount and fade speed are added together, and the result's bit 7 is checked. If is set, the speed's bit 7 is checked. If set (aka fading out), all music is stopped. In both cases, the fade counter and master volume are cleared. If however, bit 7 was not set for result, the fade amount is stored back (updates master volume too!), and fade counter is decremented. If fade counter reached 0, fade list address is loaded, and a byte is read to the fade counter. Then speed is loaded and saved, along with the new list position. Spoiler: Loading sounds First, the 68000 access to the sound queue is blocked, and the queue count is checked for 0. If zero, 68000 access is granted. In the other case, queue count is decremented and the next byte is loaded from the list (much alike 68000, but queue count is not used for indexing). 68000 queue access is granted. Next, if the ID is a command, the appropriate routine for music commands are called. Here is a list of all music commands; Code: F9 - All music is stopped (Mega Bomberman only) FA - Slow type fading out is started FB - 68000 will control master volume FC - Pause music FD - Unpause music FE - Quick type fading out is started FF - All sounds are stopped Else, the game checks if the music ID is valid, and if it is, only then it will load the music/sound. First, its pointer is loaded from the bank, and then the priority is loaded. If it is positive, sound effect loading happens, else it loads music. First, lets check out music. Some fading stuff is cleared, and the main tempo is loaded. Tempo accumulator is cleared and all music channels are stopped. The tracker address is loaded, and if 0, loop is terminated. Else, tracker address is saved, channel is set running, and priority is saved. Then just loop. Next, sound effects. Channels with same priority are stopped (Don't know why exactly, would seem like they could just override the same sound effect anyway?). The channel ID is loaded, and if 0FFh, the loop is stopped. Then it checks if the channel is running or has lower priority. If not, the channel is not overridden. Else, the hardware channel is stopped if running, channel is set as active, priority and tracker address is saved, and loop is continued.