Classroom Public page

Lab 4.4: Change a Gameplay Value (Lives, Score-Per-Pickup, Starting Position)

989 words

~90 minutes. Identify a single byte in PRG-ROM that controls a numeric gameplay value; change it; verify the gameplay difference.


Goal: hunt for a constant in PRG-ROM (a "magic number" the game uses for some specific behavior), modify it, and observe the gameplay change in Mesen.

Estimated time: 90 minutes

Prerequisites: labs 4.1, 4.2, 4.3 complete (you have done easier hacks; this one requires more detective work)

Steps

Step 1: Pick a numeric value to change (15 minutes)

Run your ROM in Mesen. Identify a number you might be able to change. Candidates:

  • The starting life count (often shown as 3 at game start)
  • The score added per pickup (often a value like 100, 200, 1000)
  • The starting position of the player (an X or Y coordinate)
  • The number of enemies on a screen
  • A timer value (how long an effect lasts)

Pick something the game prominently uses. If you cannot tell what the values are, the easiest pick is "starting lives", most games show a number like 3 at start. (Note: many homebrew games may not have a lives system; pick another value if so.)

Write down: "I want to change ___ from ___ to ___."

Step 2: Use Mesen's RAM watch to find where the value lives in RAM (20 minutes)

Open Tools → Memory Viewer. Watch the running game's RAM.

Strategy: identify the RAM byte that stores your target value.

  • Pause the game
  • Note your target value (say, lives = 3)
  • Scan the visible RAM for a byte that equals 3 (most likely in the $0000-$07FF range, where game-state lives)
  • There will be many bytes equal to 3. Narrow down by changing the game state: lose a life, then check which byte changed from 3 to 2. (Or pick up a coin, see which byte's score-display value changed)
  • That byte is your target, it is the RAM location holding the live game-state value

Some emulators (including Mesen) have a "memory search" / "cheat search" feature that automates this hunt. If yours does, use it.

Write down: "The live value lives at RAM address 0x____."

Step 3: Use a breakpoint to find where the constant is written (15 minutes)

Now you know the RAM address where the value lives during play. But you want to change the PRG-ROM byte that INITIALIZES this value at startup or scene-load.

Use Mesen's debugger. Set a "write breakpoint" on the RAM address from step 2. Reset the game (restart from power-on or scene start). The breakpoint should fire when the game writes the initial value to that RAM address.

When the breakpoint fires, you see the instruction that wrote the value. The instruction will look something like LDA #$03 / STA $0070, load immediate value 3, store at $0070. The #$03 is the constant; this is what you want to change.

Note the PRG-ROM byte address of the immediate value. Mesen's debugger should show both the runtime address and the underlying PRG-ROM byte. Write down: "The constant byte is at PRG-ROM offset 0x____."

(If you cannot get a breakpoint to work, alternative strategy: search PRG-ROM for the byte sequence A9 03, that is the 6502 instruction LDA #$03. The byte right after A9 is your constant. There may be many matches; test each.)

Step 4: Change the byte (5 minutes)

Open your ROM copy in your hex editor. Navigate to the offset you found. Change the immediate value.

For "starting lives 3 → 9," change 03 to 09. For "score per pickup 100 → 1000": this is more complex because 1000 doesn't fit in one byte; skip this case for week 4. For "starting X position 64 → 200," change 40 to C8. (Hex: 64 = 0x40; 200 = 0xC8.)

Save the file.

Step 5: Verify in Mesen (15 minutes)

Reload the hacked ROM. Start a new game (or wherever the initial value is set). Confirm the new value shows up.

If it does not work, the most common cause is that you changed the wrong LDA #$xx instance; there may be others elsewhere in PRG-ROM. Try a different occurrence.

Step 6: Take screenshots and journal (20 minutes)

Save before/after screenshots. Write in ~/spk-101/journal/lab-4-4-notes.md:

  • What value did you change? From what to what?
  • How did you find the RAM byte holding the live value?
  • How did you trace from the RAM byte back to the PRG-ROM constant?
  • What was the actual gameplay effect of the change?
  • A reflection: what does it feel like to change a number and watch the game obey? Does this change your sense of what games are?

Expected output

  • A working ROM hack with one gameplay value changed
  • A documented chain: live RAM address → write breakpoint → PRG-ROM offset → modified byte
  • Before/after screenshots
  • A journal entry

Common pitfalls

  • Hunting for the wrong value: if the game internally uses values that are different from what's displayed (e.g., score is divided by 10 before display), the byte you find may be different from what you expected
  • Multi-byte values: lives is usually 1 byte; score is usually 2-3 bytes. Multi-byte hacking is beyond week 4. Stick to 1-byte values for now
  • Breakpoint that does not fire: reset (full power cycle) rather than just reload. Some games initialize values only once at power-on, not at scene change
  • The value is computed, not stored as a constant: some games compute values like "starting lives = base + difficulty modifier." If you cannot find a single constant, the value may be derived from multiple sources. Pick a different target

Stretch (optional)

  • Try changing a 2-byte value (e.g., score-per-pickup) by modifying two consecutive immediate-load instructions. The 6502 typically loads each byte separately with LDA #$nn followed by STA $addr and LDA #$nn followed by STA $addr+1
  • Change one timer value (e.g., how long an item stays on screen). Note the difference in feel
  • Look for "physics" constants, gravity strength, jump height, walking speed. These are often single bytes too, and changing them can dramatically alter the game's feel

Lab 4.4 v0.1. The "make the game easier or harder" lab. Heart of week-4 ROM hacking.