Skip to content

ROM Patching

Patches contain a set of changes that can be applied to a file, turning that file into something different. Common examples for patching ROMs are: translating text to a different language but keeping game logic the same, and fan-made creations such as new levels for an existing game.

Games and their ROMs are protected under copyrights, so patches are used to not share copyrighted code online. A person needs the original ROM file plus a patch file to get the resulting patched ROM that will be played with an emulator.

Specifying patch files

Patch files can be specified with the --patch <path|glob> option. See the file scanning docs for more information.

Supported commands

Patching can be used with any combination of the copy or move commands, with or without the extract or zip commands. Patching can't be used with the link command.

Patches need to read the ROM's contents, so there are some limitations when ROMs are archived and those archives would be copied or moved as-is:

Commands Patched un-archived ROMs Patched archived ROMs
copy or move ✅ ❌ input archives will not be modified in any way
copy extract or move extract ✅ ✅
copy zip or move zip ✅ ⚠️ only ROMs that aren't excluded from zipping

Patch types

There are many, many patch types that ROM hackers use to distribute their changes on the internet (xkcd "Standards"). Typically, a patch will only be distributed in one format, so gamers are entirely at the mercy of the ROM hacker's choice.

Not all patch types are created equal. Here are some tables of some existing formats, whether Igir supports them, and what the patch supports.

Common patch types:

Type Supported CRC32 in patch contents Notes
.bps ✅ ✅
.ips ✅ IPS, IPS32 ❌
.ppf ✅ v2, v3 ❌
.ups ✅ ✅ The author, byuu, created .ups to replace .ips, but then created .bps as a replacement for .ups.
.vcdiff, .xdelta ⚠️ (LZMA secondary compression only) ❌

Uncommon patch types:

Type Supported CRC32 in patch contents Notes
.aps (GBA) ✅ ❌
.aps (N64) ✅ simple & N64 ❌
.bdf, .bsdiff (BSDiff) ✅ v4 ❌
.bsp (Binary Script Patching) ❌ ❌ BSP will probably never be supported, the implementation is non-trivial.
.dldi (NDS libfat) ❌ ❌ No file specification exists.
.dps (Deufeufeu) ✅ ❌
.ebp (EarthBound) ✅ ❌ EBP is just IPS with some JSON after the EOF string.
.gdiff ❌ ❓
.mod (Paper Mario Star Rod) ✅ PMSR, Yay0-compressed PMSR ❌ The source file has to be Paper Mario (USA).z64 (CRC32 A7F5CD7E), so you don't need to put it in the patch filename.
.ffp, .pat (FireFlower) ❌ ❓ No file specification exists anymore.
.pds (Sephiroth87's NDS) ❌ ❓ No file specification exists.
.rup (NINJA 2.0) ⚠️ only single file patches, only raw/binary file type ❌ uses MD5
.rxl (ROM eXtension Library) ❌ ❌ RXL will probably never be supported, it is used to inject files at manually specified locations into ROMs.

If you have a choice in patch format, choose one that contains CRC32 checksums in the patch file contents (e.g. choose .bps over .ips if possible).

Note

Igir can read patch files inside any supported archive format (just like DATs and ROMs), but most patch types will have to be fully extracted to a temporary file before they can be applied.

ROM checksums

Igir needs to be able to know what source ROM each patch file applies to, and it does this using CRC32 checksums.

A few patch formats include the source ROM's CRC32 checksum in the patch's file contents. This is the most accurate and therefore the best way to get source ROM information. .bps is a great example of an efficient and simple patch format that includes this information.

Most patch formats do not include the source ROM's CRC32 checksum. .ips patches are some of the most likely you will come across. For those patches, you need to put the source ROM's CRC32 checksum in the patch's filename. Here are some examples:

Source ROM filename Patch filename
Super Mario Land (World).gb At the end: Super Mario Land DX v2.0 (World) 90776841.ips
NBA Jam - Tournament Edition (USA) (Track 1).bin At the beginning: A8F1ADF5 NBA Jam 22 v1.4.ppf
Mega Man - Dr. Wily's Revenge (USA).gb In square brackets: Mega Man - Dr. Wily's Revenge DX v1.02 (USA) [47e70e08].ips
Metroid II - Return of Samus (World).gb In parentheses: Metroid II - Return of Samus DX v2.0 (World) (DEE05370).ips
Pokemon Card GB 2 - GR Dan Sanjou! (Japan).gbc With an 0x prefix: Pokemon Card GB 2 - GR Dan Sanjou! (Japan) 0x6c933a14 [T+En1.0_Artemis251].gbc

Only writing patched ROMs

By default, Igir will write patched ROMs in addition to un-patched ROMs. This includes any ROMs that do not have any matching patches in a --patch <path|glob>.

If you want to only write patched ROMs to the output directory, you can use the option:

--patch-only

Creating ROM patches

Marc Robledo's Rom Patcher JS site is a great resource for creating ROM patches in a number of common formats without the need to download any tools.