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
The four scenes below let you practice the wk-4 lab loop in your browser before you open Mesen and a hex editor on your own machine. The loop is the same one Section 1 names: find the byte, change the byte, verify the change. The same Lan Master ROM you ran in week 1 is loaded here, and the same tile and palette bytes the labs ask you to modify are wired into the in-browser editors. Browser tools and hex editor modify exactly the same bytes at exactly the same offsets; one is a teaching shortcut, the other is the practitioner workflow.
Scene A: Offset calculator. Three-step walkthrough of the chr_start + tile_idx * 16 + row formula every wk-4 lab uses to land at the right byte. Worked example pulled from the live ROM, so the numbers in the formula are the same numbers you will type into your hex editor in lab.
Scene B: Palette swap. Click a swatch in the in-browser palette renderer; the tilemap below recolors instantly. Mirrors Lab 4.1. The file offset of the changed byte is visible the whole time, so the connection between "I picked blue" and "byte at offset 0xNNNN changed from 0x16 to 0x21" stays concrete.
Scene C: Sprite swap. Edit a CHR tile bit by bit in an 8x8 grid; the tilemap below redraws as you flip bits between Plane A and Plane B. Mirrors Lab 4.3. The 16-byte before-and-after diff is shown alongside the edit so you can preview an edit in your head, click to apply it, and check whether your prediction matched.
Scene D: From browser to hex editor. Compact side-by-side view of the palette editor, the sprite editor, and a hex viewer scrolled to the modification offsets with the modified bytes highlighted. Three tool surfaces, same bytes. This scene is the bridge from the browser-tool shortcut to the hex-editor workflow you use in lab.
Two cognitive tools that supplement the scenes
The scenes above are interactive, but they do not replace the underlying mental model. Two cognitive tools in the cognitive tools supplement cover the same ground at deeper depth and on paper, which is useful when an in-browser edit goes sideways and you need to slow down.
Offset calculations. Scene A drives the formula in the browser. The supplement has a fully-worked offset example using the same formula, plus a longer derivation that helps when an offset comes out wrong and you need to track down which term is off. If your lab edit is landing at the wrong byte, re-derive the offset formula on paper before editing again.
Bitplane Decomposer (Lab 4.3). Scene C lets you flip bits and see the result. The supplement has the step-by-step column method on paper, which is faster when you want to predict the result of an edit before you click. Before changing any bytes in Lab 4.3, decode the original tile on paper using the column method; 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
- Scene B in the Visual Helpers section above walks through this palette swap in the browser; do it there first so you know which byte you are looking for, then redo it in Mesen + a hex editor for the artifact
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
- Scene C in the Visual Helpers section above lets you flip the same kind of tile bit by bit in the browser before you touch the 16 bytes in your hex editor; use it to predict the result of an edit, apply the edit, and see whether your prediction matched
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)
- Self-check quiz: NES bitplane tile decoding, 6 questions, ~15 minutes; predict-then-verify with the embedded decomposer.
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.
All technical terms used here are in the glossary.