mirror of
https://github.com/marcrobledo/RomPatcher.js.git
synced 2025-06-27 16:25:54 +00:00
Created Embedding Rom Patcher JS (markdown)
parent
2326dfe417
commit
5ba1089794
1 changed files with 209 additions and 0 deletions
209
Embedding-Rom-Patcher-JS.md
Normal file
209
Embedding-Rom-Patcher-JS.md
Normal file
|
@ -0,0 +1,209 @@
|
|||
# Embedding Rom Patcher JS in your site
|
||||
If you are self-hosting your own translations and/or hack patches, you can embed Rom Patcher JS and provide a nice solution for your users, allowing them to easily apply your patches to their ROMs without requiring them to download a single file, all thanks to the magic of the web!
|
||||
|
||||
Take a look at [`index_template.html`](https://github.com/marcrobledo/RomPatcher.js/blob/master/index_template.html) for a template. Basically you need to:
|
||||
|
||||
1. [Download the latest version](https://github.com/marcrobledo/RomPatcher.js/releases) and copy the entire `rom-patcher-js/` folder to your site
|
||||
2. Include **all** file imports from the `<header>` into yours:
|
||||
```html
|
||||
<link type="text/css" rel="stylesheet" href="./rom-patcher-js/style.css" media="all" />
|
||||
<script type="text/javascript" src="./rom-patcher-js/modules/BinFile.js"></script>
|
||||
...
|
||||
<script type="text/javascript" src="./rom-patcher-js/RomPatcher.js"></script>
|
||||
<script type="text/javascript" src="./rom-patcher-js/RomPatcher.webapp.js"></script>
|
||||
```
|
||||
3. Copy the needed HTML structure from `index_template.html`:
|
||||
```html
|
||||
<div id="rom-patcher-container">
|
||||
...
|
||||
</div>
|
||||
```
|
||||
4. Build a quick patcher with a simple call to `RomPatcherWeb.initialize`:
|
||||
```html
|
||||
<script type="text/javascript">
|
||||
window.addEventListener('load', function(){
|
||||
const myPatcherSettings={
|
||||
language: 'en',
|
||||
allowDropFiles: false /* if true, it adds drag and drop support,*/
|
||||
};
|
||||
RomPatcherWeb.initialize(myPatcherSettings, 'my_patch.ips');
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Providing additional patch information
|
||||
If you want to improve the user experience, you can provide additional information of your patches.<br/>
|
||||
Instead of a simple file path, you can build a JSON object like this:
|
||||
```js
|
||||
RomPatcherWeb.initialize(myPatcherSettings, {
|
||||
file: 'my_hack.ips',
|
||||
name: 'My game improvement (v2.0)', //patch name that will appear in the dropdown button
|
||||
inputCrc32: 0xdeadbeef, //add checksum validation to patch, will warn user if the ROM is not valid
|
||||
description: 'This patch translates the game and fixes bugs!', //short description that will appear when user picks this patch
|
||||
outputName: 'My game (Hack)' //patched ROM name
|
||||
});
|
||||
```
|
||||
It is recommended, though, to store the patch or patches in a single zip file:
|
||||
```js
|
||||
RomPatcherWeb.initialize(myPatcherSettings, {
|
||||
file: 'my_patches.zip', //zip containing patches
|
||||
patches: [ //information about patches inside the zip
|
||||
{
|
||||
file: 'my_hack.ips', //required, must match the patch file name in the zip
|
||||
name: 'My game improvement hack (v2.0)',
|
||||
inputCrc32: [0xdeadbeef, 0xd0d0cafe], //an array of valid checksums
|
||||
description: 'This patch translates the game and fixes bugs! (Recommended)',
|
||||
outputName: 'My game improvement'
|
||||
},
|
||||
{
|
||||
file: 'my_hack_vanilla.ips',
|
||||
name: 'My game improvement hack (v2.0, no bugfixes)',
|
||||
inputCrc32: [0xdeadbeef, 0xd0d0cafe],
|
||||
description: 'This patch translates the game but keeps the original game\'s bugs untouched for a vanilla experience',
|
||||
outputName: 'My game improvement'
|
||||
},
|
||||
/* ... */
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Events
|
||||
If you want to go further, you can run your own code via events:
|
||||
```js
|
||||
const myPatcherSettings={
|
||||
language: 'en',
|
||||
|
||||
onloadrom: function (romFile) {
|
||||
/* this event is triggered when user provides a ROM and before validating it */
|
||||
/* can be used to: */
|
||||
/* - modify it before validation (e.g. add/remove/fix header, change endianness...) */
|
||||
/* - to switch to another patch file in the dropdown selector */
|
||||
},
|
||||
onvalidaterom: function (romFile, isRomValid) {
|
||||
/* this event is triggered after ROM is validated */
|
||||
/* can be used to show a custom error message if provided ROM is not valid */
|
||||
},
|
||||
onpatch: function (romFile) {
|
||||
/* this event is triggered a ROM is patched */
|
||||
/* can be used to modify it before the patched ROM file is saved */
|
||||
}
|
||||
};
|
||||
```
|
||||
In all events, the `romFile` parameter is an instance of [BinFile.js](https://github.com/marcrobledo/RomPatcher.js/blob/master/rom-patcher-js/modules/BinFile.js), which allows easy file data and name manipulation.
|
||||
|
||||
|
||||
|
||||
|
||||
### Example: Fix ROM endianness
|
||||
N64 ROM files are usually stored in `.z64` (Big Endian) or `.n64` (Little Endian) formats. You can make your patcher compatible with both formats by changing the provided ROM file endianness before patching (and then restoring it after patching).<br/>
|
||||
```js
|
||||
const SSB_LITTE_ENDIAN_CRC32 = 0xf0b7c200;
|
||||
var romIsLittleEndian;
|
||||
|
||||
RomPatcher.initialize(
|
||||
{
|
||||
onloadrom:function(romFile, patch){
|
||||
/* if ROM is little endian */
|
||||
if(romFile.getExtension()==='n64' && romFile.hashMD5()===SSB_LITTE_ENDIAN_CRC32){
|
||||
/* change endianness to big */
|
||||
romFile.swapBytes(4);
|
||||
/* change extension */
|
||||
romFile.setExtension('z64');
|
||||
|
||||
romIsLittleEndian=true;
|
||||
}else{
|
||||
romIsLittleEndian=false;
|
||||
}
|
||||
},
|
||||
onpatch:function(patchedRomFile){
|
||||
/* if ROM was little endian */
|
||||
if(romIsLittleEndian){
|
||||
/* revert endianness to little */
|
||||
romFile.swapBytes(4);
|
||||
/* revert extension */
|
||||
romFile.setExtension('n64');
|
||||
}
|
||||
}
|
||||
}, {
|
||||
file: 'smashremix1.5.2.xdelta',
|
||||
inputCrc32: 0xeb97929e,
|
||||
name: 'Smash Remix v1.5.2',
|
||||
outputName: 'Smash Remix v1.5.2 (Hack)'
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
### Example: Choose correct patch automatically
|
||||
If your zip file contains several patches for different ROMs, you can make Rom Patcher JS so it picks automatically the patch for the provided ROM.
|
||||
```js
|
||||
const SML2_CHECKSUM_WORLD = 0xd5ec24e4;
|
||||
const SML2_CHECKSUM_JAPAN = 0xa715daf5;
|
||||
const SML2_CHECKSUMS_INVALID = [0xe6f886e5, 0x635a9112, 0xbf733e10, 0x29e0911a];
|
||||
|
||||
RomPatcher.initialize(
|
||||
{
|
||||
onloadrom: function (romFile) {
|
||||
const crc32 = romFile.hashCRC32();
|
||||
/* if ROM region is USA/Europe */
|
||||
if (crc32 === SML2_CHECKSUM_WORLD)
|
||||
RomPatcherWeb.pickEmbededFile('SML2DXv181.ips');
|
||||
/* if ROM region is Japan */
|
||||
else if (crc32 === SML2_CHECKSUM_JAPAN)
|
||||
RomPatcherWeb.pickEmbededFile('SML2DXv181_jap.ips');
|
||||
},
|
||||
onvalidaterom: function (romFile, isRomValid) {
|
||||
const crc32 = romFile.hashCRC32();
|
||||
/* if ROM is a known SML2 revision that is not compatible with the patch*/
|
||||
if (!isRomValid && SML2_CHECKSUMS_INVALID.indexOf(crc32) !== -1)
|
||||
RomPatcherWeb.setErrorMessage('Please provide a v1.0 SML2 ROM');
|
||||
}
|
||||
}, {
|
||||
file: 'SML2DXv181.zip',
|
||||
patches: [
|
||||
{
|
||||
file: 'SML2DXv181.ips',
|
||||
name: 'Super Mario Land 2 DX - 6 Golden Coins (v1.8.1)',
|
||||
inputCrc32: SML2_CHECKSUM_WORLD,
|
||||
description: 'SML2 colorization hack (USA/Europe) by toruzz',
|
||||
outputName: 'Super Mario Land 2 DX - 6 Golden Coins (Hack)',
|
||||
outputExtension: 'gbc'
|
||||
},
|
||||
{
|
||||
file: 'SML2DXv181_jap.ips',
|
||||
name: 'Super Mario Land 2 DX - 6-tsu no Kinka (v1.8.1)',
|
||||
inputCrc32: SML2_CHECKSUM_JAPAN,
|
||||
description: 'SML2 colorization hack (Japan) by toruzz',
|
||||
outputName: 'Super Mario Land 2 DX - 6-tsu no Kinka (Hack)',
|
||||
outputExtension: 'gbc'
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
### Example: Remove header
|
||||
SNES ROM files are usually stored in `.sfc` (headerless) or `.smc` (headered) formats. You can make your patcher compatible with both formats by detecting if the ROM is headered and remove the header before the ROM is validated.<br/>
|
||||
```js
|
||||
RomPatcher.initialize(
|
||||
{
|
||||
onloadrom: function (romFile) {
|
||||
const SMC_HEADER_SIZE=512;
|
||||
if(romFile.getExtension()==='smc' && ((romFile.fileSize - SMC_HEADER_SIZE) % 0x20000) === 0){
|
||||
romFile.removeLeadingBytes(SMC_HEADER_SIZE);
|
||||
romFile.setExtension('sfc');
|
||||
console.log('removed SMC header');
|
||||
}
|
||||
}
|
||||
}, {
|
||||
file: 'Tekkaman Blade v1.0.rup',
|
||||
name: 'English translation by D and Near',
|
||||
outputName: 'Uchuu no Kishi Tekkaman Blade (English v1.0)',
|
||||
}
|
||||
);
|
||||
```
|
Loading…
Add table
Add a link
Reference in a new issue