The practical heart of the course. You make four real changes to a real ROM: palette swap, text swap, sprite swap, level-byte tweak. By the end of the week you have a modified ROM that runs in Mesen with your changes visible.
Theme
ROM hacking is the discipline of modifying a game's ROM file to change what the game does. It is older than emulation; people modified ROMs by burning new EPROMs in the 1980s. Modern ROM hacking happens entirely in software: open the ROM in a hex editor, change some bytes, run the modified ROM in an emulator, see the change.
This week you make four ROM hacks. Each is small, concrete, and produces a visible change in the emulator. By the end of the week you have:
- Changed the color of something (palette swap)
- Changed text the game displays (text swap)
- Changed what a sprite looks like (sprite swap)
- Changed a numeric value in the game (level-byte tweak)
These four hacks are the "Hello World" of ROM hacking. They teach you the loop: find the byte; change the byte; verify the change. That loop is the same loop every ROM hacker uses, from the simplest palette swap to the most ambitious total-conversion mod that changes everything about a game.
Week 4 has four labs (one per hack) instead of the usual two. The schedule absorbs the extra lab time by reducing this week's independent practice. Total weekly time stays at ~10 hours.
Visual Helpers
Two cognitive tools are especially useful this week:
Offset calculations: Every lab this week requires you to calculate a byte offset -- where in the file does tile N start, or where does the palette begin. If you are landing at the wrong byte, re-derive the offset formula on paper before editing. The supplement at curriculum-supplements/spk-101-younger-learner-tools.md has a fully-worked offset example using the same formula this week's labs use.
Bitplane Decomposer (Lab 4.3): Lab 4.3 asks you to modify sprite bytes and predict the result. Before changing any bytes, decode the original tile on graph paper using the step-by-step column method from the Bitplane Decomposer section of the supplement. This tells you exactly which bit in which byte controls which pixel. Changing a byte without first understanding the bit layout leads to unexpected results that are hard to debug.
Reading list (~45 minutes)
- NESdev wiki: "PPU palettes" at
wiki.nesdev.org/w/index.php/PPU_palettes, the NES palette system. You will modify palette bytes in Lab 4.1, so understand the structure first. - NESdev wiki: "PPU pattern tables" at
wiki.nesdev.org/w/index.php/PPU_pattern_tables, re-read from week 2; this week you will modify pattern table bytes in Lab 4.3. - "ROM hacking dot net" introduction at
www.romhacking.net/start/, the canonical ROM-hacking community's "how to start" page. Read for cultural context; the community goes back decades.
Lecture outline (~1.5 hours)
Section 1: The ROM hacking loop
- Identify the byte (or bytes) you want to change. This is the hardest part. It requires reading the ROM with whatever tools help: hex editor, debugger, dedicated graphics viewer, dedicated music viewer
- Make a copy of the ROM. Always. The original stays untouched
- Change the byte(s) in your copy. Use a hex editor
- Run the modified ROM in the emulator. Verify the change is visible
- Iterate. If the change did not produce the expected effect, undo it; try a different byte
Section 2: Finding bytes, by category
- Palette bytes: easy to find. Modern emulators (Mesen included) have a built-in palette viewer that lets you inspect the colors the game is currently displaying. Working backward from the palette view to the bytes in the ROM is straightforward
- Text bytes: usually stored as ASCII or a tiny custom encoding (sometimes called a "table" in ROM hacking). Searching the hex editor's ASCII view for the text you see in the game usually finds the bytes
- Sprite bytes: stored in CHR-ROM. A graphics viewer tool like YY-CHR (Windows) or the Mesen built-in PPU viewer shows you all 512 tiles at once; you find the tile you want to change, note its offset in CHR-ROM, edit the bytes
- Numeric game-state bytes: harder. These are typically initial values in PRG-ROM or constants embedded in code. Finding them often requires Mesen's debugger and a "memory search" feature: change the value in the game, see what RAM byte changed, trace it back to the PRG-ROM constant that loaded it
Section 3: Common pitfalls
- The ROM has a checksum. Some ROMs verify their own integrity at boot; if you change a byte, the checksum fails and the ROM refuses to run. Homebrew ROMs and most NES commercial ROMs do NOT have this; but you should know it exists
- The byte you changed is also referenced elsewhere. Common in tile data: the same sprite tile might be used for multiple game characters, so changing it changes more than you expected
- The change happens, but you cannot tell. The byte you changed is for a feature that is not visible until a specific game state. Patience and "save state at the right moment" help
Section 4: ROM hacking community norms
- Always distribute as a patch, not as a modified ROM. A "patch" file contains only the differences between the original and the modified versions. Distributing the modified ROM itself amounts to distributing a copy of the original (illegal for commercial ROMs); distributing just the patch is legal because the recipient supplies their own ROM
- Common patch formats: IPS (oldest, simplest); BPS (modern, more reliable); UPS (rare). Free tools: Floating IPS (
Flips) creates and applies patches - Credit your work: when you publish a hack, credit the original game's authors and any tools or tutorials you used. The ROM-hacking community has decades of norms here
Section 5: Legal scope of this week's work
- This week's labs use ONLY homebrew ROMs released under permissive licenses, OR ROMs the student personally dumped from their own cartridges
- The capstone in week 6 follows the same rule
- We do NOT use ROMs of commercial games we do not own; even if "everyone has those ROMs," using them in academy work would put students in legal gray territory and the academy refuses to do that
Labs (~5 hours total, week 4 has 4 labs)
Lab 4.1: Palette swap (labs/lab-4-1-palette-swap.md)
- Goal: Change the colors of your homebrew ROM. Pick one sprite or background palette; change one or more of its color bytes; verify the change in Mesen
- Time: ~75 minutes
- Artifact: before/after screenshots; a note in your lab journal explaining which palette you changed and what colors
Lab 4.2: Text swap (labs/lab-4-2-text-swap.md)
- Goal: Change a piece of text the game displays (typically a title-screen string or a menu option). Find it in the hex editor's ASCII view; change the characters; verify in the emulator
- Time: ~75 minutes
- Artifact: before/after screenshots; the byte offset where the text lived
Lab 4.3: Sprite swap (labs/lab-4-3-sprite-swap.md)
- Goal: Change what a sprite tile looks like. Open the CHR-ROM portion of the file; locate a recognizable tile; edit its 16 bytes; verify the change in Mesen's PPU viewer and in the running game
- Time: ~90 minutes
- Artifact: before/after screenshots of the tile in Mesen's PPU viewer; the byte offset of the tile
Tier-1 companion: Bitplane Decomposer Workout (worksheets/spk-101/lab-bitplane-decomposer.md)
- Drive the Bitplane Decomposer through mario-M, diamond, and a custom 4-color tile you author
- Hand-decode row 0 of mario-M before stepping the visualizer; predict-then-verify per cell with
Color = (PlaneB << 1) | PlaneAMSB-first per Jon's 2026-05-11 resolved-formula - ~60 minutes; recommended primer before Lab 4.3 sprite swap (the same 16-byte edit loop, with the visualizer's tooltip math doing the heavy lift)
Lab 4.4: Level-byte tweak (labs/lab-4-4-level-byte-tweak.md)
- Goal: Change a numeric game-state value (a starting life count, a starting score, the number of enemies in a level, the player's starting position). Use Mesen's debugger to identify the byte; find it in PRG-ROM; modify
- Time: ~90 minutes
- Artifact: before/after screenshots showing the changed value; a note in your lab journal explaining how you found the byte
Independent practice (~1.5 hours)
This week the independent practice is light because lab time is heavy. Pick one:
- Combine your four hacks. Apply all four changes (palette + text + sprite + level byte) to one ROM. Create an IPS patch with
Flips. Test that applying the patch to a fresh copy of the original ROM produces your modified version - Hack a different homebrew ROM. Pick a homebrew ROM you have not touched this week. Apply just one of the four hacks to it. The skill transfers; you will find the byte faster the second time
Reflection prompts (~30 minutes)
- Which of the four labs was easiest for you? Which was hardest? What made the hard one hard?
- The lecture said "always make a copy of the ROM." This week, were you tempted to skip that step at any point? Why or why not?
- When you found the byte for one of the hacks, how confident were you that it was the right byte before you tried changing it? How did you build that confidence?
- The ROM-hacking community distributes patches, not modified ROMs. What is the reasoning, and do you agree with it?
- Looking back at weeks 1-4: you can now run a ROM, read its bytes, read its code, and modify it. What do you think week 5 should cover?
What comes next
Week 5 takes the skills you just developed and applies them to different platforms: Game Boy (using SameBoy) and SNES (using bsnes-plus). The hex-editor skills transfer directly; the 6502 assembly does NOT (the Game Boy uses a Z80-like CPU; the SNES uses a 65816, which is a 6502 successor). The week is about seeing that the IDEAS transfer even when the specifics do not. By the end of week 5 you can boot a Game Boy ROM, find its header, and make a simple modification using the same loop you used this week.