Persistent NES-ROM hacking for profit and fun (Stage 2)

Amrit Sharma Poudel
5 min readMay 30, 2023

--

Stage 2: The Basics / Search

Now the necessary software is ready, let’s have a first look at the nes file. Load HxD editor and open contra.nes. It may seem cryptic but don’t worry, it is the language 6502 understands.

4E 45 53 1A 08 00 21 00 00 00 00 00 00 00 00 00 00 07 80 68 80 00 81 A9 80 9D 98 05 A9 22 9D 88 05 A9 05 9D 58 03 A5 40 F0 16 BD 24 03 9D B8 05 20 9D ED A9 80 9D E8 05 A9 FD 9D 58 05 4C 8E E7 A0 00 A5 41 F0 0B A0 04 BD 3E 03 C9 80 90 02 A0 08 B9 5C 80 9D F8 04 B9 5D 80 9D E8 04 B9 5E 80 9D 18 05 B9 5F 80 9D 08 05 4C 8E E7 00 FD 80 00 00 FD 40 00 00 FD C0 FF 20 1C 81 A5 40 F0 21 BD E8 05 18 69 12 9D E8 05 BD 58 05 69 00 9D 58 05 20 66 ED BD D8 05 30 07 A9 A4 9D 24 03 D0 CA 60 ….

With everything set up. Open FCEUX and load Contra.nes. You can just start playing, it is an emulator too. Now have a look at Tools -> RAM Search. It may look confusing at first, but believe me, it is simple. We start our lives with 3 Lives, which means there is a value “2” Stored somewhere in RAM (because it goes like 2 then 1 then 0) when the game starts.

RAM Search

Now search for the “Specific Value” on the search window. Searching RAM is really about hits and trials, and a good place to sharpen your skills. I already did the hard work of searching for the Address of Player 1’s life. It is 0032 in the RAM. So you select “Specific Adress” enter “32” and click on search.

I have highlighted the fields. You can see the value 2 is stored in that address. Next, we need to find out when this value is modified during the game.

RAM Search

So now we know that the “value of Life” is stored in “0032” (wow! what a missed chance to store it in 0042!). We now need to set some breakpoints for this memory address. It means that whenever the CPU (in this case the Emulator) modifies the value, the program pauses and shows the code currently being executed (awesome right?). Now open the Debugger (Debug -> Debugger).

Debugger Window

There is a lot of information in this window. We are only interested in the breakpoint part. Now add a new breakpoint. Since it is a CPU Memory, select CPU Memory and should be triggered when the value is being modified (written) and no other conditions are required. With this setup, reset the game.

Adding a breakpoint

The game will break 2 or three times before the game comes to the player select window. Just click on the “RUN” button on the debugger. Whenever the game breaks, just press STEP INTO and verify the code being executed. We are in this stage interested where the value “2” is written in the memory.

Continue stepping into till the program executes to line C469. At this line, something interesting happens.

07:C45F:85 39 STA $0039 = #$01
07:C461:A9 02 LDA #$02
07:C463:A4 24 LDY $0024 = #$00
07:C465:F0 02 BEQ $C469
07:C467:A9 1D LDA #$1D
07:C469:95 32 STA $32,X @ $0032 = #$00
07:C46B:CA DEX

In line C469, the value stored in the Accumulator is written in the address 32. From line C461 we know that a Constant value #$02 which equals 02 in Hex is stored in the accumulator. There is a conditional statement going on line C465. The condition is, load the value of address 0024 in the Y register, if the value is not set (BEQ) then go to C469 else continue executing through C467. In line C467, the value #$1D is loaded into the accumulator and the program continues to C469, where the value #$1D of our accumulator is stored in address 32. And what is the value 1D in decimal? 30! Bingo! Then the game loads with 30 Lives. This is in short the Konami Code activation. The human-readable code of this part of the program would be somewhat like this (not a real code though):


lives = 2;
konami_flag = load_from_memory ($0024);
if (konami_flag == true ) {
lives = 30;
}
write_in_memory($0032, lives);

Now what we need to do is modify the code in such a way that the Konami flag or the value in the address $0024 is always set. That is a lot of work, and maybe this address is used for storing other values at some point in the game? Who knows? Who cares? We are lazy and creative at the same time :P. Let’s analyze the code one more time:

07:C463:A4 24 LDY $0024 = #$00
07:C465:F0 02 BEQ $C469
07:C467:A9 1D LDA #$1D
07:C469:95 32 STA $32,X @ $0032 = #$00

What will happen if we simply remove line C465 of the code?

07:C463:A4 24 LDY $0024 = #$00
---07:C465:F0 02 BEQ $C469---
07:C467:A9 1D LDA #$1D
07:C469:95 32 STA $32,X @ $0032 = #$00

The code will continue to line C467 because the code in line C465 is empty or has no Opcodes and the CPU will go through this line, as there is no more BEQ statement. Makes sense? Yes! That will be our final code to always start with 30 lives. But what happens if we start the game with Konami Code set? Nothing! That’s for sure because even if a flag 01 is loaded in $0024 there is no statement to jump! How cool is that?

The other ways of modifying the code would be, for example, load constant value 01 in line C463, which will always result in BEQ running the next line. Let’s stick to the deleting part. It is fun!

--

--