Making Game Genie's NES codes from binary files
First, an apology. I suspect that this will be very difficult to read at any resolution lower than 800x600 due to my wanton use of tab stops. I'd better see how it looks at higher resolutions, too.
NES code making--preparing your file
Perhaps the best way to learn to make codes is to do what I did: jump in and get your hands dirty. We'll begin the tutorial by preparing your game for translation. For example purposes, we'll use an image named FOOBAR.NES. The first thing to do is to strip the game to its bare minimum. To do this, you will need a hex editor. A graphic editor is also helpful.
First, copy your game into another file. We'll copy FOOBAR.NES into FOOBAR.BIN. You will be editing the copy, not the original. Next, open the game in the graphic editor. If the editor demands that the file have an .NES extension, go ahead and open the original. You won't be making any changes from here. Scroll through the file and look for obvious graphics. Most likely, they will either be at the beginning or at the end. An example from Tile Layer:
At top is the hex address of the first line of graphics shown. In Tile Layer, you must scroll a line to the top of the screen to see its address. This screenshot starts at the first line of graphics in the game. Thus, we know that the game's graphics begin at $8000. In this case, everything from $8000 to the end of the file is graphic data. In some games, the graphics would be located at the beginning of the file instead. In that case, you should scroll until the first line that isn't graphic data is at top, so that you can see the address where the graphics end.
Keep in mind that there may be garbldy-gook interspersed with the graphics. Here you may find an NES emulator helpful. Go to Zophar's Domain and pick up a copy of NESticle. (Other programs may have a feature similar to this.) Go to the file loading menu, and single click on the original game (i.e. FOOBAR.NES). Look at the bottom of the window for something that looks like this:
MAP #0 32K / 8K V
Look at the last number, the "8K V" in this case. If it isn't 0, everything after the start of the graphics is part of the graphics, whether or not it looks like it. If it is 0, everything before the end of the graphics is part of the raw data used by the game. All raw data can be considered as graphics for our purposes.
Now that you know where the graphics start and end, it's time to begin. Open the copy of the game (i.e. FOOBAR.BIN) into the hex editor and delete the first line. This is the 16-byte header placed there by the emulator.
Next, delete the graphics. Here's where you will need the start and end points. In the above illustration, everything from $8000 on can go. When the graphics begin at the end, their starting point must be a multiple of $4000. Your game's graphics may have begun at $0. In that case, you will need to scroll past the graphics and get the address of the first thing that isn't a picture. Delete everything from $0 up to, but not including, that point. The ending point should be a multiple of $4000. If it isn't, you should back up to the nearest address that is to be safe.
There are more steps we could take to trim the fat, but we don't want to delete too much our first time through. Having a bit of data or graphics in your file just makes it larger. For the most part, it doesn't hurt to leave something in if you aren't sure about it.
Your shortened copy of the game is now ready to go! Run it through your trusty 6502 disassembler now. You should use the option to print hex values. (Just type the program name without a file to see the list of options. Both programs in the file section support this.) Remember, most programs display their output directly to the screen. You'll have to pipe them into a file using DOS commands. (*shudder*) For example:
D:\NES>dasm6502 -p foobar.bin > foobar.asm
The little ">" tells it to store all of the output in the file on the right. The name is up to you, but use one you can readily associate with the game. When it finishes, you'll be ready to make codes!
Reading the results
Next, open up the file you just created. In this example, we'll use FOOBAR.ASM, the file produced by the disassembler. What does it look like?
00000000: 78 sei
00000001: D8 cld
00000002: A9 00 lda #$00
00000004: 8D 00 20 sta $2000
00000007: A2 FF ldx #$FF
Ack! It's a horrid mess of computerese. Let's take this one step at a time. On the far left is a series of eight hex digits followed by a colon. This is the address of that line in the file. We'll go over addresses in a bit. Next comes one to three hex numbers. These numbers are what you would find in the original game at that address using a hex editor. The computer uses these numbers to produce its translation. On the far right is that translation. The funny three-letter acronyms and strange numbers are actually supposed to tell you what the game is doing. Much later, we'll go over some of these symbols and what they mean. For now, let's work on addresses.
File addresses aren't that hard to understand if you are familiar with your hex editor. $0 is the very first thing in the file, and everything else is located relative to it. $1 is the next thing after $0, $10 is the sixteenth thing after $0, etc. (Remember the overview: $n is a hex number) The numbers in the far left column above represent those same addresses. Note the way the sample jumps from $4 on one line and $7 on the next. Like a hex editor, the numbers in the middle run in a grid. The number next to the one at address $4 is at address $5, and the one next to that is at address $6. Finally, the line is broken and the next begins at address $7. Practice: where is the number $20 from the middle column above? It is two to the right of the $8D, which is at address $4. It is also one to the left of the $A2, which is at address $7. Do the math, and either way the $20 must be at address $6.
That wasn't too hard, right? Well, that was just the file address. Since we're on the subject of addresses, this might be a good time to explain the mysteries of CPU addresses.
NES CPU addresses
As far as the making of Game Genie codes is concerned, only two parts of the NES's memory are important. The easier to explain is the RAM area. Recall from the overview that RAM is where changing data such as ammo and lives is stored. The Genie itself does not work with RAM at all, so this information is more for reference. In the rightmost column of your disassembled file, hidden among the funny three-letter words, are many addresses. For example:
00000004: 8D 00 20 sta $2000
The $2000 above is an example of an address. These addresses always begin with a $ and are always either two or four digits long. Numbers that begin with a # are not addresses. Look again:
00000002: A9 00 lda #$00
As explained in the overview, numbers that begin with # are literal numbers. In this case, #$00 is the number $00, or 0. #$40 is the number $40, or 64. Any number that only begins with a $ is an address, on the other hand. Thus, while #$00 is the number 0, $00 is the address 0.
Now, back to RAM. Any time you see an address in the right-hand column less than $2000, you can be sure it's in RAM. In fact, all of the addresses less than $2000 that you see will also probably be less than (or equal to) $800. Why? The NES only has 2K of RAM, which fills addresses $0-$800. Between $800 and $2000, the same stuff is repeated over and over to pad the space. Here's four lines. Can you spot the RAM?
00001234: AD C4 03 lda $03C4
00002345: 8D 16 40 sta $4016
00003456: 0D FF 91 ora $91FF
00004567: A5 3C lda $3C
Look at the addresses in the right-hand column and figure out which are less than $800. The first one is. The next two are not. Is the last? You won't usually see leading zeros. If an address $xx is only two digits long, it really means $00xx. Thus, the last address is in RAM.
Addresses $100-$1FF belong to a special part of memory, the stack. (Why is the stack in the middle of RAM? Heck if I know...) Unless you dream of writing your own game, you probably don't need to care too much about what the stack is or what it does. Anyway, memory in this area is used differently than the rest of RAM, so keep an eye out for it.
The other part of memory you'll need to know about is the ROM area. Every address greater than (or equal to) $8000 is in the ROM area. Remember, the ROM, the stuff in the cartridge, is the permanent and unchanging data that makes up the game. This ROM is a bit different. For one thing, it isn't permanent and unchanging. See, the CPU has to have everything together in one place to get its work done. It keeps the RAM close at hand, and the registers and other stuff are built into it. To follow the game program in the ROM, it needs to bring that inside itself, too. The CPU loads a chunk of the ROM into a special holding area and runs it from there. In fact, it is this holding area that the Genie modifies.
Now, I want you to picture an odd device. This is going to be like a slide rule, but with locking tabs. Think of the locking teeth on a screen-door window, attached to a ruler. Sound strange? Of course it is. Here's an illustration.
What does this have to do with anything? Well, this is what the CPU ROM area is like. The big, long stick is the entire ROM stored in the cartridge. The smaller stick is the CPU ROM area. The CPU only remembers 32K of the cartridge at a time. To read the next part, the ROM area has to slide down and lock into the next 32K chunk, just like our slide rule. As suggested by the locking tabs, the ROM area doesn't slide freely. The cartridge is divided into 16K segments, and the CPU can only grab two adjacent, predefined segments.
Add numbers to the above illustration and you should (hopefully) get an idea of the way the cartridge is loaded.
00000000
00002000
00004000
00006000
00008000 <--|
0000A000 |
0000C000 Current ROM area
0000E000 |
00010000 <--|
00012000
00014000
00016000
00018000
CPU ROM addresses always run from $8000-$FFFF, regardless of the actual ROM position they represent. Let's add more numbers:
00010000 <--|--> 00008000
00012000 | 0000A000
00014000 ROM area 0000C000
00016000 | 0000E000
00017FFF <--|--> 0000FFFF
00018000 00008000
On the left is the cartridge address. On the right is the resulting CPU address. There's something odd about the addresses--how can both $10000 and $18000 be called $8000 at the same time? They can't. The actual ROM area stops just short of $18000, at $17FFF. When you get to $18000, it starts over. More numbers!
00000000 --> 00008000
00002000 --> 0000A000
00004000 --> 0000C000
00006000 --> 0000E000
00007FFF --> 0000FFFF
00008000 --> 00008000
0000A000 --> 0000A000
0000C000 --> 0000C000
0000E000 --> 0000E000
0000FFFF --> 0000FFFF
00010000 --> 00008000
00012000 --> 0000A000
00014000 --> 0000C000
00016000 --> 0000E000
00017FFF --> 0000FFFF
00018000 --> 00008000
Sorry about the Froot-Loop color scheme (and my apologies to the color blind, who'll have to work out the numbers). Each colored block represents one 32K chunk. When the CPU gets to the addresses on the left, it will name them with the ones on the right. The first block runs from $0000 to $7FFF. There is no room left for anything else. So, when the game needs $8000, the CPU has to ditch all of $0000-$7FFF and replace it with $8000 through $FFFF. When the game gets to $10000, the CPU has to forget $8000-$FFFF and replace it with $10000 through $17FFF.
Is your brain sore yet? There's just one thing left to CPU ROM addresses. Because the CPU only remembers 32K of the cartridge at a time, it can only refer to a part of the cartridge it remembers. $A345 is a CPU address located somewhere in the ROM area. What part of the cartridge does it refer to? Who knows! All we know is that it is somewhere in the 32K currently loaded. Look at the colored numbers above. $A345 might represent cartridge address $2345, $A345, $12345, or anything else. The important thing is simply that $A345 comes from the same color block as all of the other CPU ROM addresses being used at the moment.
Don't worry, it isn't impossible to figure out the exact address. Consider the following line:
0001B031: AD 43 92 lda $9243
Where is $9243 here? Look at the left column, the file address. Which color block does it fall in? Well, okay, that's a trick question. The blue block above that starts at $18000 would run to $1FFFF if the diagram were complete. That's the secret: figure out which two multiples of $8000 the file address falls between. That 32K chunk of the file is the one referred to by the CPU address. At the moment, $18000 is called $8000. Do the math: $9243 in the CPU at this point refers to $19243 in the file.
There's one last thing to consider regarding CPU addresses. A few of the earliest NES games ever made were only 16K long. In these cases, the game is loaded into CPU addresses $C000-$FFFF. Here's what the slide rule looks like:
00000000 --> 0000C000
00001000 --> 0000D000
00002000 --> 0000E000
00003000 --> 0000F000
00003FFF --> 0000FFFF
This map represents the entire game. The "slide rule" doesn't slide here, because the entire game can be loaded into the CPU with room to spare. Remember to add $C000 to the file address before getting the Game Genie address (described later), or your codes won't work!
SRAM addresses
A few games here and there use an extra 8K of persistent memory called Save RAM, or SRAM for short. This memory is kept in the cartridge but is addressed and used the same way as the NES' own 2K of RAM. Unfortunately, Nintendo's charming price-jacking policy made (and still makes, in fact) this uneconomical for all but the longest, hardest games that desperately needed some save feature. If the game carries a mysterious warning regarding the power and reset buttons, it uses SRAM.
How does this affect you? Games are capable of fetching and changing play variables directly in the save file. It won't look like RAM, because the addresses of quantities stored in SRAM are waaay off. SRAM is located from $6000 to $7FFF in the CPU. Any time you see a reference to a location in the six or seven thousands, you can consider it identical to a RAM address.
The hex numbers
Let's briefly go over the middle column of the disassembled file. There's not too much to say about it. Take another look to refresh your memory.
00000004: 8D 00 20 sta $2000
This line has three numbers in the middle column. The first is $8D. The first hex number always represents the program instruction of that line. In this case, $8D represents STA Q. Don't worry yet about what a STA is, or how the Q magically turned into a $2000 in the right-hand column. We'll get there. After the $8D are two more numbers. Not every line has three numbers in it. Some have one, and some have two. The number of numbers depends on what the first number is. $8D is always followed by two numbers. Others, like $85, are always followed by one number. Yet others, like $78, are never followed by any numbers. We'll get there, too.
There is one important thing to note here that relates to the addresses we were just discussing. After the $8D comes "00 20." According to the right side, this refers to address $2000. Why is it all scrambdly? "20 00" looks like $2000, but "00 20" looks like $0020, right? Welcome to the wonderful world of computers. Way back in the day, some genius decided to make his new processor store numbers half-backwards. (It had to be a "he;" only a man would!) That's right, half backwards. Half backwards. Yep, half backwards. Okay, enough sneering. Consider a four digit number xxyy. In the computer, this is stored as "yy xx." It's convienient for the computer, but a pain for us. Now consider a four digit number wxyz. This is stored as "yz wx." It's the same principle--last two digits first, first two digits last. Take some examples:
1234 --> 34 12
3030 --> 30 30
87E4 --> E4 87
367 --> 67 03
Whoa, waitaminute! Remember, folks: you won't always see the leading zero. 367 is really 0367, which more obviously becomes "67 03." Here's another trick question:
45 --> 45 00
You won't see this on the NES more than once or twice, but it happens a lot in the real world. 45 is really 0045, which becomes "45 00."
The instruction column
Okay, we're going to have to face the music sooner or later. Let's go back:
00000004: 8D 00 20 sta $2000
So, what is a STA, anyway? It almost sounds like a Hollywood agent: "Ah'm gonna make you a stah, baby!" Ahem. The three-letter symbol represents the action that the computer takes when it executes that line. In this case, STA stands for "store the contents of A in the given address." Argh, a new symbol. What's "A"? It's time for an introduction to registers.
There are two types of registers, but we're only concerned with one. Remember from the overview that our registers are special areas of memory built into the CPU. As far as code making goes, we only have to worry about three of these.
A: The accumulator. That's just a fancy name for "math scratchpad." Very, very few mathematical operations work directly on RAM addresses. The vast majority instead work on the contents of the A register. To use these, the game must load the number into A, do the math, then store the contents of A back into memory. A is also used to store numbers directly into memory and to copy numbers from one part of memory into another. The 6502 does not support memory-to-memory transfers, and A is usually involved in getting everything into the right place.
X, Y: The indices. An index register is a way of getting at a number somewhere in the vicinity of a given address. The current contents of the index are added to the address to yield the actual location of the desired number. For example, "$0500,X" means that the address in question is equal to $500 + X. If you've ever worked with other programming languages, you may have worked with arrays. For example, "foobar[x]" means "the xth element of foobar." The concept is exactly the same, and you could even write "$0500,X" as "$0500[X]"--the xth number after $500.
Most of the instructions you will use when making codes will involve registers, especially A. Now, consider STA again: store the contents of A into the address. Is it still scary? Hopefully, it isn't.
After the instruction name is the parameter, if any. What's a parameter? It's the number or address an instruction works on. "STA $2000" stores A into $2000; $2000 is the parameter. Not all instructions take parameters. For example:
00000000: 78 sei
SEI just does its thing, on its own. The function performed by SEI isn't affected by any other number, so there aren't any. If you're curious, SEI means "set interrupt." Don't try to remember it. In fact, SEI is one of a few forbidden instructions that you should never mess with yourself. To the computer, it's like hitting below the belt.
Now that you've seen each part of the translation in detail, it's time to introduce some program instructions. Don't try to understand what every single instruction in a game means. We're only going to cover the important ones here. If you just can't get past some odd-looking name in your file, you can look them all up in the GTE processor reference doc in the file section. (It's a long file; scroll about halfway down)
Important 6502 instructions
First, I'll introduce you to your new best friends: load A and store A.
A1 LDA (Z,X) LDA direct indirect indexed w/ X
A5 LDA Z LDA direct
A9 LDA #n LDA immediate
AD LDA Q LDA absolute
B1 LDA (Z),Y LDA direct indirect indexed w/ Y
B5 LDA Z,X LDA direct indexed
B9 LDA Q,Y LDA absolute indexed w/ Y
BD LDA Q,X LDA absolute indexed w/ X
LDA, or "load A," does just that. It takes a number and puts it into the A register. The eight addressing modes above are explained in the overview. The three most important ones are highlighted. To summarize: LDA Z fetches the contents of the given one-byte address and puts them in A (i.e. LDA $12 gets whatever is at address $12 and puts it in A), LDA Q fetches the contents of the given two-byte address and puts them in A (i.e. LDA $1234 gets whatever is at address $1234 and puts it in A), and LDA #n puts the given number in A (i.e. LDA #$1C puts the literal number $1C in A).
81 STA (Z,X) STA direct indirect indexed w/ X
85 STA Z STA direct
8D STA Q STA absolute
91 STA (Z),Y STA direct indirect indexed w/ Y
95 STA Z,X STA direct indexed w/ X
9A STA Q,Y STA absolute indexed w/ Y
9D STA Q,X STA absolute indexed w/ X
STA, or "store A," is the opposite of LDA. It takes whatever is inside the A register and copies it into the given address. The addressing modes are the same as for LDA, except the lack of an immediate mode. (You can put the number $5 into address $20, but you can't put the number $5 into the number $20!)
Keep in mind that the A register only holds one byte. This is a number from 0 to 255, from $0 to $FF. Unless the number following LDA or STA begins with a #, it says nothing about the actual value of A. Say that address $1234 holds the number $10. LDA $1234 does not mean that the number $1234 will be loaded into A. In fact, A isn't big enough to hold it. A will be filled with one-byte contents of $1234. Thus, LDA $1234 puts the number $10 into A. The same is true of STA. Say that A currently holds the number $10. STA $1234 puts that $10 into address $1234. The fact that the address is two bytes long has nothing to do with the size of the number in A.
Why are LDA and STA so important? As far as changing values in RAM, these are how the job gets done. Before the game can take 5 HP out of your health, your health has to pass through the A register. This happens when the RAM address containing your health is loaded into A, $5 is subtracted from A, then A is stored into the address with your health. It looks somewhat like this:
LDA $1234 <-- load health from $1234 into A
SBC $05 <-- subtract 5 from A (to come later)
STA $1234 <-- store A back into $1234
There may be some variations from this theme, but that's the basic idea. Can the game ever change your health without using A? We'd better look at increment and decrement to answer that question.
E6 INC Z INC direct
EE INC Q INC absolute
F6 INC Z,X INC direct indexed w/ X
FE INC Q,X INC absolute indexed w/ X
INC, or increment, adds one directly to the contents of the given address. For example, if address $12 contains the number 4, INC $12 makes address $12 contain 5.
C6 DEC Z DEC direct
CE DEC Q DEC absolute
D6 DEC Z,X DEC direct indexed w/ X
DE DEC Q,X DEC absolute indexed w/ X
DEC, or decrement, is the opposite of INC. It subtracts one directly from the contents of the given address. So, if address $12 contains the number 4, DEC $12 makes address $12 contain 3.
INC and DEC may seem somewhat insidious, as they can go behind the back of the A register and sneak in math operations when nobody is looking. Luckily, they are the only non-"store something somewhere"-type instructions that can change RAM. In games, they are used most often to update counters and to scroll values up or down. You may have seen games in which your money rapidly runs down instead of instantly dropping? That's DEC at work. The use of these instructions is quite simple:
INC $50 <-- add 1 to whatever is in $50
They are also used in more complicated blocks:
10: LDX #$05 <-- load the X register with 5 (ignorable)
12: DEC $1234 <-- subtract one from your money at $1234
15: DEX <-- subtract one from the X register (ignorable)
16: BPL $12 <-- go back to 12 if X is positive (to come later)
Without worrying about the other instructions yet, the above block basically subtracts 5 bucks from your cash flow, one at a time. In a real game, there would be more lines in it to update the screen display of your budget after each DEC operation.
The above example brings up the existence of instructions similar to these four. We'll look briefly at what they do, but it's up to you to read more about them if you wish.
LDX: Loads the X register with a number.
LDY: Loads the Y register with a number.
STX: Stores the contents of X into an address.
STY: Stores the contents of Y into an address.
INX: Increment X.
INY: Increment Y.
DEX: Decrement X.
DEY: Decrement Y.
All of these are the same as their more common versions, but they work on the index registers instead of on A or on RAM.
Far above, I let a subtract instruction slip in. This would be a good time to introduce the math commands.
61 ADC (Z,X) ADC direct indirect indexed w/ X
65 ADC Z ADC direct
69 ADC #n ADC immediate
6D ADC Q ADC absolute
71 ADC (Z),Y ADC direct indirect indexed w/ Y
75 ADC Z,X ADC direct indexed w/ X
79 ADC Q,Y ADC absolute indexed w/ Y
7D ADC Q,X ADC absolute indexed w/ X
ADC, or "add with carry," adds a number to the A register. Inside P, a register we don't really care about, is a carry flag. It's like writing a 1 above the next column. Instead of telling you when the two numbers being added result in something over 10, this carry flag tells you when A and the number add to something over 255. (The name is a mystery, as there is no "add without carry") The addressing modes are the same as for LDA. ADC $12 adds the contents of address $12 to A, ADC #$12 adds the number $12 to A, etc.
E1 SBC (Z,X) SBC direct indirect indexed w/ X
E5 SBC Z SBC direct
E9 SBC #n SBC immediate
ED SBC Q SBC absolute
F1 SBC (Z),Y SBC direct indirect indexed w/ Y
F5 SBC Z,X SBC direct indexed w/ X
F9 SBC Q,Y SBC absolute indexed w/ Y
FD SBC Q,X SBC absolute indexed w/ X
SBC, or "subtract with carry," is the opposite of ADC. It subtracts the given literal number or the contents of the given address from A. The carry flag is set when the result of the subtraction is a negative number. The addressing modes are the same as for ADC.
ADC and SBC are used to add and subtract more than one from an address. Unlike INC and DEC, however, they only change the number in A, which has to be put back in the address later. You've already seen an example of SBC. ADC works the same way.
Of less importance are the binary math operators. You will see these frequently, but will almost never need to use them.
ORA: Binary ORs A and the given number/address together.
AND: Binary ANDs A and the given number/address together.
EOR: Binary XORs A and the given number/address together. EOR #$FF is often used as a cheap substitute for binary NOT.
BIT: Tests the bits in A, supposedly. Just sounds like AND to me.
ASL: Shifts A left by the given number of bits. Remember "arithmetic shift left" for the next one.
LSR: Shifts A right by the given number of bits. The name looks like "left shift right" or something equally stupid, doesn't it? It actually means "logical shift right." I never could figure this one out until they told me that.
Before we go into the last set, let me show you a handy tool to have.
EA NOP NOP implied
NOP stands for "no operation." This makes the computer kill time. It sounds useless, but it is actually quite helpful at times. NOP can be used to replace operations such as DEC and SBC that take away your health and money.
The last instructions of any real concern to you are the so-called "flow controls."
C0 CPY #n CPY immediate
C1 CMP (Z,X) CMP direct indirect indexed w/ X
C4 CPY Z CPY direct
C5 CMP Z CMP direct
C9 CMP #n CMP immediate
CC CPY Q CPY absolute
CD CMP Q CMP absolute
D1 CMP (Z),Y CMP direct indirect indexed w/ Y
D5 CMP Z,X CMP direct indexed w/ X
D9 CMP Q,Y CMP absolute indexed w/ Y
DD CMP Q,X CMP absolute indexed w/ X
E0 CPX #n CPX immediate
E4 CPX Z CPX direct
EC CPX Q CPX absolute
CMP, or compare, compares A to the given number or address. This tells the computer if A is equal to, less than, or greater than that number. CPX and CPY compare the indices to the given number.
90 BCC L BCC relative
BCC, or "branch if carry clear," causes the computer to jump a bit ahead or behind in the program if the carry flag is clear.
B0 BCS L BCS relative
BCS, or "branch if carry set," causes the computer to move a bit if the carry flag is set.
F0 BEQ L BEQ relative
BEQ, or "branch if equal," seems to have a number of uses. It is used with CMP to make the computer move elsewhere when two numbers are equal. It can be used to move elsewhere when a conditional test is false. It also seems to move elsewhere when the last number loaded into A was zero.
D0 BNE L BNE relative
BNE, or "branch if not equal," is the total opposite of BEQ. It makes the computer move elsewhere when CMP says that two numbers are not equal, when a conditional test is true, or when a number is not zero.
30 BMI L BMI relative
Believe it or not, BMI stands for "branch if negative." (BNE was taken) This makes the computer move elsewhere when CMP says that A is less than another number, or when a subtract or decrement operation produces a negative result.
10 BPL L BPL relative
Another odd one, BPL stands for "branch if positive." This makes the computer move elsewhere when CMP says that A is greater than another number, or when a math operation produces a positive result.
50 BVC L BVC relative
BVC stands for "branch if overflow clear." The overflow bit is another part of the P register.
70 BVS L BVS relative
BVS, "branch if overflow set," is the opposite of BVC.
4C JMP Q JMP absolute
6C JMP (Q) JMP absolute indirect
JMP, jump, makes the computer jump to the specified CPU ROM address with no intention of coming back. Unlike the branches, which give the location to jump to relative to the current address, jumps give absolute CPU addresses. JMP (Q) looks inside the given two-byte address to get the address to jump to. (See the overview for an explanation of indirect modes)
20 JSR Q JSR absolute
JSR, sometimes called "jump to subroutine" and sometimes called "jump saving return address," behaves similarly to JMP. The difference is that the computer intends to come back to its current location later.
60 RTS RTS implied
RTS, or "return from subroutine," is the opposite of JSR. When the computer hits an RTS, it jumps back to the last JSR it performed and moves on.
All of these branch and jump instructions cause the computer to run off and perform other tasks or to skip a few lines under certain circumstances. The jumps are entirely ignorable, but you must get comfortable with the branches. Remember this?
10: LDX #$05 <-- load the X register with 5
12: DEC $1234 <-- subtract one from your money at $1234
15: DEX <-- subtract one from the X register
16: BPL $12 <-- go back to 12 if X is positive
If you've never seen BPL before, you won't be able to follow this set of instructions. You'll get the load X, the decrement money, and the decrement X, but you won't even begin to realize that the decrements are performed five times each. Conditional branches are what separate games from movies, and you'll have to learn to live with them.
One other thing you may see in your disassembled file, depending on the translator you used, is ".db" followed by a number.
00001234: 17 .db $17 ;Invalid opcode
The little ".db" stands for "data byte." When you see this, it means that the first number on the line is not a program instruction at all. This serves two purposes. First, you know that the line in question must contain data used by a different part of the program. When you see many of them clustered together, you can reasonably assume that even program-looking lines squeezed between them are really also data. Second, you know never to use the number in question to replace a program instruction, as the CPU won't know what to do when it gets there.
Putting it all together
By now you must be bored out of your mind. "Just tell me how to make myself invincible, already!" One step at a time, grasshopper. First you have to understand what Game Genie codes do to the game.
Let's look at a sample code. Most of the codes we'll work with are eight letters long. Gasp! Didn't I tell you before not to mess with eight letter codes? That was only because you don't have the tools to work with them sitting in front of an NES. Sitting in front of a computer, you do. Anyway, let's start by dissecting a code.
NNELIYZO = 3785 ? 12 : FF
The Genie code is obvious enough, but the hex code takes some explaining. The first four-digit number is the CPU address of the code. Or is it? Remember, CPU addresses run from $8000 to $FFFF, regardless of the actual cartridge or file position. Can $3785 be a CPU address? That's the odd thing about the NES Genie: it's the only one that farts the address. NES codes always run from $0000 to $7FFF. The Genie then adds $8000 to them later. Thus, $3785 in the code really refers to CPU address $B785. (There is a reason why the codes do not contain the actual CPU address, but it only relates to user-friendliness)
Following a '?' is a two-digit number. This is what separates six and eight letter codes. This number is the check value. Consider our CPU address map again:
00000000 --> 00008000
00002000 --> 0000A000
00003785 --> 0000B785
00004000 --> 0000C000
00006000 --> 0000E000
00007FFF --> 0000FFFF
00008000 --> 00008000
0000A000 --> 0000A000
0000B785 --> 0000B785
0000C000 --> 0000C000
0000E000 --> 0000E000
0000FFFF --> 0000FFFF
00010000 --> 00008000
00012000 --> 0000A000
00013785 --> 0000B785
00014000 --> 0000C000
00016000 --> 0000E000
00017FFF --> 0000FFFF
On the left are the absolute game positions; on the right are the relative CPU addresses. Now, we've just seen that Genie codes refer to CPU addresses. Our example is $B785. Look at the above diagram and tell me which absolute address $B785 corresponds to. You can't, can you? It could be $3785, $B785, $13785, $1B785... The Genie can't tell, either. This is where the check value comes in. Look at what our sample addresses might look like:
00003785: 12
0000B785: A9 04
00013785: 0D E4 05
0001B785: 37
Is there any way to distinguish the different $B785s? Sure, their contents are different. $3785 holds a $12, $B785 holds an $A9, $13785 holds $0D, and $1B785 holds $37.
Without a check value--you gave it a six letter code instead--the Genie doesn't know which $B785 to change. So, it changes all of them. In the above example, this is bad. Pretend that $3785, the one with the $12 in it, holds the number of gems you start with. You want to max it out and start with 255 gems instead. So, you make a code to replace $B785 with $FF. You punch it in and the game crashes. Why? $3785 and $1B785 just hold numbers, so those are safe to change. However, $B785 and $13785 are part of the game program. You just replaced the program instructions with something that isn't a program instruction, and now the NES is sulking.
This is why check values are so good, and why we will be working with eight letter codes. Look at our sample code again: 3785 ? 12 : FF. The $12 is the check value. What does it do? It tells the Genie to change only those $B785s that contain $12. Remember the diagram of the CPU slide rule: $B785 is one thing this moment and another thing the next. Given a check value, the Genie will wait for the address to take on the check value before acting. Now, only $3785 above is changed, because only it contains $12. The result: you start the game filthy stinking rich, and the game doesn't crash.
It isn't guaranteed that only one absolute address will contain the given check value. I can think of a game off-hand that threw me for years because I searched for the first instance of the check value and stopped there. Only after I gave up on that part of the game and went looking for another did I find the real thing. It was only a coincidence that a piece of data at the same relative address held the same number. In these cases, the Genie will change both. The Genie doesn't know where it is in the cartridge, only that it is supposed to change a CPU address when it contains a number.
The last part of the code is the data value. This is the two-digit number following the ':'. The data value is what the Genie puts in the given address. In the above example, when it gets to the right $B785, it replaces whatever is there ($12) with $FF. "Hey, you said you can't change the ROM in the cartridge!" You can't. The CPU copies 32K of the game into its own memory, remember? The Genie intercepts that loading process and tricks the CPU into copying something else. The cartridge still has a $12 at $3785, but the CPU thinks it held $FF.
It's time for another quiz. First, go back to our sample addresses:
00003785: 12
0000B785: A9 04
00013785: 0D E4 05
0001B785: 37
Now, your job is to apply three codes. The answers will be color-coded. Your codes are TEELTYGA, KNELTYKT, and AXELIYZP. Converted to hex, these are B786?04:06 , B786?E4:F4 , and B785?12:20 .
00003785: 20
0000B785: A9 06
00013785: 0D F4 05
0001B785: 37
Did the addresses throw you? Remember, the byte next to $B785 is $B786. Only the first byte on the line is numbered.
Changing the program
When the most important program instructions on the NES were listed and explained, each was accompanied by a number. Check them out: LDA Z is number $A5, STA Q is number $8D, RTS is number $60, etc. (All of which you, too, will probably have memorized by the time you're done!) Why are these mystery numbers listed? Believe it or not, the number alone tells the CPU what to do. If you open up your original game (FOOBAR.NES) in your hex editor, you don't see pretty symbols like CLD or ASL. All you see are numbers. (Okay, things like FD and EA look like symbols, even though they're really numbers)
Let's borrow part of our last example, changing the address for variety:
0001C321: A9 04
The first number on the line is always the one that the computer tries to execute. The instruction performed by this line is represented by $A9. If you go back to the list of instructions, you'll find that $A9 represents LDA #n. Thus, this line stores the number 4 in the A register. (This is how you read games without a disassembler, except you don't get line breaks. My apologies to my Mac-using brethren, as it seems you might have to do it this way...)
This is all the Genie sees when the cartridge is read in. Heck, the Genie doesn't even care what "A9 04" means. It just knows that you told it to replace $4321 with $FF when it equals $12, and that $A9 isn't $12.
To replace one instruction with another, you must replace the number of the instruction with the number of another. Say you want to replace the LDA #$04 above with INC $04. You already know that the LDA #n is $A9 just by looking at it. Now you need the number of your new instruction. Here's where you have to figure out which of the four INCs you want.
E6 INC Z INC direct
EE INC Q INC absolute
F6 INC Z,X INC direct indexed w/ X
FE INC Q,X INC absolute indexed w/ X
Refer to the overview if you can't remember what on Earth "direct" and "absolute" and the rest mean. In summary, Z is a one-byte address, an address between $00 and $FF. Q is a two-byte address, anything from $0000 to $FFFF. Z,X and Q,X are the same, but the contents of X are added to the address represented by Z or Q.
So, which one do you want? $04 is a one-byte address. You need either INC Z or INC Z,X. A quick rule of thumb: don't bother with the indexed versions unless the original line uses an index. We'll take INC Z. The number for that is $E6. That means that we intend to change the $A9 at address $1C321 into $E6. Hmm, we're also going to need the Genie-fied CPU address of $1C321. That's easy: keep subtracting $8000 from the address until it is less than $8000. Watch the math unfold:
1C321
14321
C321
4321
The Genie address of our code is $4321. (The real CPU address would be $C321, but Genie codes are always $8000 less, remember?) Finally, we want to go to $4321, see if it is equal to $A9, and change it to $E6 if it is. Put the address, check value, and data value together like so: 4321?A9:E6. This is the hex code to do what we want. If you prefer testing your codes in an NES emulator, you can enter this as is. If you want to use the code on a real NES, however, you'll have to put it into Genie format. The process is explained in the NES conversion formula, but it is much faster and easier to use a conversion program (if you can... Sorry, Mac folks). You can find such programs everywhere, and there is one in the file section.
4321?A9:E6 --> VTXGPUOZ
Now it's your turn. As this stuff gets more complicated, you'll be quizzed more often. (Boy, what I wouldn't give for a copy of Javascript for Dummies!) Your job is to make a code that replaces the following STA instruction with something suitable. We're trying to keep the address listed from decreasing, so stay away from DEC. Here's the program:
00005B5B: AD 33 03 lda $0333
00005B5E: E9 10 sbc #$10
00005B60: 8D 33 03 sta $0333 <-- change this
There's a world of possibilities, so I'll leave the choice up to you for now. The answer here uses the most common replacement, LDA. The first step is to figure out which STA we are replacing. $8D is STA Q, so we should use XXX Q to replace it. We'll use LDA Q. What's the number for that? Actually, $5B5B contains the number we want, $AD. So, we'll replace the $8D with $AD. Now we need the Genie address. $5B60, the location of the $8D to be changed, is already less than $8000. The final address is simply $5B60. Put all the pieces together: $5B60 contains an $8D to be changed to an $AD. In hex form, we write this as 5B60?8D:AD. This becomes the Genie code SZVIEUSE. No matter what you chose to replace the STA with, your hex code should look like 5B60?8D:xx and your Genie code should look either like xxVIEUSA or xxVIEUSE.
Changing the program better
Why did we replace STA Q with LDA Q? Out of nearly 160 instructions, why that one? The subtle secrets of LDA and STA in particular will be discussed later. In general, you should replace instructions with their relatives. ADC goes with SBC, ORA goes with AND, BPL goes with BNE, etc. By replacing instructions with equal but opposite instructions, you can be sure that your code doesn't operate merely by lucky side effects (and that it won't have any unlucky side effects... I can think of Galoob codes that don't work right because they broke this rule).
It is a good idea to stick to related instructions, but it is not mandatory and may even be restricting at times. On the other hand, it almost is mandatory that you use the same addressing mode, unless you are very lucky and you know exactly what you are doing. I can only think of one person who's ever succesfully made codes by breaking this rule, and he's universally regarded as a god. Don't try it. If the original instruction is followed by two bytes, replace it with one that takes two bytes. If the original instruction is followed by one byte, replace it with one that takes one byte. If the original instruction stands alone, replace it with a loner. In all of these cases, if the original instruction uses an index, use that same index in yours.
There is one time when you may be able to get away with changing addressing modes. If two or three consecutive lines contain the same number of bytes that your replacement instruction needs, you might be okay. Look at this:
00001234: CA dex
00001235: CA dex
00001236: CA dex
Yep, that's three DEX instructions in a row. These three lines taken together contain three bytes. What else contains three bytes? Well, LDA Z plus DEX make three bytes. LDA Q alone is three bytes. What if we replace the first DEX with LDA Q?
00001234: AD CA CA lda $CACA
Whee, we just loaded A with caca! Seriously, we just killed three DEXes with one stone. If you can change instructions such that subsequent line breaks don't shift as a result, you may be fine. Note the way that the three lines in question moved up into a single line. LDA Q wants a two-byte parameter, and it grabs the next two bytes it sees for itself.
Another way to do the same thing is to replace XXX Z with XXX #n or vice versa. Both take one byte as a parameter, so nothing gets moved when you do. Thus, you can safely replace LDA $40 with LDA #$10, for example.
The dangers of changing registers
Okay, I promised to tell you the dark secrets of the load and store operations... well, of the load operation, anyway. LDA, LDX, and LDY each replace the current contents of their respective registers with something new. That's great--unless the old contents were important. Then you have trouble. As an example, there is an infinite lives code in the NES codebook that glitches horribly in the second half of the game. Sure, you get infinite lives, but you also warp to a different level when you die. What could possibly be wrong with an official Galoob code?
The guy that made the code thought that a good way to keep your lives from changing would be to make the changes to X instead of to A. That way, when A is stored into your lives, nothing has changed. There's just one problem: X was already in use. By loading your lives into X, you overwrite critical game data with random garbage. Now, don't get me wrong; there's nothing wrong with the code. In fact, I found you can fix it by using Y instead of X. The issue here is simply one of not looking before taking a leap.
How can you tell if a register shouldn't be messed with? You have to use context clues. This can only be explained with a million examples.
00005B5B: AD 33 03 lda $0333
00005B5E: E9 10 sbc #$10
00005B60: 8D 33 03 sta $0333
Here we have an example of A being loaded with something just long enough to subtract $10 from that something. Let's say that $0333 is the RAM address with your health in it. Now, is it safe to replace STA with LDA? Sure it is. A is currently devoted to your health. There's nothing wrong with putting more of your health into it. When you see these LDA/STA pairs, rest assured that another LDA won't hurt anything.
00001030: A5 04 lda $04
00001032: 85 3C sta $3C
00001034: 85 3D sta $3D
00001036: A5 05 lda $05
00001038: 85 3E sta $3E
Say we have a reason to protect that address $3D. We want to change STA $3D to LDA $3D. Can we? Immediately after that line is a LDA. No matter what we do to A at this point, A is going to be reloaded with the right value in the next line. We can change it.
Now, say that it is the $3C we want protected. Can we change the STA $3C into LDA $3C? Maybe. After the contents of address $4 are placed in $3C, they are also placed in $3D. By loading A with the contents of $3C, we instead place those in $3D. With this one, you'll just have to try and find out. It probably doesn't matter if you screw up address $3D, but it still might. (In this case, I'd recommend changing STA $3C into another STA $3D... But we'll get to that later)
000088A2: A2 05 ldx #$05
000088A4: 8E 9C 02 stx $029C
000088A7: B5 40 lda $40,X
We don't like the STX $029C. Can we change it to LDX $029C? I wouldn't. In the LDA after it, X is used as an index. Right now, A is loaded from address $40 + $5, or $45. Change X to something else, and the Lord only knows where A will come from. If A is being used for something important, all kinds of havoc will result. On the other hand, we can very safely change the STX $029C into LDA $029C, as A is going to be given a new value in the next line.
If it is the LDA $40,X we don't like, we can go ahead and change X. That way, A probably won't come from $45 anymore.
00010202: AD 11 01 lda $0111
00010205: 8D 12 01 sta $0112
00010208: 20 13 80 jsr $8013
Now we want to get rid of the STA $0112. Can we make it a LDA $0112? Probably, but it isn't guaranteed. The JSR tells the computer to jump to a different part of the program. If the game is, well... To put it flatly, if the game is badly programmed, it may want to start using the contents of A right away when it gets there. You can't see what the game is going to do after the jump unless you figure out where CPU address $8013 currently is and scroll there. Try LDA. If it doesn't work, try LDY. If that doesn't work, try LDX. If the wretched thing still doesn't work, get imaginative. Try ORA, CMP, or something else that doesn't involve registers at all.
That last tip is a sound piece of advice: when in doubt, pick a replacement that doesn't change a register. CMP is often good, unless the game uses fancy logic tests:
00004567: AE 77 04 ldx $0477
0000456A: F0 16 91 beq $9116
Conditional branches such as BEQ are rather sensitive creatures. Watch what you do around them. Otherwise, get creative. Hey, the worst that can happen is the game crashes. (Unless there are saved games in the cartridge)
Code-finding tips (finally!)
When you opened this document on making cheat codes, you probably weren't expecting a full-blown computer science lecture. You'll thank me when you get to college. Anyway, none of this information is any good if you can't even find the right part of the program to change. I'll assume first that you're here because you don't have any codes for your game. Later, we'll go over ways to squeeze new codes out of old ones.
To make a code when you have nothing to go on, you need to find a relatively unique and recognizable aspect of the game. Do you start with $12,000? (That's dollars, not hex digits!) Perhaps you start with 28 energy? Or maybe you always lose 30 gems when you cast a spell? You need a factoid that you can pick out amidst a sea of strange numbers. Of course, this won't work for every game. Yes, I can still picture in my mind the way my arch-enemy operates... Sorry, there's a game I haven't been able to figure out for the past two years. You will probably run into a few stumbling blocks such as this. If you try and try and just can't make codes for a game, find a new one. Don't get discouraged if it doesn't work the first time.
The 6502 instructions we discussed were chosen for a reason. Not only do they make the best replacements to use in your codes, they are the most common ways of getting things done in the original program. These are the ones you will be working with most often. Let's see how the game probably does things.
Initial value codes: To initialize values at the beginning of the game or at the beginning of a level, they have to be loaded into a register (almost always A) and stored in the right place. If the actual number is uncommon enough, it shouldn't be too hard to find the part of the game that does this. Of course, if the only number you can find is a common one like zero, you may have to wade through hundreds of possibilities. Yikes! Anyway, numbers are initialized using LDA/STA pairs. For example:
LDA #$1E
STA $05C2
This loads the number $1E, or 30, into A and immediately puts it into the address $05C2 in RAM. Remember, things like money and life that can change will always be in RAM. Sometimes more than one value is set to the same thing:
LDA #$1E
STA $05C2
STA $05C3
This loads the number $1E and stores it into both $05C2 and $05C3. You might see this when both your current and maximum amounts of something can change.
The best way to find initial value codes is to look for LDA #$something, where "something" is the number placed there at the beginning of the game. To find the above example, you would have the computer search for "LDA #$1E." This is what makes some of these codes rather frustrating. LDA #$1E probably appears many, many times. You have to use your judgement when a match comes up. Is it followed by a STA? Is there even a STA anywhere in the vicinity? There probably shouldn't be any math operations around it, and there certainly shouldn't be any jumps or branches. Weed out the unlikely suspects to lessen your workload.
To find out if that part of the program is really responsible for setting your initial values, you have to change the number used. In the above example, you might change the $1E to a $10 and see if you start with less than usual. Remember how we change things?
00014502: A9 1E lda #$1E
00014504: 8D C2 05 sta $05C2
00014507: 8D C3 05 sta $05C3
First, you need to get the address of the number to change. It is next to the number at $14502, so we know it is at $14503. Subtract $8000 from the address until it is less than $8000. This results in $4503. Now, write the hex code as the new address, followed by the number we want to change, followed by our replacement. This gives 4503?1E:10. If you wish, convert that to Genie format. The resulting code is APEGLSTP. If it is the right code, you should start with 16 units of something instead of 30. If not, look for another piece of program like it and make a code out of it until you find the right one.
Fixed change codes: Some games always change a certain quantity by the same amount. For example, shooting a pedestrian may always cost you 100 points. These usually look like initial value codes with a math operation thrown in. For example:
LDA $041A
SBC #$64
STA $041A
These program sections usually only appear once, maybe twice. The best way to find one is to search for the math operation behind it. Losing 100 points means "subtract 100," or "subtract $64." So, search for "SBC #$64." Gaining 100 points would mean "ADC #$64." Again, you may see the search string several times. If it isn't surrounded by "LDA address" and "STA same address," it almost certainly is wrong. That doesn't mean that there can't be anything else with it, but the LDA/STA pair must be relatively nearby.
You check these codes in the same way as initial value codes: by changing the amount used by the game. Try a code to double the penalty for trigger-happiness: subtract 200 ($C8) instead of 100.
00008120: AD 1A 04 lda $041A
00008123: E9 64 sbc #$64
00008125: 8D 1A 04 sta $041A
Use the code-making steps described above to change $8124 ($0124) from $64 to $C8: 0124?64:C8, or EGXAGPGV. If it works, you should lose twice as many points for reckless slaughter as usual. (Of course, the sadists among you may wish to subtract 0, or even to add 100 by changing the SBC #n to ADC #n)
Dirty, evil trick alert: Some games store information in unimaginably stupid ways. Others store information in unimaginably clever ways. Either case can present a problem when looking for that information. For example, the timer in one game is split between three bytes: one for the hundreds place, one for the tens place, and one for the ones place. Gak! It also may be possible that a game stores information using bit flags. Bit flags will be described in the SNES tutorial, as I have yet to see an NES game use them. (They're also explained in Matt Johnson's math tutorial.)
Locating existing codes
The next section explains how existing codes can help you find more. If the codes aren't your own, however, you will have to hunt for them. This is easiest with eight-letter codes. Start by converting the code to its hex format. You now have a CPU address, a check value that must be located there, and a replacement value. Because the CPU address can refer to one of hundreds of file addresses, you have to look at each and see which ones contain the given check value. In most cases, you keep adding $8000 to the given address until you find the right one. Here's an example using the hex code 3014?1C:32.
00003014: A9...
0000B014: 10...
00013014: 5A...
0001B014: 1C...
File address $1B014 contains the check value, so it will be modified by the code. There may be others after it, but you locate them in the same way.
A few evil games make this difficult. If you keep adding $8000 to the address all the way to the end of the file and never find the code, you may have an evil game. Go way back up to the top of the file and add $4000 to the address in the code. If the resulting code has an address greater than $8000, subtract $8000 from it. Now proceed normally, adding $8000 each time until you get a match. First we'll try to find the code 7014?10:20 in such a game the normal way.
00007014: 15...
0000F014: EA...
00017014: 42...
0001F014: 9A...
00027014: 0B...
It never appeared, so we will adjust the code. The address is $7014, so we start by adding $4000 to it to get $B014. It went over $8000, so we subtract $8000 to get $3014. Now we try again with the new address.
00003014: A9...
0000B014: 10...
Now we've got it! Why some games do this, I just don't know. Now, what if your code only has six letters in it? Without a check value, it is impossible to tell exactly where the right code is located (unless the game is 16K or 32K in size). If you have other codes whose exact locations you know, you can probably assume that all of your codes are in that general area, probably even in the same CPU ROM area. You still have to use your noodle to figure out if the code makes sense in its projected location. Say you have the code 3014:1F and you think it has to be in one of these places:
00013014: A9 05
0001B013: 05 14
00023014: 0A
One of these things is not like the others. Consider the value inserted by the code, $1F. It doesn't represent an NES program instruction, and should never appear at the beginning of a program line. (Lines you know contain only data are okay) If you placed the code at $13014 or $23014, the game would crash. Of these three, only $1B014 could be the code's location.
Using existing codes
Once you have a code for your game (and know exactly where in the file it is), you can derive all sorts of information from it. Check out one of the examples:
LDA $041A
SBC #$64
STA $041A
Say you were able to turn this into a working code. What does that tell you? Let's analyze the program. First, it loads something from RAM at $041A. Then, it takes $64 away from that number. Finally, it stores the result back into $041A. You know now that it takes $64 away from your score. That must mean that $041A is synonymous with your score! Congratulations, you've just discovered one of the details lost when the game was compiled. Now, anytime you see an address of $041A used in the program, you can be sure that it affects your score.
How does that help? Now you can find other score-related codes. Say you want to double the reward for blasting a Megabot. You know that the game adds something to something... but more importantly, you know that the result has to be stored into $041A using STA in order to change your score. So, tell the computer to search for "STA $041A."
00008250: AD 1A 04 lda $041A
00008253: 7D 00 83 adc $8300,X
00008255: 8D 1A 04 sta $041A
This has to be it! But... ADC $8300,X adds a variable quantity to your score. Doubling it from here would be a mess. Why the variable? Megabots are worth more than Minibots. It's easier to look up the point value than to include separate routines for every single type of enemy. Hence the index: the point values are probably listed sequentially, and the game simply uses an index to get the right one.
What do we do? Well, there should be a LDX shortly above this block. That sets the pointer to the right bonus value. (If the game used an ADC indexed with Y, we'd look for a LDY)
0000824E: A6 $50 ldx $50
00008250: AD 1A 04 lda $041A
00008253: 7D 00 83 adc $8300,X
00008255: 8D 1A 04 sta $041A
That wasn't hard to find at all; it was right above it. Presumably, $50 holds the current type of enemy. It would be easy enough to make all enemies worth the same amount as the biggest one by trying LDX #ns in place of the LDX Z until we found the most profitable one. If you are really intent on only changing Megabots, though, we will have to move a bit. Start by figuring out which file address is referred to by the CPU address $8300, the address that the point value comes from. We are at $8250ish now, so the current CPU ROM area runs from $8000 to $FFFF. Remember how we figure that out? The current ROM area starts at the greatest multiple of $8000 less than the file address, and ends one short of the least multiple of $8000 greater than the file address. In this case, the CPU addresses happen to be the same as the file addresses. Otherwise, you would have to subtract $8000 from the CPU address and add the result to the file address that you just determined was the start of the current ROM area. Baffled yet? Just keep the slide rule in mind. (And here I told you there wouldn't be much math!)
Anyway, do the math and you find that CPU address $8300 is also file address $8300. Go there.
00008300: 10 15 bpl $8317
00008302: 20 25 30 jsr $3025
00008305: 40 rti
00008306: 50 A9 bvc $83B1
Do not be fooled by the program-like appearance! This is so NOT part of the program that I can't emphasize it enough. Let me explain why this has to be raw data. You're going to see this often, so you need to be prepared. First, remember why we're here. The game loads one of these numbers and adds it to your score. The game will only do this to an address set aside for data. If a programmer ever tried to read program instructions as data just because they were already good numbers, he'd be laughed out of the industry. Second, the instructions themselves are impossible. JSR jumps to an address in the CPU ROM area. $3025 isn't in the CPU ROM area, so you can't jump to it. RTI in the middle of a program would screw the whole thing up. (That's one of those forbidden instructions you should never use) Third, that A9 at the end looks suspiciously like the number for LDA #n, and it probably is. Fourth, the numbers themselves are just too round, too convienient. (Converted to decimal, they wouldn't be, right? Actually, some strange games read hex numbers in as decimal numbers--these could already be in decimal!)
Anyway, you are looking at the point values loaded by the game when you kill a baddie. Which one is the Megabot's? Let's say it is the $40. That's the one you want to double. Change $8305 from $40 to $80 and see if it works. It better--this was a lot of work!
Why did I just take you on that horrid wild goose chase? Why couldn't the example simply have loaded a constant score, and we could have doubled it from there? Welcome to the real world. Games are almost never so straightforward, and you'll probably have to look up indexed values this way a few times yourself. Just remember: if the address that a number comes from is at least $8000, the number can be found somewhere in the file.
Besides, you also needed to see how data can be translated mistakenly. Most disassemblers can't tell program from data, and all of the 6502 translators that can are written specifically for Atari. Sad, but true. You need to know how to weed out the stuff that isn't really part of the program. Here's another example of such a thing:
00010000: FF .db $FF ;Invalid opcode
00010001: 17 .db $17 ;Invalid opcode
00010002: AD FF FF lda $FFFF
00010005: FF .db $FF ;Invalid opcode
The wheat-to-chaff ratio is so low here that the whole thing must be data. Another thing to note: look at all the $FFs here. That's a sure sign that something's amiss.
Here's another example (and I promise it will be short and direct this time!):
00001A10: A9 64 lda #$64
00001A12: 8D D2 03 sta $03D2
Let's say that by changing the $64 above into a $32, you made yourself start with half the usual amount of health. That means that $03D2 must contain your health. Can you find any other places with a STA $03D2?
0000301A: AD D2 03 lda $03D2
0000301D: ED 3C 04 sbc $043C
00003020: 10 03 bpl $3024
00003022: A9 00 lda #$00
00003024: 8D D2 03 sta $03D2
Hmm, what do you suppose this does? First, the address which you now know to be your health is loaded into A. A variable amount is then subtracted from it. If the result is still positive, it skips the next line. Otherwise, it loads zero into A. Finally, it puts A into your health. This must be the part that damages you. If you replace the STA--a LDA would work well here--you probably won't take damage anymore. If it doesn't work, look for another part of the game like it and change that.
This is fun, but what if you want a different code entirely? You only searched for an infinite lives code because it stood out; you really want an infinite health code. Take heart: with but a single important NES RAM address, you can find as many others as you want. You'll need a memory search program for this next part. You can find one in the file section. Oh, and you'll need an NES emulator, available from Zophar's Domain. (Geez, this whole site is beginning to look like a bloody ZD ad. If I have to link to them one more time...)
Using existing codes the odd way
To find a part of the program that changes a game value, you need to know the RAM address of that value. Luckily, there is a way to find one address relative to another. If you know one of them, you can then calculate the other. (More math! Aah!) To do this, you must find both values in the computer's memory.
Start by loading the game in the emulator. Next, load up your memory search program. Go back to the emulator and get into the game. You're going to be searching for the value you already know. If you started by making an infinite lives code, search for your lives. It shouldn't be too hard to do this. In the case of GameHack, the documentation is barely in English (the filenames aren't at all), but the program is relatively intuitive. Start by pushing the button that looks like two gears, and double-click on the name of your emulator. Next, push the little binoculars. Change "4 bytes" at the bottom to "1 byte," then enter the number you are searching for into the "Value 1" box. Go back to the game and do something to change the number. If you are searching for lives, die. Go back to GameHack and push the binoculars with the arrow under them. Follow the same instructions to search for the new number. If that isn't enough, change the number again, push the binoculars/arrow button again, and repeat until you get only one or two results. Remember, the program can be very slow at times. Give the computer a while before deciding it is frozen.
Once you are down to a handful of results, double-click on them to add them to the bottom list. Double-click on one and change the value. Go back to the game and see if there's a difference. You may have to change the value in the game before you see anything. If it doesn't work at all, delete that code by right-clicking on it and choosing "delete," and try the next one. Keep doing this until there is only one, and that one works.
Now, write down the address you get. For example, we'll say that your lives are at $80017FF5. Next to that, write down the NES RAM address you determined from the disassembled file. We'll use $4015. The last step is to use the memory search program to find something else. Try using it to find your health in the computer's memory. You may need to use the ranged or comparative searches; start a new search by pressing the big, arrowless binoculars, then change the top box that says "Exact value" to something else. (Either way, start by pressing the big, arrowless binoculars)
When you get what you want, write the address under the first one. We'll say that your health is at $80018000. Your paper should look like this:
Lives: $80017FF5 / $4015
Health: $80018000 / ?
Here's where you'll need a hex calculator. Start by subtracting the smaller computer address from the larger:
$80018000
--$80017FF5
-------------
$B
That means that health and lives are $B (11) bytes apart. Health is located after lives, so we'll add $B to the lives address to get the health address. If the health address comes out before that of lives, subtract instead. Anyway:
$4015
+ $B
-------
$4020
That's it! If $4015 represents your lives, then $4020 must be your health. Why does this work? The NES emulator is just that: a program that acts as much like a real NES as possible. To do this, it must keep all of the numbers in the game in the same order, at the same distances from each other. The actual positions are different, but their positions relative to each other are the same.
Why bother with this? The memory search is generally easier to use and more direct. You may not know anything obvious about your quantity, such as what it starts at and how much it changes. Worse, the amount of change may be variable. The memory search should tell you where it is anyway. The only catch is that you need at least one other code before you can use it.
Getting info from RAM dumps
If you're willing to compare and contrast several memory dumps by hand, you may be able to get the internal position of your game value without any other codes. To do this, you need an emulator program that allows you to dump the game's RAM to a file. I don't know how many do, but I know that NESticle supports this feature. Maybe the thing you are trying to find doesn't start with a unique value, and there's no rhyme or reason to the way it changes. If you know its exact value at any given moment, though, you may be able to find it yourself.
Start by playing the game until the quantity you want to find has a value that doesn't appear often, like 103 or 413. (0, 1, 16, and 255 are bad things to search for) Pause the game and take a RAM dump at this point. In NESticle, go up to the "CPU" menu, go down to "Debug," and choose "Dump RAM." Now, keep playing until the quantity changes, and take another dump (of the computer variety!). Make sure you remember what the value was at the time of each dump.
Now, open the first one in a hex editor. The extension should be ".D00." Search for the value that the quantity had when you made the file. Hopefully, there shouldn't be too many options. Stop looking when the address is greater than $800, as this marks the end of RAM. (There's other things in the file, including the entire ROM area) Open the second file (extension ".D01") and look at each of the addresses that matched in the first. The right one should now contain the quantity's second value. If you still have multiple possibilities, take a third dump after giving the quantity a different value, and look in the third file (extension ".D02") at each remaining address. Eventually, there should only be one address that consistently contains the value of the item in question. This is the internal RAM address of that item. You can now use this address as you usually would, searching the program for parts that change it.
Changing colors
To make codes that change the colors in the game, you need an NES emulator. I don't know if they all support this, so I'll explain the process using NESticle.
Go to the appropriate part of the game and press F4 on the keyboard. A box showing 32 colors should pop up. Click on each of the first four color blobs, and write down the numbers shown in order. (If any of the first four colors cycle, use a set of four from the top row that doesn't) Now, open the original game in your hex editor and search for that string. For example, if the first four colors show the numbers $0D, $00, $00, and $2B, search for "0D00002B." Go back to the game and get the number of the fifth color. Look at the match in the hex editor and make sure it is followed by that number. If it is, you've probably found it. Keep in mind that the same list of numbers may appear several times, or that this particular list may only affect this part of the game. In either case, you may have to repeat this process to change the specific colors you want.
Anyway, go back to the game and figure out which four colors are used for the thing you want to recolor. You can do this by clicking on a likely color, then sliding the RGB tabs around. The object in the game should change colors as you do this. Count off sets of four colors each until you figure out which four colors are used for your object. Get their numbers and look for them in the hex editor. They should be near the colors you've already found.
Next, choose up to three colors to replace the old ones with. (The first color is transparent and can't be changed) You'll need the number of each color to do this. Here's a rough guide:
0x = Dark 1x = Medium dark 2x = Bright 3x = Pale
x0 = Gray x1 = Blue x2 = Sky blue x3 = Purple x4 = Magenta
x5 = Pink x6 = Peach x7 = Red/orange x8 = Yellow
x9 = Yellow/green xA = Green xB = Sea green xC = Cyan
xD = Dark gray xE = Black xF = Black
For example, $13 is a deep bluish-purple. $2B is a bright sea green. $30 is white. Now, replace the old color numbers with the new ones in the same way that you replace everything else. Just remember, if the file in the hex editor has an .NES extension, you must subtract $10 from the address to account for the header!
Changing pictures
You can change the appearance of objects in the game in the exact same way that you change their colors. Go into the game and press F2. A jumbled mass of graphics should pop up. The trick is to hunt down each tile used in the object. A quick way to tell if a tile is part of an object is to click on it and begin doodling. The object should change as you do this. Gather the number of each tile in the same way as you did with the colors. Here's an example:
[00] [01]
[02] [03]
[07] [08]
[09] [0A]
The numbers read left to right, then top to bottom. Search for them in the hex editor in this order. The rest is the same: get the numbers of the replacement tiles you want, then make codes. The only trouble you might have is with horizontal mirroring. The NES is capable of flipping tiles and reusing them to form symmetrical designs. The tile numbers in the figure above could just have easily been:
[00] [01]
[02] [02] <--|
[07] [07] Same, but flipped
[09] [09] <--|
If you are aware of this, it isn't a problem. Just use the same tile number for both the left and right sides.
Pseudo-Game Shark
This last section is still experimental. I've only done this two, er, one and a half times myself. It works, but it also glitches the game's graphics terribly. For this, you pretty much need a copy of NESticle.
Go into the game and whack Alt-T a couple of times. Some stuff should come up at the bottom of the screen. Whack the button some more and then press F1. You should see the output here. For example:
[B012] lda $10
[B014] beq $B012
[B012] lda $10
[B014] beq $B012
:
:
Okay, some highly repetetive infinite loop-looking thingy came up. So? Yes, but consider the possibilities. Say you know the RAM address (we'll assume two bytes long) of your health, but nothing you can do to the game makes you invincible. For some reason, the stuff that looks like it should hurt you apparently doesn't. But, you still have the address. If you change an existing STA to change that health address, your health might refill. It would only happen when the game got to that point, however. If there were only a point in the game that gets called a lot...
There is, and you're looking at it. This little gem is called a VBlank. Why? It has something to do with TV screens. Anyway, the infinite loop you just found is hit every frame. Unfortunately, there isn't any room to stick a STA directly into it. Maybe you should look at that spot in your file? The trick, of course, is to find it. Start with $B012 and look for the above instructions. If they're not there, add $8000 and look there ($13012). Keep moving up by $8000 until you find them.
0000B012: A5 10 lda $10
0000B014: F0 FC beq $B012
0000B016: A2 1C ldx #$1C
0000B018: 20 00 C0 jsr $C000
Drat. You don't want to interfere with that jump, and there isn't enough room to stick a STA Q or anything else in there before it. You could follow the jump yourself and see what's down there. Remember how to find CPU addresses in the file? In this case, $C000 is simply $C000.
0000C000: 20 CD E6 jsr $E6CD
0000C003: 8D 07 20 sta $2007
0000C006: A4 15 ldy $15
0000C008: 8C 00 01 sty $0100
0000C00B: 8C 01 01 sty $0101
This is promising. Let's say that your health is at address $0512. You could replace the STY $0100 with STY $0512. The only problem is that you don't know what is in Y, only that it comes from address $15. You can change the LDY Z into a LDY #n, and then you will know that Y contains $15. But then, you not only keep address $0100 from recieving the right value (you're telling the game to put the number in $0512 instead by changing that line), you now give address $0101 a different value as well. This is why the graphics screw up (or at least, screwed up both times I tried it). The stuff happening at this point in the game is related to redrawing the screen.
Oh, and be careful with that STA $2007 up there. That particular address is directly related to the image on the screen. Hands-off are $4016 and $4017, which can freeze up the joystick. You may only have $2006, $2007, $4016, and $4017 available to work with. In that case, you'll have to settle for the $2006 or $2007.
Anyway, go ahead and try some codes. At the bare minimum, you'll need C009?00:12 and C00A?01:05 (or, if you'd rather change the second STY, C00C?01:12 and C00D?01:05). If you don't trust the number in address $15 to stay nice, also enter C006?A4:A0 to change the LDY Z into LDY #n. Finally, if you have two Genies and 21 health isn't enough in your game (say we need 100), add C007?15:64 to the list.
Play the game and lose some health. Hmm, your health didn't automatically refill? Both times I've done this, I had to press Select or Start before the code kicked in. Each time you press the button, your health refills. It's not infinite health, but you should stay alive if you're vigilant.
If you can't find anything in the area worth changing, you might be able to find a different area. Whack Alt-T to pause the game and go into trace mode, then go up to CPU/Debug/VInt in the menus. After that, press Alt-T again. Depending on the game, you may find yourself tracing a different area than before. Check out this new area the same way you analyzed the first, and see if you have better luck with it. Just follow the same instructions to make your code.
(If anybody tries this method, let me know how it works for you! I should probably do a few more games this way and revise this section accordingly.)
Phew! That should be about it for the lesson. Read the example scenario, then try it out for yourself.