Midway ADPCM hacking guide

More
6 months 2 weeks ago #1010 by docwallace
I've been threatening to do this for ages, and if I put it here, then there's no chance of this getting forgotten if I get hit by a bus or something.
WARNING: This is going to be LONG, so if the technical side of this doesn't interest you, you may want to save your time.

I've been looking at the Y and T Unit ADPCM sound board for some time, and the TL;DR is that we can now add new ADPCM samples, and amend the ROM code accordingly to do it.

I've described the basic process in videos before, but for one reason or another I'm unable to record right now in a format that isn't ridiculously low resolution, so the best way of describing this is here.

There is a document I'm building up at docs.google.com/document/d/1_49G0IsOiZ-O...jnw/edit?usp=sharing , but this is the simple version.


Preamble
Essentially, there's a load of header magic in bank 3 of the U3 ROM, which for Mortal Kombat is starting at 0x20000 in the file. What you have to remember at all times is that that is mapped into the CPU at 0x4000, so wherever you see pointers back to a 0x4000 region, that is actually the 0x20000 in ROM. In the MAME debugger however, where the ROM is mapped in place, the adpcm:cpu memory window will show it in the correct place. I'll use the 'correct' internal values in the main here, and point out where things differ for those looking at the ROM in a hex editor, but in the main the conversion is very simple.

Also note that in this post, I'm going to refer exclusively to the SL1 version of the ROM, which is the untouched original from the standard MAME set. Obviously for Plus, when people have messed with it, some of this stuff will have changed as tables get moved around, expanded etc.

Sound board operation
The main program communicates with the sound CPU by copying bytes to one specific area of TMS memory space, that links serially to the sound board to act on, so the commands are short. In fact, every sound, speech or music cue is triggered with at most 2 bytes written to this serial space.

In the sound ROM, there are two tables of lookup data for interpreting these commands, one for if there's one byte (or a 2 byte 'word' starting with 00) and one for 2 byte 'words' starting with 7A.

