1
0
Fork 0
mirror of https://github.com/marcrobledo/RomPatcher.js.git synced 2025-06-27 16:25:54 +00:00

refactor and added EBP description showing in frontend

This commit is contained in:
Marc Robledo 2025-04-30 01:11:55 +02:00
parent 198c046424
commit 844cfcb5a6
5 changed files with 88 additions and 55 deletions

View file

@ -3,8 +3,8 @@
<head> <head>
<title>Rom Patcher JS</title> <title>Rom Patcher JS</title>
<meta http-equiv="content-Type" content="text/html; charset=UTF-8"/> <meta http-equiv="content-Type" content="text/html; charset=UTF-8"/>
<meta name="description" content="An online web-based ROM patcher. Supported formats: IPS, BPS, UPS, APS, RUP, PPF, EBP and xdelta."/> <meta name="description" content="An online web-based ROM patcher. Supported formats: IPS, BPS, UPS, APS, RUP, EBP, PPF and xdelta."/>
<meta name="keywords" content="ips,ebp,ups,aps,bps,rup,ninja,ppf,xdelta,patcher,online,html5,web,rom,patch,hack,translation"/> <meta name="keywords" content="ips,ups,aps,bps,rup,ninja,ebp,ppf,xdelta,patcher,online,html5,web,rom,patch,hack,translation"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
<link rel="manifest" href="./manifest.json"/> <link rel="manifest" href="./manifest.json"/>
<link rel="shortcut icon" href="./webapp/app_icon_16.png" type="image/png" sizes="16x16"/> <link rel="shortcut icon" href="./webapp/app_icon_16.png" type="image/png" sizes="16x16"/>
@ -27,7 +27,7 @@
<meta name="twitter:domain" content="marcrobledo.com"> <meta name="twitter:domain" content="marcrobledo.com">
<meta property="og:title" content="Rom Patcher JS"> <meta property="og:title" content="Rom Patcher JS">
<meta name="twitter:title" content="Rom Patcher JS"> <meta name="twitter:title" content="Rom Patcher JS">
<meta name="twitter:description" content="An online web-based ROM patcher. Supported formats: IPS, BPS, UPS, APS, RUP, PPF, EBP and xdelta."> <meta name="twitter:description" content="An online web-based ROM patcher. Supported formats: IPS, BPS, UPS, APS, RUP, EBP, PPF and xdelta.">
<meta property="og:image" content="https://www.marcrobledo.com/RomPatcher.js/webapp/thumbnail.jpg"> <meta property="og:image" content="https://www.marcrobledo.com/RomPatcher.js/webapp/thumbnail.jpg">
<meta name="twitter:image" content="https://www.marcrobledo.com/RomPatcher.js/webapp/thumbnail.jpg"> <meta name="twitter:image" content="https://www.marcrobledo.com/RomPatcher.js/webapp/thumbnail.jpg">
<meta name="twitter:card" content="photo"> <meta name="twitter:card" content="photo">
@ -152,7 +152,7 @@
<button id="button-settings" class="btn-transparent"><img src="./webapp/icon_settings.svg" loading="lazy" class="icon settings" /> <span data-localize="yes">Settings</span></button> <button id="button-settings" class="btn-transparent"><img src="./webapp/icon_settings.svg" loading="lazy" class="icon settings" /> <span data-localize="yes">Settings</span></button>
</div> </div>
Rom Patcher JS <small><a href="legacy/" rel="nofollow">v3.1</a></small> by <a href="/">Marc Robledo</a> Rom Patcher JS <small><a href="legacy/" rel="nofollow">v3.2</a></small> by <a href="/">Marc Robledo</a>
<br /> <br />
<img src="./webapp/icon_github.svg" loading="lazy" class="icon github" /> <a href="https://github.com/marcrobledo/RomPatcher.js/" target="_blank">See on GitHub</a> <img src="./webapp/icon_github.svg" loading="lazy" class="icon github" /> <a href="https://github.com/marcrobledo/RomPatcher.js/" target="_blank">See on GitHub</a>
<img src="./webapp/icon_heart.svg" loading="lazy" class="icon heart" /> <a href="https://www.paypal.me/marcrobledo/5" target="_blank" rel="nofollow">Donate</a> <img src="./webapp/icon_heart.svg" loading="lazy" class="icon heart" /> <a href="https://www.paypal.me/marcrobledo/5" target="_blank" rel="nofollow">Donate</a>

