RomPatcher.js: a multi-format ROM patcher that runs in a browser tab
An IPS/UPS/APS/BPS/RUP/PPF/xdelta ROM patcher made in HTML5.
At a glance
- What is it?
- RomPatcher.js is a Vanilla JavaScript ROM patcher that applies and creates patches in the IPS, UPS, APS, BPS, RUP, PPF, EBP, BSDiff, Star Rod, VCDiff and xdelta formats, works in a modern browser including on a phone and in Node.js, and can be embedded in a modding site so visitors patch a ROM without downloading anything. The repository is MIT licensed in its package metadata, and the site list is longer than the feature list.
- Who is it for?
- Adopt RomPatcher.js if you publish patches and want your visitors to apply them in the browser without installing anything, since the same code runs in a page, on a phone and in Node.js, and it both applies and creates patches across a wide format range.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A patcher that lives in a browser tab
RomPatcher.js is a ROM patcher made in Javascript, and the description is an IPS, UPS, APS, BPS, RUP, PPF, xdelta ROM patcher made in HTML5.
The delivery model is the point. The tool is made in Vanilla JS, and it can be run in any modern web browser, including mobile, and in Node.js. Nothing is compiled, there is no binary to distribute, and the same code path serves a visitor on a phone and a script in a terminal.
For the community it serves, that solves a specific problem. Modders publish patches, and the friction in getting one applied is often the download and the tool. A visitor who opens a page, drops their base ROM onto the page, and receives a patched file has not had to install anything, and on a phone, which is where a lot of the audience is, installing a patcher is often the step that ends the attempt.
The feature list shows the same instinct elsewhere. Files are unzipped automatically, headers can be removed before patching, and the tool shows the ROM CRC32, MD5 and SHA-1 before patching. That last one is not decoration. A patch applies to a specific base image, and if the base is wrong the result is a corrupted file that looks plausible, so showing the hashes first lets a user confirm they are holding the right ROM before anything is written.
The target user is therefore two-sided. For the person making patches, it is a cross-platform patch authoring tool. For the person running a fan site, it is a component to embed so that your community can apply your patch without leaving the page. The repository tree supports both readings: `index.html` and `index_template.html` for the browser side, `index.js` and the `rom-patcher-js/` directory for the code, `webapp/` and `_cache_service_worker.js` and `manifest.json` for the progressive web app, and `docker/` for serving it.
The format list is the real feature list
The supported formats are what a ROM hacking site actually cares about, and the list is long:
IPS, UPS, APS for N64 and GBA, BPS, RUP, PPF, EBP, BSDiff with the `.bdf` and `.bspatch` extensions, Paper Mario Star Rod with the `.mod` extension, and VCDiff with the `.xdelta` and `.vcdiff` extensions.
Each of those formats solves a different problem. IPS is the simplest, a sequence of offsets and byte replacements. BPS adds a delta against the base with checksums that let the patcher verify the base is correct. UPS is similar with a CRC. PPF applies patches at fixed offsets in the original file layout, which is what several GameCube and Game Boy Advance patches need. VCDiff and BSDiff are the general binary delta formats, and the Star Rod `.mod` format is a specific one for a specific game.
A patcher that handles one format is a small program. A patcher that handles all of these, in one implementation, in JavaScript, is a genuine piece of infrastructure, and it explains why the tool appears where it does.
The list of known sites that use RomPatcher.js is the evidence of that. The README names Romhacking.net, Smash Remix, Radical Red, Rocket Edition, SnapCameraPreservation, Pokemon Clover, the ZeldaHacking Wiki for The Legend of Zelda Oracle of Ages and Seasons, Pokemon Elite Redux, Earthbound Beginnings and 64DD.org. These are community sites that put a patcher in front of their visitors, which is a statement about trust and reach.
The patch authoring direction is equally supported, because a patch format is only useful if someone can make one. The tool can patch and create patches, and the creation path is the same code path as the application path, which means the tool's own round trip is its first test.
Embedding the patcher in a fan site
The embedding story is documented, which is the part that turns a library into an infrastructure component.
The README explains the intent: modders and hackers can embed Rom Patcher JS in their websites to provide an online ROM patcher for their patches, allowing users to patch ROMs without downloading any files. The `index_template.html` file includes a simple working example, and the wiki has a page on embedding Rom Patcher JS with more detailed instructions.
The design constraint that makes embedding possible is the Vanilla JS choice. There is no framework, no build step and no runtime dependency in the browser path, so a site can take the template, point it at its own patch files and have a working patcher. The npm dependencies, chalk and commander, are for the Node command line interface and are not part of what a browser page loads.
The website version also explains the progressive web app files. `manifest.json` and `_cache_service_worker.js` are the two pieces you need for a page that can be installed to a home screen and that keeps working offline, which is a sensible pairing with a patching tool, because a user on a hotel network with a bad connection can still open the patcher.
The patch authoring side is symmetric with this. A modder who wants to publish a patch needs to make it, and the CLI does that from the same repository, so the two halves are not separate tools that have to be kept in step.
The Node.js command line path
The command line interface is documented in three short steps in the README, and it is the same `index.js` that the browser page uses.
Installing the dependencies:
npm installPatching a ROM:
node index.js patch "my_rom.bin" "my_patch.ips"And creating a patch, which takes the original and the modified file:
node index.js create "original_rom.bin" modified_rom.binThe full option list is available from either subcommand:
node index.js patch --help
node index.js create --helpThe package metadata shows how the command is exposed. The package is named `rom-patcher`, the version is 3.0.0, the main entry is `index.js`, and there is a `bin` entry mapping `RomPatcher` to `./index.js`, so a global install gives you a `RomPatcher` command. The test script is `node test.js`, and the `test.js` file is in the repository root, so the project's own test entry point is a single file rather than a framework directory.
One detail in the package metadata is worth reading before you package this yourself. There is a comment explaining that they are not using `type: module` for now to ensure compatibility with old browsers and Node, and that the latest chalk version works only as an ES6 module, so the usage of the last CommonJS compatible version is forced. That is why chalk is pinned to exactly 4.1.2 while commander uses a caret range. The trade is explicit: broad environment compatibility in exchange for a dependency that is several major versions behind, and it applies to the CLI path rather than to the browser bundle.
Version drift, the licence file and where it does not fit
Two things to check before you depend on this.
The first is the licence. The `package.json` declares MIT, and the README links the LICENSE file, while the project metadata records the licence as other, a custom licence that GitHub cannot classify. The LICENSE file at the repository root is the one to read, and if you embed the tool in a website that serves patched ROMs, the terms matter more than usual, because you are distributing a tool that produces copyrighted game content to your visitors. That is a description of the files rather than legal advice, and it is worth a conversation with whoever handles that question in your organisation.
The second is version drift. The recent releases are v3.2.1 from 2025-11-04, v3.1 from 2024-11-02 and v2.9.1 from 2024-07-21, while the `package.json` still says version 3.0.0, and the last push to `master` was on 2026-08-28. The npm package version and the git tags do not match, so a dependency on the npm registry gives you a different artefact from the latest tag. If you need to know exactly what you are running, pin the git commit rather than the version range.
On fitness for purpose, there are three cases where this is the wrong tool.
The first is a large archive. This is a JavaScript patcher running in a browser tab, so the practical ceiling is the browser's memory and the time you are willing to make a user wait. Patching a multi-gigabyte archive is not what this is built for, and a native tool with a streaming implementation is the answer there.
The second is a workflow that needs a desktop application with a file browser and a preview. The browser tool is excellent at one thing, applying a patch to a file the user picks, and it is not a replacement for a general patch authoring environment.
The third is a case where the base ROM's identity is the problem rather than the patch format. The tool prints CRC32, MD5 and SHA-1 before patching, which is exactly the right check, but it cannot help when the base image itself is undumped, and a project whose output depends on a specific dump will need that dump supplied separately.
The alternative approach is a native patcher per format, one binary per format or one with format plugins, which is faster and can handle large files, at the cost of platform-specific binaries and the download step that the browser version removes. The difference in approach is a native tool you install versus a page you open, and for the communities listed in the README the second one clearly wins.
Editorial conclusion
Adopt RomPatcher.js if you publish patches and want your visitors to apply them in the browser without installing anything, since the same code runs in a page, on a phone and in Node.js, and it both applies and creates patches across a wide format range. Do not adopt it if you need a native binary with a graphical interface, if you need to patch multi-gigabyte archives, or if you need a project with a stable release cadence, since the newest tag is v3.2.1 from 2025-11-04 and the package version in the metadata still reads 3.0.0. Verify three things first: that the licence file matches the MIT declaration in `package.json`, since the project metadata records it as a custom licence GitHub cannot classify, that the checksums the tool prints before patching are the ones your patch expects, since a mismatched base ROM produces a silently wrong result, and that the browser or Node version you target supports the APIs the tool uses, because the package deliberately sticks to CommonJS for old environment compatibility.
Frequently asked questions
Which patch formats does RomPatcher.js support?
IPS, UPS, APS for N64 and GBA, BPS, RUP, PPF, EBP, BSDiff with the .bdf and .bspatch extensions, Paper Mario Star Rod with the .mod extension, and VCDiff with the .xdelta and .vcdiff extensions. It can both apply patches and create them.
How do I run RomPatcher.js from the command line?
Run `npm install`, then `node index.js patch "my_rom.bin" "my_patch.ips"` to apply a patch, or `node index.js create "original_rom.bin" modified_rom.bin` to create one. The package also declares a `RomPatcher` binary entry pointing at `./index.js`.
Can RomPatcher.js be embedded in my own website?
Yes. The README says modders and hackers can embed it to provide an online ROM patcher so users can patch ROMs without downloading any files. The `index_template.html` file includes a simple working example, and the wiki has a page with more detailed instructions.
What licence does RomPatcher.js use?
The package.json declares MIT, and the README links the LICENSE file at the repository root, while the project metadata records the licence as a custom licence that GitHub cannot classify. The LICENSE file is the document to read, which matters if you embed the tool on a site that serves patched game files.
How does RomPatcher.js check the ROM it is patching?
It shows the ROM CRC32, MD5 and SHA-1 before patching, and it can remove headers before applying a patch, and unzips files automatically. Showing the hashes first matters because a patch applies to one specific base image and a mismatched base produces a result that looks plausible but is wrong.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/marcrobledo-rompatcher-js)Was this useful?