To find where these tables live, check 0x400f and 0x4010 for the first (remembering that's actually 0x2000f and 0x20010), and 0x4019 and 0x401a (0x20019 and 0x2001a) for the second. This will give a word, read with most significant bit first, so 40 5E means looking at 0x405e, which as I've mentioned before is 0x2005e in the file. This is the base value.

Part 1: Command processing
Since each entry in this table is a word itself, take the command byte, multiply by 2 and add to the initial
base value to find the place. For this example I'm going to take the first ADPCM sample in the sound test which is the SMACK! sound. This has the command code 36, without the 7A prefix. so we're looking at the first offset table, which starts at 0x405e.

0x405e + (2 * 0x36) = 0x40ca.

Reading this (0x200ca in ROM) gives two bytes in succession, 07 06.

The first byte is a type designation for the sound command:

01 = MUSIC
04 = DAC
07 = SAMPLE
10 = NOT USED
OTHER = CODE

So 07 tells us, yes, this is a sample, and we need the sample data table next.
The entry offset for that table is the second byte, 06.

Part 2: Sample Table
There's only one sample data table, and that's found from the header again, at 0x400b and 0x400c
Looking at those in ROM (following our conversion rule 0x2000b, 0x2000c) gives 4416 - which is our base for the sample table.

0x4416 + (2 * 0x06) = 0x4422

Going to that space (in ROM 0x20422) shows a word that looks very much like a jump address (46 2A), because it is.
We go there (0x2062a) in this case, and there's a 4 byte sequence, 01 06 00 FF

The 00 FF seem to be ignored, as there's only two parameters here that need to be configured. Taking those first two bytes:

Byte 1 is the voice to use on the ADPCM chip, there are 4 in total, and playing a sample on a voice in use will cut that sample off to start the new one. To that end, you'll see a number of commands that are basically identical except for the voice byte to allow for mixing.

Byte 2 is yet another offset into a data table to actually find which sample needs to be played. This may seem strange, but because of the duplication mentioned above, this can be used to compress those near duplicate entries to reduce the amount of bytes needed to store the data, separating the changing part. Coincidentally, this offset is also 06 like the last one, but this is not always the case, and it has nothing to do with the offset we used to get here.

Part 3: Sample Table 2
This third lookup table used is defined, yet again, in the header at 0x4015 and 0x4016 , which when converted and looked up gives the word 4a26.

Using the same equation as before:

0x4a26 + (2 * 0x06) = 0x4a32

Looking at that space (in ROM 0x20a32) gives a jump address, 4B66

There is a 5 byte sequence 01 03 07 00 A5

01 is the bank in the ADPCM ROM combination (U12 and U13), 03 seems to be a priority byte to decide what to do about actually playing a sound or not if its a voice in use, 07 is the sample number in the bank, and 00A5 is the length of the sample in ticks, to allow the system to figure out roughly how long to play it before allowing interruptions etc.

With the tools already built to add samples to the ADPCM ROM, changing values in these tables to convert unused samples to point to new data is relatively straightforward, if time consuming, and with the amount of space left in U3, there's certainly potential to add a few little things of interest ;)
The following user(s) said Thank You: zpaul2fresh8

Please Log in or Create an account to join the conversation.

More
3 months 2 weeks ago #1109 by nidaamber44
hey, i am Profile designing designer and i want to learn hacking where i found so many things be like but now i get bore and i want to learn new things. things are just renewable and artificial, as with technology we should update our self.

Please Log in or Create an account to join the conversation.

More
2 months 4 weeks ago #1116 by zpaul2fresh8
Good stuff. This is a test reply, integrating Kunena with a webhook to Discord.

Please Log in or Create an account to join the conversation.

More
2 months 16 hours ago #1130 by docwallace
I'm going to add a coda to the previous post, because I've found out some more stuff that may be useful.

I've mentioned before the wonders that are the nested data tables, 0x4416 in the bank used in U3, or 0x20416. The jump tables there point to some tables that are not a standard width necessarily (though most are 4 bytes wide). This is where what's up there is, well, wrong.
e.g 01 06 00 FF

Byte 1 is the voice to use on the ADPCM chip, there are 4 in total, and playing a sample on a voice in use will cut that sample off to start the new one. To that end, you'll see a number of commands that are basically identical except for the voice byte to allow for mixing.

Byte 2 is yet another offset into a data table to actually find which sample needs to be played. This may seem strange, but because of the duplication mentioned above, this can be used to compress those near duplicate entries to reduce the amount of bytes needed to store the data, separating the changing part.
There are other patterns in there too that are longer, but always they end with an FF. As I see it, the code loops over this structure until it hits an FF which is the stop command.

Why would you do that, I hear you cry?


Using this combination of byte 1 and 2 to look up patterns, we can build phrases

Take command 7A 71 - work that through and when you get to this point in the ROMs (0x207FE, or 0x47FE in MAME) there's a structure
02 4D 00 53 00 FF

[NOTE: Voice commands should be 01,02,03 or 04 - 00 just means duplicate the voice that you're already on)

So this means, (play ROM sample 4D on voice 2, then 53 on voice 2, then stop voice 2)

Looking these up is based around 0x20a26 or 0x4a26, with + (2 * sample ID)

for 4D that's 0x4ac0, which has within it a jump to 0x4cc9 these 5 bytes:

04 01 47 01 4a

This is a command to play Bank 4, sample 47, and wait 0x014a 'ticks' to proceed.

The second byte the '01' appears to be a delay routine - if this number is greater than 2, the sample plays immediately, but otherwise there's some pause
With the CPU speed at 2MHz, each tick is 0.000036 seconds, so 0.08712 seconds

It's the Kano callout.

Code 53
04 01 4d 01 87
is the 'Wins' voice

So this plays 'Kano Wins'.

With careful amendment and addition to these tables, you can add all new samples if need be.
The following user(s) said Thank You: zpaul2fresh8

Please Log in or Create an account to join the conversation.

Created by ZPaul2Fresh8

Go to top