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

Merge branch 'marcrobledo:master' into main

This commit is contained in:
xenophile 2024-08-28 12:24:44 -07:00 committed by GitHub
commit 146231dde7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 217 additions and 193 deletions

View file

@ -6,7 +6,7 @@
*/ */
var PRECACHE_ID = 'rom-patcher-js'; var PRECACHE_ID = 'rom-patcher-js';
var PRECACHE_VERSION = 'v30rc2b'; var PRECACHE_VERSION = 'v30rc4';
var PRECACHE_URLS = [ var PRECACHE_URLS = [
'/RomPatcher.js/', '/RomPatcher.js/index.html', '/RomPatcher.js/', '/RomPatcher.js/index.html',
'/RomPatcher.js/manifest.json', '/RomPatcher.js/manifest.json',

View file

@ -151,7 +151,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>v3.0 <a style="color:rgb(255, 197, 7)" href="legacy/" rel="nofollow">RC2</a></small> by <a href="/">Marc Robledo</a> Rom Patcher JS <small>v3.0 <a style="color:rgb(255, 197, 7)" href="legacy/" rel="nofollow">RC4</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

@ -318,7 +318,8 @@ var RomPatcherWeb = (function () {
return fallback || 0; return fallback || 0;
}, },
setFakeFile: function (id, fileName) { setFakeFile: function (id, fileName) {
if (document.getElementById('rom-patcher-input-file-' + id)) { const isBrowserSafari = /Safari/i.test(navigator.userAgent); /* safari does not show fake file name: https://pqina.nl/blog/set-value-to-file-input/#but-safari */
if (!isBrowserSafari && document.getElementById('rom-patcher-input-file-' + id)) {
try { try {
/* add a fake file to the input file, so it shows the chosen file name */ /* add a fake file to the input file, so it shows the chosen file name */
const fakeFile = new File(new Uint8Array(0), fileName); const fakeFile = new File(new Uint8Array(0), fileName);
@ -508,6 +509,15 @@ var RomPatcherWeb = (function () {
return false; return false;
} }
const _dragEventContainsFiles = function (evt) {
if (evt.dataTransfer.types) {
for (var i = 0; i < evt.dataTransfer.types.length; i++) {
if (evt.dataTransfer.types[i] === 'Files')
return true;
}
}
return false;
}
const _initialize = function (newSettings, embededPatchInfo) { const _initialize = function (newSettings, embededPatchInfo) {
/* embeded patches */ /* embeded patches */
var validEmbededPatch = _checkEmbededPatchParameter(embededPatchInfo); var validEmbededPatch = _checkEmbededPatchParameter(embededPatchInfo);
@ -727,106 +737,110 @@ var RomPatcherWeb = (function () {
if (ZIPManager.isZipFile(binFile)) { if (ZIPManager.isZipFile(binFile)) {
ZIPManager.unzipPatches(binFile._u8array.buffer); ZIPManager.unzipPatches(binFile._u8array.buffer);
} else { } else {
const parsedPatch = RomPatcher.parsePatchFile(binFile); try{
if (parsedPatch) { const parsedPatch = RomPatcher.parsePatchFile(binFile);
patch = parsedPatch; if (parsedPatch) {
_setPatchInputSpinner(false); patch = parsedPatch;
_setPatchInputSpinner(false);
const embededPatchInfo = _getEmbededPatchInfo(binFile.fileName); const embededPatchInfo = _getEmbededPatchInfo(binFile.fileName);
if (embededPatchInfo) { if (embededPatchInfo) {
/* custom crc32s validation */ /* custom crc32s validation */
if (embededPatchInfo.inputCrc32) { if (embededPatchInfo.inputCrc32) {
patch.validateSource = function (romFile, headerSize) { patch.validateSource = function (romFile, headerSize) {
for (var i = 0; i < embededPatchInfo.inputCrc32.length; i++) { for (var i = 0; i < embededPatchInfo.inputCrc32.length; i++) {
if (embededPatchInfo.inputCrc32[i] === romFile.hashCRC32(headerSize)) if (embededPatchInfo.inputCrc32[i] === romFile.hashCRC32(headerSize))
return true; return true;
}
return false;
} }
return false; patch.getValidationInfo = function () {
return {
'type': 'CRC32',
'value': embededPatchInfo.inputCrc32
}
};
} }
patch.getValidationInfo = function () {
return { /* custom description */
'type': 'CRC32', if (embededPatchInfo.description) {
'value': embededPatchInfo.inputCrc32 patch.getDescription = function () {
return embededPatchInfo.description;
} }
}; }
} }
/* custom description */ /* toggle ROM requirements */
if (embededPatchInfo.description) { if (htmlElements.get('row-patch-requirements') && htmlElements.get('patch-requirements-value')) {
patch.getDescription = function () { if (typeof patch.getValidationInfo === 'function' && patch.getValidationInfo()) {
return embededPatchInfo.description; var validationInfo = patch.getValidationInfo();
} if (Array.isArray(validationInfo) || !validationInfo.type) {
} validationInfo = {
} type: 'ROM',
value: validationInfo
/* toggle ROM requirements */
if (htmlElements.get('row-patch-requirements') && htmlElements.get('patch-requirements-value')) {
if (typeof patch.getValidationInfo === 'function' && patch.getValidationInfo()) {
var validationInfo = patch.getValidationInfo();
if (Array.isArray(validationInfo) || !validationInfo.type) {
validationInfo = {
type: 'ROM',
value: validationInfo
}
}
htmlElements.setText('patch-requirements-value', '');
htmlElements.setText('patch-requirements-type', validationInfo.type === 'ROM' ? _('Required ROM:') : _('Required %s:').replace('%s', validationInfo.type));
if (!Array.isArray(validationInfo.value))
validationInfo.value = [validationInfo.value];
validationInfo.value.forEach(function (value) {
var line = document.createElement('div');
if (typeof value !== 'string') {
if (validationInfo.type === 'CRC32') {
value = value.toString(16);
while (value.length < 8)
value = '0' + value;
} else {
value = value.toString();
} }
} }
/* htmlElements.setText('patch-requirements-value', '');
var a=document.createElement('a');
a.href='https://www.google.com/search?q=%22'+value+'%22'; htmlElements.setText('patch-requirements-type', validationInfo.type === 'ROM' ? _('Required ROM:') : _('Required %s:').replace('%s', validationInfo.type));
a.target='_blank';
a.className='clickable'; if (!Array.isArray(validationInfo.value))
a.innerHTML=value; validationInfo.value = [validationInfo.value];
line.appendChild(a);
*/ validationInfo.value.forEach(function (value) {
line.innerHTML = value; var line = document.createElement('div');
htmlElements.get('patch-requirements-value').appendChild(line); if (typeof value !== 'string') {
}); if (validationInfo.type === 'CRC32') {
htmlElements.addClass('row-patch-requirements', 'show'); value = value.toString(16);
} else { while (value.length < 8)
htmlElements.setText('patch-requirements-value', ''); value = '0' + value;
htmlElements.removeClass('row-patch-requirements', 'show'); } else {
value = value.toString();
}
}
/*
var a=document.createElement('a');
a.href='https://www.google.com/search?q=%22'+value+'%22';
a.target='_blank';
a.className='clickable';
a.innerHTML=value;
line.appendChild(a);
*/
line.innerHTML = value;
htmlElements.get('patch-requirements-value').appendChild(line);
});
htmlElements.addClass('row-patch-requirements', 'show');
} else {
htmlElements.setText('patch-requirements-value', '');
htmlElements.removeClass('row-patch-requirements', 'show');
}
} }
}
/* toggle patch description */ /* toggle patch description */
if (typeof patch.getDescription === 'function' && patch.getDescription()) { if (typeof patch.getDescription === 'function' && patch.getDescription()) {
htmlElements.setText('patch-description', patch.getDescription()/* .replace(/\n/g, '<br/>') */); htmlElements.setText('patch-description', patch.getDescription()/* .replace(/\n/g, '<br/>') */);
//htmlElements.setTitle('patch-description', patch.getDescription()); //htmlElements.setTitle('patch-description', patch.getDescription());
htmlElements.addClass('row-patch-description', 'show'); htmlElements.addClass('row-patch-description', 'show');
} else {
htmlElements.setText('patch-description', '');
//htmlElements.setTitle('patch-description', '');
htmlElements.removeClass('row-patch-description', 'show');
}
RomPatcherWeb.validateCurrentRom(_getChecksumStartOffset());
if (typeof settings.onloadpatch === 'function') {
settings.onloadpatch(binFile, embededPatchInfo, parsedPatch);
}
if (transferFakeFile) {
htmlElements.setFakeFile('patch', binFile.fileName);
}
} else { } else {
htmlElements.setText('patch-description', ''); _setToastError(_('Invalid patch file'));
//htmlElements.setTitle('patch-description', '');
htmlElements.removeClass('row-patch-description', 'show');
} }
}catch(ex){
RomPatcherWeb.validateCurrentRom(_getChecksumStartOffset()); _setToastError(ex.message);
if (typeof settings.onloadpatch === 'function') {
settings.onloadpatch(binFile, embededPatchInfo, parsedPatch);
}
if (transferFakeFile) {
htmlElements.setFakeFile('patch', binFile.fileName);
}
} else {
_setToastError(_('Invalid patch file'));
} }
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* BinFile.js (last update: 2024-02-27) * BinFile.js (last update: 2024-08-21)
* by Marc Robledo, https://www.marcrobledo.com * by Marc Robledo, https://www.marcrobledo.com
* *
* a JS class for reading/writing sequentially binary data from/to a file * a JS class for reading/writing sequentially binary data from/to a file
@ -188,7 +188,7 @@ BinFile.prototype.slice = function (offset, len, doNotClone) {
else if (len === 0) else if (len === 0)
throw new Error('zero length provided for slicing'); throw new Error('zero length provided for slicing');
else else
offset = Math.floor(offset); len = Math.floor(len);
if (offset === 0 && len === this.fileSize && doNotClone) if (offset === 0 && len === this.fileSize && doNotClone)
return this; return this;

View file

@ -204,7 +204,6 @@ APS.buildFromRoms=function(original, modified){
}else{ }else{
patch.addRecord(offset, differentBytes); patch.addRecord(offset, differentBytes);
} }
//NO se puede comentar??? why????
} }
} }

View file

@ -1,4 +1,4 @@
/* BPS module for Rom Patcher JS v20240721 - Marc Robledo 2016-2024 - http://www.marcrobledo.com/license */ /* BPS module for Rom Patcher JS v20240821 - Marc Robledo 2016-2024 - http://www.marcrobledo.com/license */
/* File format specification: https://www.romhacking.net/documents/746/ */ /* File format specification: https://www.romhacking.net/documents/746/ */
const BPS_MAGIC='BPS1'; const BPS_MAGIC='BPS1';
@ -26,6 +26,10 @@ BPS.prototype.toString=function(){
s+='\n#Actions: '+this.actions.length; s+='\n#Actions: '+this.actions.length;
return s return s
} }
BPS.prototype.calculateFileChecksum = function () {
var patchFile = this.export();
return patchFile.hashCRC32(0, patchFile.fileSize - 4);
}
BPS.prototype.validateSource=function(romFile,headerSize){return this.sourceChecksum===romFile.hashCRC32(headerSize)} BPS.prototype.validateSource=function(romFile,headerSize){return this.sourceChecksum===romFile.hashCRC32(headerSize)}
BPS.prototype.getValidationInfo=function(){ BPS.prototype.getValidationInfo=function(){
return { return {
@ -121,7 +125,7 @@ BPS.fromFile=function(file){
patch.targetChecksum=file.readU32(); patch.targetChecksum=file.readU32();
patch.patchChecksum=file.readU32(); patch.patchChecksum=file.readU32();
if(patch.patchChecksum!==file.hashCRC32(0, file.fileSize - 4)){ if (patch.patchChecksum !== patch.calculateFileChecksum()) {
throw new Error('Patch checksum mismatch'); throw new Error('Patch checksum mismatch');
} }
@ -238,10 +242,9 @@ BPS.buildFromRoms=function(original, modified, deltaMode){
patch.actions=createBPSFromFilesLinear(original, modified); patch.actions=createBPSFromFilesLinear(original, modified);
} }
var patchFile=patch.export();
patch.sourceChecksum=original.hashCRC32(); patch.sourceChecksum=original.hashCRC32();
patch.targetChecksum=modified.hashCRC32(); patch.targetChecksum=modified.hashCRC32();
patch.patchChecksum=patchFile.hashCRC32(0, patchFile.fileSize - 4); patch.patchChecksum = patch.calculateFileChecksum();
return patch; return patch;
} }

192
test.js
View file

@ -29,8 +29,8 @@
- ROM: New Super Mario Bros. (USA, Australia).nds [CRC32=0197576a] - ROM: New Super Mario Bros. (USA, Australia).nds [CRC32=0197576a]
*/ */
const chalk=require('chalk'); const chalk = require('chalk');
const { existsSync }=require('fs'); const { existsSync } = require('fs');
const BinFile = require('./rom-patcher-js/modules/BinFile'); const BinFile = require('./rom-patcher-js/modules/BinFile');
const HashCalculator = require('./rom-patcher-js/modules/HashCalculator'); const HashCalculator = require('./rom-patcher-js/modules/HashCalculator');
@ -38,68 +38,68 @@ const RomPatcher = require('./rom-patcher-js/RomPatcher');
const TEST_PATH='_test_files/'; const TEST_PATH = '_test_files/';
const TEST_PATCHES=[ const TEST_PATCHES = [
{ {
title:'IPS - Super Mario Land 2 DX', title: 'IPS - Super Mario Land 2 DX',
romFile:'Super Mario Land 2 - 6 Golden Coins (USA, Europe).gb', romFile: 'Super Mario Land 2 - 6 Golden Coins (USA, Europe).gb',
romCrc32:0xd5ec24e4, romCrc32: 0xd5ec24e4,
patchFile:'SML2DXv181.ips', patchFile: 'SML2DXv181.ips',
patchCrc32:0x0b742316, patchCrc32: 0x0b742316,
patchDownload:'https://www.romhacking.net/hacks/3784/', patchDownload: 'https://www.romhacking.net/hacks/3784/',
outputCrc32:0xf0799017 outputCrc32: 0xf0799017
},{ }, {
title:'BPS - Samurai Kid translation', title: 'BPS - Samurai Kid translation',
romFile:'Samurai Kid (Japan).gbc', romFile: 'Samurai Kid (Japan).gbc',
romCrc32:0x44a9ddfb, romCrc32: 0x44a9ddfb,
patchFile:'samurai_kid_en_v1.bps', patchFile: 'samurai_kid_en_v1.bps',
patchCrc32:0x2144df1c, patchCrc32: 0x2144df1c,
patchDownload:'https://www.romhacking.net/translations/6297/', patchDownload: 'https://www.romhacking.net/translations/6297/',
outputCrc32:0xed238edb outputCrc32: 0xed238edb
},{ }, {
title:'UPS - Mother 3 translation', title: 'UPS - Mother 3 translation',
romFile:'Mother 3 (Japan).gba', romFile: 'Mother 3 (Japan).gba',
romCrc32:0x42ac9cb9, romCrc32: 0x42ac9cb9,
patchFile:'mother3.ups', patchFile: 'mother3.ups',
patchCrc32:0x2144df1c, patchCrc32: 0x2144df1c,
patchDownload:'https://mother3.fobby.net/', patchDownload: 'https://mother3.fobby.net/',
outputCrc32:0x8a3bc5a8 outputCrc32: 0x8a3bc5a8
},{ }, {
title:'APS - Zelda OoT spanish translation', title: 'APS - Zelda OoT spanish translation',
romFile:'Legend of Zelda, The - Ocarina of Time (USA).z64', romFile: 'Legend of Zelda, The - Ocarina of Time (USA).z64',
romCrc32:0xcd16c529, romCrc32: 0xcd16c529,
patchFile:'ZELDA64.APS', patchFile: 'ZELDA64.APS',
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:'Tekkaman Blade translation', title: 'Tekkaman Blade translation',
romFile:'Uchuu no Kishi - Tekkaman Blade (Japan).sfc', romFile: 'Uchuu no Kishi - Tekkaman Blade (Japan).sfc',
romCrc32:0x7e107c35, romCrc32: 0x7e107c35,
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
},{ }, {
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,
patchFile:'nsmb_infusion10a.xdelta', patchFile: 'nsmb_infusion10a.xdelta',
patchCrc32:0xa211f97c, patchCrc32: 0xa211f97c,
patchDownload:'https://www.romhacking.net/hacks/2871/', patchDownload: 'https://www.romhacking.net/hacks/2871/',
outputCrc32:0x9cecd976 outputCrc32: 0x9cecd976
} }
]; ];
const _test=function(title, testFunction){ const _test = function (title, testFunction) {
try{ try {
const startTime=(new Date()).getTime(); const startTime = (new Date()).getTime();
const result=testFunction.call(); const result = testFunction.call();
const executionTime=((new Date()).getTime() - startTime) / 1000; const executionTime = ((new Date()).getTime() - startTime) / 1000;
console.log(chalk.greenBright('√ '+title + ' ('+executionTime+'s)')); console.log(chalk.greenBright('√ ' + title + ' (' + executionTime + 's)'));
}catch(err){ } catch (err) {
console.log(chalk.redBright('× '+title + ' - failed with error: '+err.message)); console.log(chalk.redBright('× ' + title + ' - failed with error: ' + err.message));
} }
}; };
@ -111,14 +111,14 @@ const TEST_DATA = (new Uint8Array([
_test('HashCalculator integrity', function(){ _test('HashCalculator integrity', function () {
if(HashCalculator.md5(TEST_DATA) !== '55c76e7e683fd7cd63c673c5df3efa6e') if (HashCalculator.md5(TEST_DATA) !== '55c76e7e683fd7cd63c673c5df3efa6e')
throw new Error('invalid MD5'); throw new Error('invalid MD5');
if(HashCalculator.crc32(TEST_DATA).toString(16) !== '903a031b') if (HashCalculator.crc32(TEST_DATA) !== 0x903a031b)
throw new Error('invalid CRC32'); throw new Error('invalid CRC32');
if(HashCalculator.adler32(TEST_DATA).toString(16) !== 'ef984205') if (HashCalculator.adler32(TEST_DATA) !== 0xef984205)
throw new Error('invalid ADLER32'); throw new Error('invalid ADLER32');
if(HashCalculator.crc16(TEST_DATA).toString(16) !== '96e4') if (HashCalculator.crc16(TEST_DATA) !== 0x96e4)
throw new Error('invalid SHA1'); throw new Error('invalid SHA1');
}); });
@ -126,13 +126,21 @@ _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'].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);
const patch=RomPatcher.createPatch(originalFile, modifiedFile, patchFormat); const patch = RomPatcher.createPatch(originalFile, modifiedFile, patchFormat);
const patchedFile=RomPatcher.applyPatch(originalFile, patch, {requireValidation:true}); const patchedFile = RomPatcher.applyPatch(originalFile, patch, { requireValidation: true });
if(patchedFile.hashCRC32() !== modifiedFile.hashCRC32())
if (patchFormat === 'bps') {
if (patch.patchChecksum !== patch.calculateFileChecksum())
throw new Error('invalid patch checksum');
else if (patch.export().hashCRC32() !== 0x2144df1c)
throw new Error('invalid BPS crc32');
}
if (patchedFile.hashCRC32() !== modifiedFile.hashCRC32())
throw new Error('modified and patched files\' crc32 do not match'); throw new Error('modified and patched files\' crc32 do not match');
}) })
}); });
@ -140,40 +148,40 @@ const MODIFIED_TEST_DATA = (new Uint8Array([
TEST_PATCHES.forEach(function(patchInfo){ 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: ' + patchInfo.patchFile));
console.log(chalk.yellow(' download patch at '+patchInfo.patchDownload)); console.log(chalk.yellow(' download patch at ' + patchInfo.patchDownload));
return false; return false;
} }
const patchFile=new BinFile(patchPath); const patchFile = new BinFile(patchPath);
if(patchFile.hashCRC32() !== patchInfo.patchCrc32){ if (patchFile.hashCRC32() !== patchInfo.patchCrc32) {
console.log(patchFile.hashCRC32().toString(16)); console.log(patchFile.hashCRC32().toString(16));
console.log(chalk.yellow('! skipping '+patchInfo.title+' test: invalid patch crc32')); console.log(chalk.yellow('! skipping ' + patchInfo.title + ' test: invalid patch crc32'));
console.log(chalk.yellow(' download correct patch at '+patchInfo.patchDownload)); console.log(chalk.yellow(' download correct patch at ' + patchInfo.patchDownload));
return false; return false;
} }
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: ' + patchInfo.romFile));
return false; return false;
} }
const romFile=new BinFile(romPath); const romFile = new BinFile(romPath);
if(romFile.hashCRC32() !== patchInfo.romCrc32){ if (romFile.hashCRC32() !== patchInfo.romCrc32) {
console.log(chalk.yellow('! skipping '+patchInfo.title+' test: invalid ROM crc32')); console.log(chalk.yellow('! skipping ' + patchInfo.title + ' test: invalid ROM crc32'));
return false; return false;
} }
_test('patch '+patchInfo.title, function(){ _test('patch ' + patchInfo.title, function () {
const patch=RomPatcher.parsePatchFile(patchFile); const patch = RomPatcher.parsePatchFile(patchFile);
const patchedRom=RomPatcher.applyPatch(romFile, patch, {requireValidation:true}); const patchedRom = RomPatcher.applyPatch(romFile, patch, { requireValidation: true });
if(patchedRom.hashCRC32() !== patchInfo.outputCrc32) if (patchedRom.hashCRC32() !== patchInfo.outputCrc32)
throw new Error('invalid patched file crc32'); throw new Error('invalid patched file crc32');
}); });
}); });