In this post, I’m going to outline a few areas of study that will help you get started reverse engineering a game, and outline the method I took with World Warrior. I won’t be going into too much detail that can already be found elsewhere, only pointing you in the right direction so you can do your own googling 🙂
To get stated, especially using the MAME debugger, you’ll at least need to become familiar with the 68000 CPU assembly instructions and how the processor works. While it’s hard to write code in assembly, it’s not actually that hard to learn the instructions and what they do.
Once you’ve learned the basic instructions, such as MOVE, TST, ADD, SUB, and Bcc, you’ll be able to play around in the MAME debugger to get familiar with how the CPU processes the instructions, what effect the different instructions have on the CPU status register, and how the different branch (Bcc) instructions work.
Next, you should learn about breakpoints and watchpoints in the MAME debugger. Breakpoints stop the debugger whenever execution reaches the address where you’ve set the breakpoint. You can use this to help confirm whether a piece of code does what you think it does – the breakpoint will “hit” (and the emulator will pause) whenever that address is reached.
For example, if you suspect a piece of code is responsible for creating a fireball, you can set a breakpoint at that address, and play the game, ideally in 2P mode so you don’t have to worry about a computer opponent acting by themselves. See if the breakpoint:
1) Always gets hit whenever you execute a fireball
2) Never gets in any other cases
If both of these are true, you’ve probably confirmed your suspicion, but keep an open mind: Does it only hit for Ryu’s fireball? Does it hit for Ryu and Ken? Or does it hit for general projectiles being fired for any player? Always be careful in your assumptions. As you progress you’ll make notes of the different things you’ll find. Make sure you’re not misleading your future self reading these notes again months, maybe years later, well after you’ve forgotten the context in which you wrote them.
The MAME Cheat XML files will be a lot of help to you, as they reveal the addresses of variable for things such as energy levels, time remaining, etc. which will be valuable in deciphering the code. This brings us to Watchpoints.
Watchpoints are similar to breakpoints, except they involve variables instead of instructions. Maybe you want to learn about how a player’s energy is adjusted. A good place to start might be to set a watchpoint on the address that holds that energy variable, and you can learn many such addresses from a cheat file.
When you set up a watchpoint, you can tell the debugger whether you want it to stop whenever that variable is written, read, or both. A ‘write’ watchpoint is useful to finding out what code is making changes to that variable, while a ‘read’ watchpoint can help you find what code is using that variable later on.
For example, a write WP on the energy variable will probably reveal the code that calculates damage, while a read WP is likely to be hit by a graphics routine that draws the players energy bar on screen (and also a number of other things, such as AI routines that make decisions based on how much energy their opponent has. Again, be careful in your assumptions).
Lastly, you’ll want to build a Memory Map of the game. This is a table of address ranges and what they are connected to. Looking at the MAME source for the driver of your game will help you with this, and they will be similar for all games on the same platform type.
A CPS1 game will have a memory map like this:
0x000000 to 0x3fffff Game ROM
0x800000 to 0x800040 Player inputs, coin counters, etc.
0x800100 to 0x80017f CPS chipset functions
0x800180 to 0x80018f Commands to the sound CPU
0x900000 to 0x92ffff Graphics RAM
0xff0000 to 0xffffff RAM
Keep a text editor window handy with this memory map until you memorise it. Eventually you’ll instinctively see a write to some address in 0x900000 and know it’s a graphics write you’re looking at.
That’s all for today. In my next post, we’ll take the bull by the horns and generate a machine language dump of the whole ROM set.