The problem
I wanted to play through Dragon Crystal (partly to rip the VGMs, partly to see how it ends). But I'm not that good at it. I could play it a lot, practice day and night, hone my skills to perfection and then be able to battle through the game; but I'm a busy guy. So I wanted to cheat.
Step 1: look for a cheat
My laziness knows no bounds; I started by looking for existing cheats. Well, there are none built in to the game, and I couldn't find anything useful. But I did find this...
00C6 2160 Unlimited hit points
It's a Pro Action Replay code. A PAR is a device which plugs between the console and cartridge and enables you to cheat in games - the Game Gear one is shown to the right. I know enough about them to know that this basically means that the game stores the "hit points" (I'll call it energy) in RAM at offset 0xC621. That's a hexadecimal number; if you don't know anything about them you might want to read the box on the right below.
All PAR codes store the required offset in the middle four digits. While there's currently no VGM-logging emulator which supports PAR codes, it can be useful for easy rom hacking...
|
Hexadecimal numbers
Normal (decimal) numbers count from 0 to 9, before increasing the second ("tens") digit. We use this "base 10" system because we have 10 fingers. Hexadecimal (often abbreviated to "hex") numbers count from 0 to 9, then A to F, before increasing the second ("sixteens") digit. This "base 16" system is used when dealing with computers because it is compatible with binary numbers (base 2) which computers use. It's compatible because one hex digit corresponds to 4 binary digits, so one byte can be represented by 2 digits; one decimal digit corresponds to about 3.322 binary digits which is no use at all. (Mathematical note: the number of digits in base a represented by each digit in base b can be shown to be given by log b / log a.) You can convert between hex and decimal (and other number bases) using a scientific calculator. Windows' calculator will do this quite easily. If a hex number happens not to contain any letters, you wouldn't be able to tell if it was decimal or hexadecimal. So various notations are used to signify a hex number:
I tend to use the first (because it's the notation used in C) or the second (used in Delphi, and by the disassembler used on this page). Also, the case of the letters doesn't matter. It's just easier to type 0xc621 than 0xC621. |
Now, to hack a rom you must first disassemble it. This basically turns stuff like this:
4E 06 00 EB 21 20 C0 09 22 A4 C0 13 1A 32 A3 C0 1B EB
(unintelligible code from a Master System game)
into this:
ld c,(hl) ; 000475 4E
ld b,$00 ; 000476 06 00
ex de,hl ; 000478 EB
ld hl,$c020 ; 000479 21 20 C0
add hl,bc ; 00047C 09
ld ($c0a4),hl ; 00047D 22 A4 C0
inc de ; 000480 13
ld a,(de) ; 000481 1A
ld ($c0a3),a ; 000482 32 A3 C0
dec de ; 000485 1B
ex de,hl ; 000486 EB
(the same code made marginally less unintelligible)
To do this, you need to download a disassembler from the S8-Dev tools section. For this page I used z80dasm (because I like the way it formats the information) but they're all much the same. Then you need to disassemble the rom using a commandline like this:
This program will disassemble the file to the screen, so I added that > filename to send it to a file instead. This is the kind of thing you'd know if you'd been using computers before 1995...
Then I opened the dragoncrystal.asm file created; it's a big file (4MB), so I used Word because it can handle it much better than WordPad, let alone Notepad. If you have Windows XP, maybe you'll be OK with Notepad. I then used the Search feature to look for c621; there's 57 or so. That's a lot. But I do know a tiny bit of Z80 assembler, mostly thanks to Mike G and Bock, and a bit more about how computers work. I know that if it stores the energy in 0xc621 then some of the time it will read from there, and sometimes write to there. If I can stop it writing to there when it wants to decrease it, the energy will never decrease. I know that to write it has to use a command like this:
ld ($c621),?
|
Registers and a tiny bit of Z80 assembler
Because of the way it works, the Z80 CPU inside a Master System or Game Gear has to use registers as go-betweens when it wants to alter values in memory. Basically, registers are a small number of memory locations inside the processor. They have names like A, B, C, D, E, H and L; each stores one byte. Some can be paired up to make 2-byte stores, and are referred to by the two letters together, like BC and HL. To change a value in memory, you use code like this:
My scheme for hacking the rom is to remove this last line. |
I then tried to look at the places where that code was, trying to understand what was going on. Some of it I understood, as you'll see below, and some I didn't. Anyway, it wasn't much use, but it took me plenty of time. I hope some of it was helpful to me in some way, but...
The disassembly tells me this, for the first line found when searching:
ld hl,$03e7 ; 000CA8 21 E7 03
ld ($c621),hl ; 000CAB 22 21 C6
Can you follow this? Load register hl with the value $03e7 (999 in decimal); then load our memory offset with that. I can see that getting rid of this won't be much use; getting 999 energy would be useful, so I don't want to stop it happening. Also, I know that that doesn't actually happen in the game so this must be something else. The next match does the same, but with $0064 (100). In fact these two situations appear quite a few times. I tried changing the 100s to 999s, and did find the one setting the initial value, but the game became quite buggy.
So I searched again, looking for more complicated code. When I did, I tried deleting the line writing the value to memory. To delete something in assembler, you need to turn it into nop (no operation) codes; for the Z80, this is 00. So, to get rid of this:
ld ($c621),hl ; 002D64 22 21 C6
I need to write three 00s starting at offset 0x002D64. I could do this to the file, using a hex editor, but instead I'll use Meka's patching feature. I opened meka.pat, and at the end I added a section like this:
[6C4E00641D7F6ADC]
seek,2D64
write,00
write,00
write,00
You can find the code to put between the square brackets by looking in meka.nam - it's the first 16 characters of the line with the game's name on it. (Notice the hexadecimal number again?)
Then I saved the file, and loaded the game in Meka. And guess what? It didn't work - the energy still went down when monsters attacked me. So I changed the offset to the next suspicious-looking line, and tried again. Several tries later, at offset 0x5346, I had success. So I could play through the game much more easily, and got all the music I wanted. (Well, there's the fact that the game tends to crash before the ending sequence, but that's another story.)

As it happens I found that the Game Gear version of Dragon Crystal has different music, so I wanted that too. Playing through 30 levels took a long time, so I looked for a better shortcut. How about this?
00C61Fxx Level select
Much better! I can go straight to level 30 this way. This one was much easier - there are only 5 writes to this location; the first is simply loading the value 01 into it, and the rest are more complicated. The first one is the one I want. I changed it similarly to before:
ld a,$01 ; 000FEC 3E 01
ld ($c61f),a ; 000FEE 32 1F C6
requires
seek,FED
write,1E
The things to notice here are that to change the 01 in the first line, I want to skip over 0xFEC (which contains the "ld a," bit) to 0xFED (C + 1 = D); and that 30 in hexadecimal is 0x1E. I loaded the game and hey presto, it worked. I start at level 30, albeit with crappy weapons and armour, and I can get the music and also (with luck) finish the game before the dragons kill me by applying the famous "Run away! Run away!" principle.

So you see, if you don't mind possibly wasting some time, not fully understanding everything you see, and applying a little trial and error once you've got the number of possibilities down to a reasonable amount, you too can hack a game. Just don't do it all the time - playing games properly is much more satisfying and fun. I know I'll come back to Dragon Crystal and play it properly when I have time, because it's quite good.