Classroom Public page

Lab 4.2: Modify In-Game Text

930 words

~90 minutes. Find a string in the ROM; change it; verify the new text appears in Mesen.


Goal: locate one specific text string (title, menu item, dialog) in your ROM; replace it with text of the same length; verify it appears correctly.

Estimated time: 90 minutes

Prerequisites: lab 4.1 complete (palette-swap mechanic understood)

Steps

Step 1: Pick a string to change (10 minutes)

Run your ROM in Mesen. Find a short text string you can clearly see: a title-screen word; a menu option; the score-display label; a level-name caption.

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

Important constraint: your replacement string must be EXACTLY THE SAME LENGTH as the original (in characters). If the original is "START," your replacement could be "BEGIN" or "PRESS" or "XXXXX," all 5 letters. Longer or shorter replacements can corrupt nearby data in the ROM; week-4 is not yet teaching how to handle length-changing edits cleanly.

Step 2: Decide on the encoding (10 minutes)

Different games encode text differently. The two most common conventions:

Standard ASCII: text bytes are direct ASCII values. 'A' = 0x41; 'B' = 0x42; etc. Many homebrew games use this. Try this first.

Custom encoding (tile-index encoding): text characters are mapped to tile indices in CHR-ROM. 'A' might map to tile 0x80, 'B' to tile 0x81, etc. Many commercial games used this; some homebrew does too. Harder to find.

Start by assuming ASCII; fall back to tile-index if ASCII doesn't pan out.

Step 3: Search for the string in your hex editor (15 minutes)

Open your ROM (the COPY in working/) in your hex editor. Most hex editors have a "search ASCII" or "find string" feature.

Search for your target string. For "START," you would search for the ASCII byte sequence 53 54 41 52 54 (or just type "START" if your editor supports ASCII search).

If you find exactly one match, you're done with the search. If you find multiple, test each by modifying one at a time and reloading in Mesen.

If you find ZERO matches, the game probably uses tile-index encoding. Switch to step 3b below.

Step 3b (if ASCII search failed): Use the PPU Viewer to find the tile mapping

Open Mesen's PPU Viewer → Pattern Tables. Look at the tiles. Identify the tile for each letter in your target string (e.g., find the 'S' tile, the 'T' tile, the 'A' tile).

Note the tile index for each letter. For example, S = 0x83, T = 0x84, A = 0x65.

Now in your hex editor, search for the byte sequence 83 84 65 84 86 (or whatever the indices are for your specific game). This is the tile-index version of "START."

Write down the encoding mapping you discovered. You will need this for step 4.

Step 4: Modify the bytes (15 minutes)

In your hex editor at the offset you found:

For ASCII text: just overwrite the existing characters with your new ones. Make sure you stay within the original length.

For tile-index text: convert your new string to tile indices using the mapping you derived. If 'A' = 0x65 and 'B' = 0x66 and you want "BEGIN" (B-E-G-I-N), you need to find each letter's tile index and write those bytes.

Save the file.

Step 5: Verify in Mesen (15 minutes)

Reload your hacked ROM in Mesen. Navigate to the screen where your text was. Did it change?

  • Yes, and it looks correct: take screenshots, journal, you're done
  • Yes, but it looks garbled: you mapped letters to the wrong tile indices. Re-check your encoding work in step 3b
  • No change: you modified a string that has the same characters but is NOT the one you intended. There were probably multiple matches; you got the wrong one. Try the other matches

Step 6: Take before/after screenshots (10 minutes)

Save:

  • ~/spk-101/working/lab-4-2-before.png (the original, unmodified ROM showing the original text)
  • ~/spk-101/working/lab-4-2-after.png (your hack showing the changed text)

Step 7: Journal (15 minutes)

In ~/spk-101/journal/lab-4-2-notes.md:

  • What text did you change? From what to what?
  • ASCII or tile-index encoding?
  • If tile-index, what mapping did you derive?
  • Where (file offset) was the string?
  • What went wrong on the first attempt (if anything)?
  • A reflection: NES games use one byte per character (8 bits). Modern text uses UTF-8 (variable width, 1-4 bytes per character). Why might a 1989 game be okay with limited-character encodings?

Expected output

  • A modified ROM with one text string changed
  • Before/after screenshots showing the change
  • A journal entry that includes the encoding scheme you used

Common pitfalls

  • Replacement string is longer or shorter: this can shift later bytes, corrupting the rest of the game's data. Stay exactly the same length. If the original is 5 characters, your replacement is 5 characters; pad with spaces if needed
  • Looking for "START" in lowercase: most NES games use uppercase letters only. ASCII 'S' (0x53), not 's' (0x73)
  • Multiple matches and modifying the wrong one: NES games often have the same word in multiple places. Test each match systematically
  • Tile-index decoding takes patience: identifying tile indices for each letter via the PPU viewer is slow. Some homebrew has the letters in a clean A-Z block; some scatters them. Take notes as you go

Stretch (optional)

  • Find ALL occurrences of one word in your ROM (e.g., every place "PLAYER" appears). Modify them consistently
  • Look for the credit-screen text. Try replacing one developer's name with your own
  • If your ROM uses a custom encoding, create a full A-Z mapping table and save it in your journal. You will reuse this if you do more hacks on the same ROM

Lab 4.2 v0.1. Second hack. The "I can leave my fingerprint on this game" moment.