IPS
From ROM Hack City
IPS is a format for a binary patch. IPS is a crude patch format to overwrite some bytes in a file with replacement bytes. The name is allegedly International Patching System, to refer to patches that contain translated messages. IPS continues to be the most popular patch format for ROM hacks, but IPS limits the patched file to 16 megabytes, which is already too small for some ROM hackers.
UPS is an alternative to IPS that supports larger files and bidirection patching. PPF is another alternative to IPS.
Contents |
[edit] IPS implementations
We forgot who invented the IPS format or created the first IPS implementation. Sonic Retro tells us, "The creation of IPS is unknown; but the file format it had was considered to be malformed."
The archive of Zophar's Domain contains "the classic IPS.EXE", an old DOS program from 1993, but not the first implementation. The program doc refers to IPS as the "International Patching System" and credits the IPS format to "Someone (not me)". The doc also reveals that by 1993, many IPS implementations already existed. "There are several .IPS converters available for multiple computers, and some work... Some CLAIM to work... And some just suck rocks..."
Most implementations only apply IPS patches. Only a few implementations can generate IPS patches by comparing two files.
- For users of Windows, the most common IPS program is Lunar IPS.
- Some Mac users have UIPS. (Mac users without StuffIt Expander can fetch UIPS in a zip.)
- Unix/Linux users can have the command-line version of UIPS.
- All these three programs can apply or generate a patch, but none of these three programs are free enough to let you take their IPS code for your own hacks.
There are also exist some script hacks to apply a patch, like ips.pl for Perl users and AppleScript-IPS for Mac. Zophar's Domain has a list of more IPS patchers.
[edit] IPS format
This is a complete reference to the IPS format. The format may seem simple, but has some caveats.
A complete IPS file contains the following:
- First five bytes: "PATCH" in ASCII.
- Zero or more patch records.
- Last three bytes: "EOF" in ASCII.
- (An optional extension places three more bytes after the "EOF".)
Each patch record is an instruction to write some data at an offset into the base file. This data overwrites part of the base file or extends the size of the base file. The IPS patcher must measure the offset in bytes, such that the first byte of the base file is at offset 0. (This is how most programming languages work; but a few languages like AppleScript number the bytes from 1, so programs like AppleScript-IPS must add 1 to every offset.)
[edit] Normal patch record
A normal patch record contains an offset into the base file and some data.
- 3 bytes: A big-endian integer (not 0x454f46) to give an offset into the base file.
- 2 bytes: A big-endian integer (not zero) to give the SIZE of the next data.
- SIZE bytes: The data to copy to the given offset.
To apply a normal patch record, the IPS patcher must seek to the given offset and copy the data into the base file.
[edit] RLE patch record
An RLE patch record uses run-length encoding to represent some repeated bytes.
- 3 bytes: A big-endian integer (not 0x454f46) to give an offset into the base file.
- 2 bytes: Zero.
- 2 bytes: The number of times to repeat a byte in the data.
- 1 byte: The repeated byte.
To apply an RLE patch record, the IPS patcher must seek to the given offset, then write the repeated byte for the given number of times.
[edit] Caveats
The number 0x454f46 looks like "EOF" in ASCII, which is why a patch record must never begin at offset 0x454f46. If your program generates a patch record at offset 0x454f46, then you have a bug, because IPS patchers will read the "EOF". One possible workaround is to start at offset 0x454f45 and include the extra byte in the patch.
If a patch provides multiple values for the same byte in the patched file, then the IPS patcher may use any of these overlapped values. Also, if the patch extends the size of the patched file, but does not provide values for all bytes in the extended area, then the IPS patcher may fill the gaps with any values. A better IPS file provides no such overlapped values and no such gaps, though this is not a requirement of the IPS format.
To exceed the maximum size of 0xffff for data from a patch record, you can split your data into multiple patch records; but there is no way to exceed the maximum offset of 0xffffff, which would point to the last byte in a file of 16 megabytes. The only way to exceed the maximum offset is to use a patch format different from IPS.
[edit] Extensions to the IPS format
Some hackers have added optional extensions to the IPS format, but some IPS programs do not understand these extensions.
[edit] RLE extension
Some documents refer to RLE patch records as an extension of IPS. The RLE patch records are now so common that every IPS patcher must understand them.
This availability does not imply that you want RLE in your patch. The purpose of RLE is to compress your patch, but RLE is so poor at compression that you can gain more compression with something like zip; but something like zip removes the reason for RLE.
[edit] Truncation extension
Lunar IPS implements the truncation extension, and might be the first implementation, but we are not sure. Snes9x also implements this extension.
At the end of the patch after the "EOF", the truncation extension appends a big-endian integer of three bytes, to give the length of the patched file. An IPS patcher that implements this extension must truncate the patched file to the given length. The extension does not specify whether this can extend a file.
This extension allows the patched file to be shorter than the base file, so that IPS can transform any binary file to any other binary file (fitting within the limit of 16 MB). ROM hackers almost never shrink their ROM images, so this extension almost never appears in IPS patches. If an IPS patcher does not support truncation, then its users might never notice.
To be compatible with this extension, an IPS patcher must not raise an error if it finds three bytes after the "EOF". An IPS patcher might or might not raise an error if it finds one, two, or at least four bytes after the "EOF".
[edit] sneslink extension
snescom has a feature to translate an assembly patch to an IPS patch.
If the assembly patch uses an undefined symbol, or if it exports a global symbol, then snescom uses an extension of the IPS format to tell sneslink how to resolve the symbols. The extension changes the meaning of patch records that start at offset $000001 or offset $000002.
[edit] References
- The classic IPS.EXE
- Source code of ips.pl
- ZeroSoft: IPS Patch Format
- Sonic Retro: IPS
- ReadIPSPatch in memmap.cpp of snes9x-gtk
- IPS output support of snescom