View file

@ -242,8 +242,8 @@ const RomPatcher = (function () {
format = 'ips'; format = 'ips';
var patch; var patch;
if (format === 'ips' || format === 'ebp') { if (format === 'ips') {
patch = IPS.buildFromRoms(originalFile, modifiedFile, format === 'ebp'); patch = IPS.buildFromRoms(originalFile, modifiedFile);
} else if (format === 'bps') { } else if (format === 'bps') {
patch = BPS.buildFromRoms(originalFile, modifiedFile, (originalFile.fileSize <= 4194304)); patch = BPS.buildFromRoms(originalFile, modifiedFile, (originalFile.fileSize <= 4194304));
} else if (format === 'ppf') { } else if (format === 'ppf') {
@ -254,6 +254,8 @@ const RomPatcher = (function () {
patch = APS.buildFromRoms(originalFile, modifiedFile); patch = APS.buildFromRoms(originalFile, modifiedFile);
} else if (format === 'rup') { } else if (format === 'rup') {
patch = RUP.buildFromRoms(originalFile, modifiedFile); patch = RUP.buildFromRoms(originalFile, modifiedFile);
} else if (format === 'ebp') {
patch = IPS.buildFromRoms(originalFile, modifiedFile, true);
} else { } else {
throw new Error('Invalid patch format'); throw new Error('Invalid patch format');
} }

View file

@ -1175,7 +1175,7 @@ const ZIPManager = (function (romPatcherWeb) {
const ZIP_MAGIC = '\x50\x4b\x03\x04'; const ZIP_MAGIC = '\x50\x4b\x03\x04';
const FILTER_PATCHES = /\.(ips|ebp|ups|bps|aps|rup|ppf|mod|xdelta|vcdiff)$/i; const FILTER_PATCHES = /\.(ips|ups|bps|aps|rup|ppf|mod|ebp|xdelta|vcdiff)$/i;
//const FILTER_ROMS=/(?<!\.(txt|diz|rtf|docx?|xlsx?|html?|pdf|jpe?g|gif|png|bmp|webp|zip|rar|7z))$/i; //negative lookbehind is not compatible with Safari https://stackoverflow.com/a/51568859 //const FILTER_ROMS=/(?<!\.(txt|diz|rtf|docx?|xlsx?|html?|pdf|jpe?g|gif|png|bmp|webp|zip|rar|7z))$/i; //negative lookbehind is not compatible with Safari https://stackoverflow.com/a/51568859
const FILTER_NON_ROMS = /(\.(txt|diz|rtf|docx?|xlsx?|html?|pdf|jpe?g|gif|png|bmp|webp|zip|rar|7z))$/i; const FILTER_NON_ROMS = /(\.(txt|diz|rtf|docx?|xlsx?|html?|pdf|jpe?g|gif|png|bmp|webp|zip|rar|7z))$/i;

View file

@ -1,21 +1,14 @@
/* IPS module for Rom Patcher JS v20230924 - Marc Robledo 2016-2023 - http://www.marcrobledo.com/license */ /* IPS module for Rom Patcher JS v20250430 - Marc Robledo 2016-2025 - http://www.marcrobledo.com/license */
/* File format specification: http://www.smwiki.net/wiki/IPS_file_format */ /* File format specification: http://www.smwiki.net/wiki/IPS_file_format */
/* This file also acts as EBP (EarthBound Patch) module */
/* EBP is actually just IPS with some JSON metadata stuck on the end (implementation: https://github.com/Lyrositor/EBPatcher) */
const IPS_MAGIC='PATCH'; const IPS_MAGIC='PATCH';
const IPS_MAX_ROM_SIZE=0x1000000; //16 megabytes const IPS_MAX_ROM_SIZE=0x1000000; //16 megabytes
const IPS_RECORD_RLE=0x0000; const IPS_RECORD_RLE=0x0000;
const IPS_RECORD_SIMPLE=0x01; const IPS_RECORD_SIMPLE=0x01;
/* There is also support for the EBP (EarthBound Patch) format here. */
/* EBP has no real specification, but an implementation is here: https://github.com/Lyrositor/EBPatcher */
/* EBP is actually just IPS with some JSON metadata stuck on the end. */
/* We can safely ignore this data when applying patches. */
/* When creating patches, insert this data after everything else. */
/* Finally, EBP doesn't seem to support truncation metadata. */
const EBP_MAGIC_META_OPENER = 0x7B //UTF-8 '{'
/* EBPatcher (linked above) expects the "patcher" field to be EBPatcher to read the metadata. Can't imagine why... */
/* CoilSnake (EB modding tool) inserts this manually too. */
const EBP_META_DEFAULT={"patcher": "EBPatcher", "author": "Unknown", "title": "Untitled", "description": "No description"}
if(typeof module !== "undefined" && module.exports){ if(typeof module !== "undefined" && module.exports){
module.exports = IPS; module.exports = IPS;
@ -25,8 +18,7 @@ if(typeof module !== "undefined" && module.exports){
function IPS(){ function IPS(){
this.records=[]; this.records=[];
this.truncate=false; this.truncate=false;
this.isEBP=false; this.EBPmetadata=null;
this.EBPmetadata=JSON.stringify(EBP_META_DEFAULT)
} }
IPS.prototype.addSimpleRecord=function(o, d){ IPS.prototype.addSimpleRecord=function(o, d){
this.records.push({offset:o, type:IPS_RECORD_SIMPLE, length:d.length, data:d}) this.records.push({offset:o, type:IPS_RECORD_SIMPLE, length:d.length, data:d})
@ -34,9 +26,31 @@ IPS.prototype.addSimpleRecord=function(o, d){
IPS.prototype.addRLERecord=function(o, l, b){ IPS.prototype.addRLERecord=function(o, l, b){
this.records.push({offset:o, type:IPS_RECORD_RLE, length:l, byte:b}) this.records.push({offset:o, type:IPS_RECORD_RLE, length:l, byte:b})
} }
IPS.prototype.addEBPMetadata=function(author, title, description){ IPS.prototype.setEBPMetadata=function(metadataObject){
/* currently not used - no frontend support */ if(typeof metadataObject !== 'object')
this.EBPmetadata=JSON.stringify({"patcher": "EBPatcher", "author": author, "title": title, "description": description}) throw new TypeError('metadataObject must be an object');
for(var key in metadataObject){
if(typeof metadataObject[key] !== 'string')
throw new TypeError('metadataObject values must be strings');
}
/* EBPatcher (linked above) expects the "patcher" field to be EBPatcher to read the metadata */
/* CoilSnake (EB modding tool) inserts this manually too */
/* So we also add it here for compatibility purposes */
this.EBPmetadata={patcher:'EBPatcher', ...metadataObject};
}
IPS.prototype.getDescription=function(){
if(this.EBPmetadata){
var description='';
for(var key in this.EBPmetadata){
if(key!=='patcher'){
const keyPretty=key.charAt(0).toUpperCase() + key.slice(1);
description+=keyPretty+': '+this.EBPmetadata[key]+'\n';
}
}
return description.trim();
}
return null;
} }
IPS.prototype.toString=function(){ IPS.prototype.toString=function(){
nSimpleRecords=0; nSimpleRecords=0;
@ -50,9 +64,10 @@ IPS.prototype.toString=function(){
var s='Simple records: '+nSimpleRecords; var s='Simple records: '+nSimpleRecords;
s+='\nRLE records: '+nRLERecords; s+='\nRLE records: '+nRLERecords;
s+='\nTotal records: '+this.records.length; s+='\nTotal records: '+this.records.length;
if(this.truncate && !this.isEBP) if(this.truncate && !this.EBPmetadata)
s+='\nTruncate at: 0x'+this.truncate.toString(16); s+='\nTruncate at: 0x'+this.truncate.toString(16);
s+='\nIs EBP: '+this.isEBP else if(this.EBPmetadata)
s+='\nEBP Metadata: '+JSON.stringify(this.EBPmetadata);
return s return s
} }
IPS.prototype.export=function(fileName){ IPS.prototype.export=function(fileName){
@ -64,13 +79,13 @@ IPS.prototype.export=function(fileName){
patchFileSize+=(3+2+this.records[i].data.length); //offset+length+data patchFileSize+=(3+2+this.records[i].data.length); //offset+length+data
} }
patchFileSize+=3; //EOF string patchFileSize+=3; //EOF string
if(this.truncate && !this.isEBP) if(this.truncate && !this.EBPmetadata)
patchFileSize+=3; //truncate patchFileSize+=3; //truncate
if(this.isEBP) else if(this.EBPmetadata)
patchFileSize+=this.EBPmetadata.length patchFileSize+=JSON.stringify(this.EBPmetadata);
tempFile=new BinFile(patchFileSize); tempFile=new BinFile(patchFileSize);
tempFile.fileName=fileName+('.ebp' ? this.isEBP : '.ips'); tempFile.fileName=fileName+(this.EBPmetadata? '.ebp' : '.ips');
tempFile.writeString(IPS_MAGIC); tempFile.writeString(IPS_MAGIC);
for(var i=0; i<this.records.length; i++){ for(var i=0; i<this.records.length; i++){
var rec=this.records[i]; var rec=this.records[i];
@ -86,17 +101,15 @@ IPS.prototype.export=function(fileName){
} }
tempFile.writeString('EOF'); tempFile.writeString('EOF');
if(this.truncate && !this.isEBP) if(this.truncate && !this.EBPmetadata)
tempFile.writeU24(this.truncate); tempFile.writeU24(this.truncate);
else if(this.EBPmetadata)
if(this.isEBP) { tempFile.writeString(JSON.stringify(this.EBPmetadata));
tempFile.writeString(this.EBPmetadata)
}
return tempFile return tempFile
} }
IPS.prototype.apply=function(romFile){ IPS.prototype.apply=function(romFile){
if(this.truncate && !this.isEBP){ if(this.truncate && !this.EBPmetadata){
if(this.truncate>romFile.fileSize){ //expand (discussed here: https://github.com/marcrobledo/RomPatcher.js/pull/46) if(this.truncate>romFile.fileSize){ //expand (discussed here: https://github.com/marcrobledo/RomPatcher.js/pull/46)
tempFile=new BinFile(this.truncate); tempFile=new BinFile(this.truncate);
romFile.copyTo(tempFile, 0, romFile.fileSize, 0); romFile.copyTo(tempFile, 0, romFile.fileSize, 0);
@ -159,7 +172,9 @@ IPS.fromFile=function(file){
}else if((file.offset+3)===file.fileSize){ }else if((file.offset+3)===file.fileSize){
patchFile.truncate=file.readU24(); patchFile.truncate=file.readU24();
break; break;
}else if (file.readU8()===EBP_MAGIC_META_OPENER) { }else if (file.readU8()==='{'.charCodeAt(0)) {
file.skip(-1);
patchFile.setEBPMetadata(JSON.parse(file.readString(file.fileSize-file.offset)));
break; break;
} }
} }
@ -179,10 +194,14 @@ IPS.fromFile=function(file){
IPS.buildFromRoms=function(original, modified, asEBP=false){ IPS.buildFromRoms=function(original, modified, asEBP=false){
var patch=new IPS(); var patch=new IPS();
patch.isEBP=asEBP if(!asEBP && modified.fileSize<original.fileSize){
if(modified.fileSize<original.fileSize && !patch.isEBP){
patch.truncate=modified.fileSize; patch.truncate=modified.fileSize;
}else if(asEBP){
patch.setEBPMetadata(typeof asEBP==='object'? asEBP : {
'Author':'Unknown',
'Title':'Untitled',
'Description':'No description',
});
} }
//solucion: guardar startOffset y endOffset (ir mirando de 6 en 6 hacia atrás) //solucion: guardar startOffset y endOffset (ir mirando de 6 en 6 hacia atrás)
@ -231,7 +250,7 @@ IPS.buildFromRoms=function(original, modified, asEBP=false){
} }
}else{ }else{
if(startOffset>=IPS_MAX_ROM_SIZE){ if(startOffset>=IPS_MAX_ROM_SIZE){
throw new Error(`Files are too big for ${'EBP' ? patch.isEBP : 'IPS'} format`); throw new Error(`Files are too big for ${patch.EBPmetadata? 'EBP' : 'IPS'} format`);
return null; return null;
} }

42
test.js
View file

@ -14,9 +14,6 @@
- IPS test - IPS test
- Patch: https://www.romhacking.net/hacks/3784/ - Patch: https://www.romhacking.net/hacks/3784/
- ROM: Super Mario Land 2 - 6 Golden Coins (USA, Europe).gb [CRC32=d5ec24e4] - ROM: Super Mario Land 2 - 6 Golden Coins (USA, Europe).gb [CRC32=d5ec24e4]
- EBP test
- Patch: https://forum.starmen.net/forum/Community/PKHack/NickBound/page/1#post2333521
- ROM: EarthBound (USA).sfc [CRC32=dc9bb451]
- BPS test - BPS test
- Patch: https://www.romhacking.net/translations/6297/ - Patch: https://www.romhacking.net/translations/6297/
- ROM: Samurai Kid (Japan).gbc [CRC32=44a9ddfb] - ROM: Samurai Kid (Japan).gbc [CRC32=44a9ddfb]
@ -26,9 +23,15 @@
- APS test - APS test
- Patch: http://dorando.emuverse.com/projects/eduardo_a2j/zelda-ocarina-of-time.html - Patch: http://dorando.emuverse.com/projects/eduardo_a2j/zelda-ocarina-of-time.html
- ROM: Legend of Zelda, The - Ocarina of Time (USA).z64 [CRC32=7e107c35] - ROM: Legend of Zelda, The - Ocarina of Time (USA).z64 [CRC32=7e107c35]
- APS (GBA) test
- Patch: http://ngplus.net/InsaneDifficultyArchive/www.insanedifficulty.com/board/index9837.html?/files/file/65-final-fantasy-tactics-advance-x/
- ROM: Final Fantasy Tactics Advance (USA).gba [CRC32=5645e56c]
- RUP test - RUP test
- Patch: https://www.romhacking.net/translations/843/ - Patch: https://www.romhacking.net/translations/843/
- ROM: Uchuu no Kishi - Tekkaman Blade (Japan).sfc [CRC32=cd16c529] - ROM: Uchuu no Kishi - Tekkaman Blade (Japan).sfc [CRC32=cd16c529]
- EBP test
- Patch: https://forum.starmen.net/forum/Community/PKHack/NickBound/page/1#post2333521
- ROM: EarthBound (USA).sfc [CRC32=dc9bb451]
- xdelta test - xdelta test
- Patch: https://www.romhacking.net/hacks/2871/ - Patch: https://www.romhacking.net/hacks/2871/
- ROM: New Super Mario Bros. (USA, Australia).nds [CRC32=0197576a] - ROM: New Super Mario Bros. (USA, Australia).nds [CRC32=0197576a]
@ -53,14 +56,6 @@ const TEST_PATCHES = [
patchCrc32: 0x0b742316, patchCrc32: 0x0b742316,
patchDownload: 'https://www.romhacking.net/hacks/3784/', patchDownload: 'https://www.romhacking.net/hacks/3784/',
outputCrc32: 0xf0799017 outputCrc32: 0xf0799017
}, {
title: 'EBP - Mother Rebound',
romFile: 'EarthBound (USA).sfc',
romCrc32: 0xdc9bb451,
patchFile: 'Mother_Rebound.ebp',
patchCrc32: 0x271719e1,
patchDownload: 'https://forum.starmen.net/forum/Community/PKHack/NickBound/page/1#post2333521',
outputCrc32: 0x5065b02f
}, { }, {
title: 'BPS - Samurai Kid translation', title: 'BPS - Samurai Kid translation',
romFile: 'Samurai Kid (Japan).gbc', romFile: 'Samurai Kid (Japan).gbc',
@ -85,6 +80,14 @@ const TEST_PATCHES = [
patchCrc32: 0x7b70119d, patchCrc32: 0x7b70119d,
patchDownload: 'http://dorando.emuverse.com/projects/eduardo_a2j/zelda-ocarina-of-time.html', patchDownload: 'http://dorando.emuverse.com/projects/eduardo_a2j/zelda-ocarina-of-time.html',
outputCrc32: 0x7866f1ca outputCrc32: 0x7866f1ca
}, {
title: 'APS (GBA) - Final Fantasy Tactics Advance X',
romFile: 'Final Fantasy Tactics Advance (USA).gba',
romCrc32: 0x5645e56c,
patchFile: 'FFTA_X_1.0.3.1.aps',
patchCrc32: 0x77e5f2ae,
patchDownload: 'http://ngplus.net/InsaneDifficultyArchive/www.insanedifficulty.com/board/index9837.html?/files/file/65-final-fantasy-tactics-advance-x/',
outputCrc32: 0x49a5539a
}, { }, {
title: 'Tekkaman Blade translation', title: 'Tekkaman Blade translation',
romFile: 'Uchuu no Kishi - Tekkaman Blade (Japan).sfc', romFile: 'Uchuu no Kishi - Tekkaman Blade (Japan).sfc',
@ -92,8 +95,17 @@ const TEST_PATCHES = [
patchFile: 'Tekkaman Blade v1.0.rup', patchFile: 'Tekkaman Blade v1.0.rup',
patchCrc32: 0x621ab323, patchCrc32: 0x621ab323,
patchDownload: 'https://www.romhacking.net/hacks/4633/', patchDownload: 'https://www.romhacking.net/hacks/4633/',
outputCrc32: 0xe83e9b0a //outputCrc32: 0xe83e9b0a //Headerless
outputCrc32: 0xda833bce //Headered
}, { }, {
title: 'EBP - Mother Rebound',
romFile: 'EarthBound (USA).sfc',
romCrc32: 0xdc9bb451,
patchFile: 'Mother_Rebound.ebp',
patchCrc32: 0x271719e1,
patchDownload: 'https://forum.starmen.net/forum/Community/PKHack/NickBound/page/1#post2333521',
outputCrc32: 0x5065b02f
}, {
title: 'NSMB Hack Domain Infusion', title: 'NSMB Hack Domain Infusion',
romFile: 'New Super Mario Bros. (USA, Australia).nds', romFile: 'New Super Mario Bros. (USA, Australia).nds',
romCrc32: 0x0197576a, romCrc32: 0x0197576a,
@ -139,7 +151,7 @@ _test('HashCalculator integrity', function () {
const MODIFIED_TEST_DATA = (new Uint8Array([ const MODIFIED_TEST_DATA = (new Uint8Array([
98, 91, 64, 8, 35, 53, 122, 167, 52, 253, 222, 156, 247, 82, 227, 213, 22, 221, 17, 247, 107, 102, 164, 254, 221, 8, 207, 63, 117, 164, 223, 10, 1, 77, 87, 123, 48, 9, 111, 64, 233, 118, 1, 36, 1, 60, 208, 245, 136, 126, 29, 231, 168, 18, 125, 172, 11, 184, 81, 20, 16, 30, 154, 16, 236, 21, 5, 74, 255, 112, 171, 198, 185, 89, 2, 98, 45, 164, 214, 55, 103, 15, 217, 95, 212, 133, 184, 21, 67, 144, 198, 163, 76, 35, 248, 229, 163, 37, 103, 33, 193, 96, 77, 255, 117, 89, 193, 61, 64, 253, 119, 82, 49, 187, 195, 165, 205, 140, 222, 134, 249, 68, 224, 248, 144, 207, 18, 126 98, 91, 64, 8, 35, 53, 122, 167, 52, 253, 222, 156, 247, 82, 227, 213, 22, 221, 17, 247, 107, 102, 164, 254, 221, 8, 207, 63, 117, 164, 223, 10, 1, 77, 87, 123, 48, 9, 111, 64, 233, 118, 1, 36, 1, 60, 208, 245, 136, 126, 29, 231, 168, 18, 125, 172, 11, 184, 81, 20, 16, 30, 154, 16, 236, 21, 5, 74, 255, 112, 171, 198, 185, 89, 2, 98, 45, 164, 214, 55, 103, 15, 217, 95, 212, 133, 184, 21, 67, 144, 198, 163, 76, 35, 248, 229, 163, 37, 103, 33, 193, 96, 77, 255, 117, 89, 193, 61, 64, 253, 119, 82, 49, 187, 195, 165, 205, 140, 222, 134, 249, 68, 224, 248, 144, 207, 18, 126
])).buffer; ])).buffer;
['ips', 'bps', 'ppf', 'ups', 'aps', 'rup'].forEach(function (patchFormat) { ['ips', 'bps', 'ppf', 'ups', 'aps', 'rup', 'ebp'].forEach(function (patchFormat) {
_test('create and apply ' + patchFormat.toUpperCase(), function () { _test('create and apply ' + patchFormat.toUpperCase(), function () {
const originalFile = new BinFile(TEST_DATA); const originalFile = new BinFile(TEST_DATA);
const modifiedFile = new BinFile(MODIFIED_TEST_DATA); const modifiedFile = new BinFile(MODIFIED_TEST_DATA);
@ -165,7 +177,7 @@ TEST_PATCHES.forEach(function (patchInfo) {
const patchPath = TEST_PATH + 'patches/' + patchInfo.patchFile; const patchPath = TEST_PATH + 'patches/' + patchInfo.patchFile;
if (!existsSync(patchPath)) { if (!existsSync(patchPath)) {
console.log(chalk.yellow('! skipping patch ' + patchInfo.title)); console.log(chalk.yellow('! skipping patch ' + patchInfo.title));
console.log(chalk.yellow(' patch file not found: ' + patchInfo.patchFile)); console.log(chalk.yellow(' patch file not found: ' + TEST_PATH + 'patches/' + patchInfo.patchFile));
console.log(chalk.yellow(' download patch at ' + patchInfo.patchDownload)); console.log(chalk.yellow(' download patch at ' + patchInfo.patchDownload));
return false; return false;
} }
@ -181,7 +193,7 @@ TEST_PATCHES.forEach(function (patchInfo) {
const romPath = TEST_PATH + 'roms/' + patchInfo.romFile; const romPath = TEST_PATH + 'roms/' + patchInfo.romFile;
if (!existsSync(romPath)) { if (!existsSync(romPath)) {
console.log(chalk.yellow('! skipping patch ' + patchInfo.title)); console.log(chalk.yellow('! skipping patch ' + patchInfo.title));
console.log(chalk.yellow(' ROM file not found: ' + patchInfo.romFile)); console.log(chalk.yellow(' ROM file not found: ' + TEST_PATH + 'roms/' + patchInfo.romFile));
return false; return false;
} }
const romFile = new BinFile(romPath); const romFile = new BinFile(romPath);