mirror of
https://github.com/marcrobledo/RomPatcher.js.git
synced 2025-07-17 16:38:31 +00:00
added BPS support (apply patch only)
This commit is contained in:
parent
69fcad33bb
commit
3b1b932346
5 changed files with 188 additions and 25 deletions
|
@ -1,4 +1,4 @@
|
|||
/* ips-patcher.js v20170722 - Marc Robledo 2016-2017 - http://www.marcrobledo.com/license */
|
||||
/* RomPatcher.js v20171102 - Marc Robledo 2016-2017 - http://www.marcrobledo.com/license */
|
||||
var MAX_ROM_SIZE=33554432;
|
||||
var romFile, patch, romFile1, romFile2, tempFile, romHashes={};
|
||||
/* Shortcuts */
|
||||
|
@ -54,10 +54,12 @@ function _readPatchFile(){
|
|||
patch=readUPSFile(tempFile);
|
||||
}else if(tempFile.readString(0,5)===APS_MAGIC){
|
||||
patch=readAPSFile(tempFile);
|
||||
}else if(tempFile.readString(0,4)===BPS_MAGIC){
|
||||
patch=readBPSFile(tempFile);
|
||||
}/*else if(tempFile.readString(0,4)===APSGBA_MAGIC){
|
||||
patch=readAPSGBAFile(tempFile);
|
||||
}*/else {
|
||||
MarcDialogs.alert('Invalid IPS/UPS/APS file');
|
||||
MarcDialogs.alert('Invalid IPS/UPS/APS/BPS file');
|
||||
}
|
||||
}
|
||||
function openPatchFile(f){tempFile=new MarcBinFile(f, _readPatchFile)}
|
||||
|
@ -74,7 +76,7 @@ function applyPatchFile(p,r){
|
|||
|
||||
|
||||
function createPatchFile(){
|
||||
var MODES=['ips','ups','aps','apsn64'/*,'apsgba'*/];
|
||||
var MODES=['ips','ups','aps','apsn64'/*,'apsgba','bps'*/];
|
||||
var mode=0;
|
||||
for(var i=0; i<MODES.length && !mode; i++)
|
||||
if(el('radio-'+MODES[i]).checked)
|
||||
|
@ -100,6 +102,8 @@ function createPatchFile(){
|
|||
newPatch=createAPSFromFiles(romFile1, romFile2, true);
|
||||
}else if(mode==='apsgba'){
|
||||
newPatch=createAPSGBAFromFiles(romFile1, romFile2);
|
||||
}else if(mode==='bps'){
|
||||
newPatch=createBPSFromFiles(romFile1, romFile2);
|
||||
}
|
||||
newPatch.export().save();
|
||||
}
|
||||
|
|
172
bps.js
Normal file
172
bps.js
Normal file
|
@ -0,0 +1,172 @@
|
|||
/* BPS module for RomPatcher.js v20171103 - Marc Robledo 2016-2017 - http://www.marcrobledo.com/license */
|
||||
/* File format specification: https://www.romhacking.net/documents/746/ */
|
||||
|
||||
var BPS_MAGIC='BPS1';
|
||||
var BPS_ACTION_SOURCE_READ=0;
|
||||
var BPS_ACTION_TARGET_READ=1;
|
||||
var BPS_ACTION_SOURCE_COPY=2;
|
||||
var BPS_ACTION_TARGET_COPY=3;
|
||||
|
||||
|
||||
function BPS(){
|
||||
this.sourceSize=0;
|
||||
this.targetSize=0;
|
||||
this.metaData='';
|
||||
this.actionsOffset=0;
|
||||
this.file=null;
|
||||
this.sourceChecksum=0;
|
||||
this.targetChecksum=0;
|
||||
this.patchChecksum=0;
|
||||
}
|
||||
BPS.prototype.toString=function(){
|
||||
var s='Source size: '+this.sourceSize;
|
||||
s+='\Target size: '+this.targetSize;
|
||||
s+='\nMetadata: '+this.metaData;
|
||||
s+='\nActions offset: '+this.actionsOffset;
|
||||
return s
|
||||
}
|
||||
/*BPS.prototype.export=function(){
|
||||
|
||||
}*/
|
||||
BPS.prototype.apply=function(romFile){
|
||||
if(this.sourceChecksum!==crc32(romFile,false)){
|
||||
MarcDialogs.alert('Warning: invalid source ROM checksum');
|
||||
}
|
||||
|
||||
|
||||
// first we determine target file size
|
||||
var newFileSize=0;
|
||||
var seek=this.actionsOffset;
|
||||
while(seek<(this.file.fileSize-12)){
|
||||
var data=decodeBPS(this.file, seek);
|
||||
var action={type: data.number & 3, length: (data.number >> 2)+1};
|
||||
seek+=data.length;
|
||||
|
||||
newFileSize+=action.length;
|
||||
if(action.type===BPS_ACTION_TARGET_READ){
|
||||
seek+=action.length;
|
||||
}else if(action.type===BPS_ACTION_SOURCE_COPY || action.type===BPS_ACTION_TARGET_COPY){
|
||||
seek+=decodeBPS(this.file, seek).length;
|
||||
}
|
||||
}
|
||||
tempFile=new MarcBinFile(newFileSize);
|
||||
|
||||
|
||||
//patch
|
||||
var outputOffset=0;
|
||||
var sourceRelativeOffset=0;
|
||||
var targetRelativeOffset=0;
|
||||
seek=this.actionsOffset;
|
||||
while(seek<(this.file.fileSize-12)){
|
||||
var data=decodeBPS(this.file, seek);
|
||||
var action={type: data.number & 3, length: (data.number >> 2)+1};
|
||||
//console.log('0x'+seek.toString(16)+' - action: '+action.type+':'+action.length);
|
||||
seek+=data.length;
|
||||
|
||||
if(action.type===BPS_ACTION_SOURCE_READ){
|
||||
tempFile.writeBytes(outputOffset, romFile.readBytes(outputOffset, action.length));
|
||||
outputOffset+=action.length;
|
||||
|
||||
}else if(action.type===BPS_ACTION_TARGET_READ){
|
||||
tempFile.writeBytes(outputOffset, this.file.readBytes(seek, action.length));
|
||||
outputOffset+=action.length;
|
||||
seek+=action.length;
|
||||
|
||||
}else if(action.type===BPS_ACTION_SOURCE_COPY){
|
||||
var data2=decodeBPS(this.file, seek);
|
||||
seek+=data2.length;
|
||||
sourceRelativeOffset+=(data2.number & 1 ? -1 : +1) * (data2.number >> 1);
|
||||
while(action.length--){
|
||||
tempFile.writeByte(outputOffset, romFile.readByte(sourceRelativeOffset));
|
||||
outputOffset++;
|
||||
sourceRelativeOffset++;
|
||||
}
|
||||
}else if(action.type===BPS_ACTION_TARGET_COPY){
|
||||
var data2=decodeBPS(this.file, seek);
|
||||
seek+=data2.length;
|
||||
targetRelativeOffset += (data2.number & 1 ? -1 : +1) * (data2.number >> 1);
|
||||
while(action.length--) {
|
||||
tempFile.writeByte(outputOffset, tempFile.readByte(targetRelativeOffset));
|
||||
outputOffset++;
|
||||
targetRelativeOffset++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(this.targetChecksum!==crc32(tempFile,false)){
|
||||
MarcDialogs.alert('Warning: invalid target ROM checksum');
|
||||
}
|
||||
|
||||
return tempFile
|
||||
}
|
||||
|
||||
|
||||
|
||||
function readBPSFile(file){
|
||||
file.littleEndian=true;
|
||||
var patchFile=new BPS();
|
||||
|
||||
var seek=4; //skip BPS1
|
||||
var decodedSourceSize=decodeBPS(file, seek);
|
||||
patchFile.sourceSize=decodedSourceSize.number;
|
||||
seek+=decodedSourceSize.length;
|
||||
var decodedTargetSize=decodeBPS(file, seek);
|
||||
patchFile.targetSize=decodedTargetSize.number;
|
||||
seek+=decodedTargetSize.length;
|
||||
|
||||
var decodedMetaDataLength=decodeBPS(file, seek);
|
||||
seek+=decodedMetaDataLength.length;
|
||||
patchFile.metaData=file.readString(seek, decodedMetaDataLength.length);
|
||||
seek+=patchFile.metaData.length;
|
||||
|
||||
patchFile.actionsOffset=seek;
|
||||
patchFile.file=file;
|
||||
|
||||
patchFile.sourceChecksum=file.readInt(file.fileSize-12);
|
||||
patchFile.targetChecksum=file.readInt(file.fileSize-8);
|
||||
patchFile.patchChecksum=file.readInt(file.fileSize-4);
|
||||
|
||||
if(patchFile.patchChecksum!==crc32(file,true)){
|
||||
MarcDialogs.alert('Warning: invalid patch checksum');
|
||||
}
|
||||
|
||||
|
||||
return patchFile;
|
||||
}
|
||||
|
||||
|
||||
/*function createBPSFromFiles(original, modified){
|
||||
|
||||
}*/
|
||||
|
||||
|
||||
/*function encodeBPS(number){
|
||||
number=number>>>0;
|
||||
var dataBytes=[];
|
||||
while(true){
|
||||
var x = number & 0x7f;
|
||||
number >>= 7;
|
||||
if(number == 0){
|
||||
dataBytes.push(0x80 | x);
|
||||
break;
|
||||
}
|
||||
dataBytes.push(x);
|
||||
number--;
|
||||
}
|
||||
return dataBytes;
|
||||
}*/
|
||||
function decodeBPS(dataBytes, i){
|
||||
var number = 0, shift = 1;
|
||||
var len=0;
|
||||
while(true){
|
||||
var x = dataBytes.readByte(i);
|
||||
i++;
|
||||
len++;
|
||||
number += (x & 0x7f) * shift;
|
||||
if(x & 0x80)
|
||||
break;
|
||||
shift <<= 7;
|
||||
number += shift;
|
||||
}
|
||||
return {number:number,length:len};
|
||||
}
|
11
index.html
11
index.html
|
@ -12,6 +12,8 @@
|
|||
<script type="text/javascript" src="./ips.js"></script>
|
||||
<script type="text/javascript" src="./ups.js"></script>
|
||||
<script type="text/javascript" src="./aps.js"></script>
|
||||
<!-- <script type="text/javascript" src="./apsgba.js"></script> -->
|
||||
<script type="text/javascript" src="./bps.js"></script>
|
||||
<script type="text/javascript" src="./ByteFlipper.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -35,7 +37,7 @@
|
|||
<!-- APP -->
|
||||
<div class="wrapper" id="the-app">
|
||||
<h3 class="red">Apply patch</h3>
|
||||
<div class="container-description">Apply an IPS/UPS patch to your ROM</div>
|
||||
<div class="container-description">Apply a patch to your ROM</div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="six columns text-right"><label for="input-file-rom">ROM file:</label></div>
|
||||
|
@ -46,7 +48,7 @@
|
|||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="six columns text-right"><label for="input-file-patch">Patch file (IPS/UPS/APS):</label></div>
|
||||
<div class="six columns text-right"><label for="input-file-patch">Patch file <small>(IPS/UPS/APS/BPS)</small>:</label></div>
|
||||
<div class="six columns">
|
||||
<input type="file" id="input-file-patch" />
|
||||
</div>
|
||||
|
@ -60,7 +62,7 @@
|
|||
|
||||
|
||||
<h3 class="blue">Create patch</h3>
|
||||
<div class="container-description">Create an IPS/UPS/APS patch from two different ROMs </div>
|
||||
<div class="container-description">Create a patch from two different ROMs </div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="six columns text-right"><label for="input-file-rom1">Original ROM:</label></div>
|
||||
|
@ -83,6 +85,7 @@
|
|||
<input type="radio" id="radio-ups" name="patch-type" /><label for="radio-ups">UPS</label>
|
||||
<input type="radio" id="radio-aps" name="patch-type" /><label for="radio-aps">APS</label>
|
||||
<input type="radio" id="radio-apsn64" name="patch-type" /><label for="radio-apsn64">APS (N64)</label>
|
||||
<!-- <input type="radio" id="radio-bps" name="patch-type" /><label for="radio-bps">BPS</label> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -94,7 +97,7 @@
|
|||
|
||||
|
||||
<h3 class="green">Byte flipper</h3>
|
||||
<div class="container-description">This tool can flip bytes on a file in order to change its endianness</div>
|
||||
<div class="container-description">This tool flips bytes in a file in order to change its endianness</div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="six columns text-right"><label for="input-file-flip">File</label></div>
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
CACHE MANIFEST
|
||||
#v20170723
|
||||
# WARNING: THIS FILE WILL BE DEPRECATED
|
||||
#CACHE:
|
||||
index.html
|
||||
RomPatcher.css
|
||||
RomPatcher.js
|
||||
favicon.png
|
||||
logo.png
|
||||
ips.js
|
||||
ups.js
|
||||
aps.js
|
||||
ByteFlipper.js
|
||||
|
||||
# force these files to be loaded in network
|
||||
NETWORK:
|
||||
*
|
|
@ -1,5 +1,5 @@
|
|||
CACHE MANIFEST
|
||||
#v20171021
|
||||
#v20171103
|
||||
#CACHE:
|
||||
index.html
|
||||
RomPatcher.css
|
||||
|
@ -9,6 +9,7 @@ logo.png
|
|||
ips.js
|
||||
ups.js
|
||||
aps.js
|
||||
bps.js
|
||||
ByteFlipper.js
|
||||
|
||||
# force these files to be loaded in network
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue