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

- feat (web): dynamic JS modules loading

- feat (web): added onloadpatch event
- fix (cli): fixed path for JS files
This commit is contained in:
Marc Robledo 2024-08-11 21:30:25 +02:00
parent bc82f6d748
commit de2f0e5c7d
9 changed files with 315 additions and 210 deletions

View file

@ -31,14 +31,29 @@
/*
to-do list:
- load JS modules dynamically when RomPatchwerWeb is initialized
- allow multiple instances of RomPatcherWeb
- allow multiple instances of RomPatcherWeb?
- switch to ES6 classes and modules?
*/
const ROM_PATCHER_JS_PATH = './rom-patcher-js/';
var RomPatcherWeb = (function () {
const SCRIPT_DEPENDENCIES = [
'modules/BinFile.js',
'modules/HashCalculator.js',
'modules/RomPatcher.format.ips.js',
'modules/RomPatcher.format.ups.js',
'modules/RomPatcher.format.aps_n64.js',
'modules/RomPatcher.format.aps_gba.js',
'modules/RomPatcher.format.bps.js',
'modules/RomPatcher.format.rup.js',
'modules/RomPatcher.format.ppf.js',
'modules/RomPatcher.format.pmsr.js',
'modules/RomPatcher.format.vcdiff.js',
'modules/zip.js/zip.min.js',
'RomPatcher.js'
];
const WEB_CRYPTO_AVAILABLE = window.crypto && window.crypto.subtle && window.crypto.subtle.digest;
const settings = {
language: typeof navigator.language === 'string' ? navigator.language.substring(0, 2) : 'en',
@ -49,6 +64,7 @@ var RomPatcherWeb = (function () {
onloadrom: null,
onvalidaterom: null,
onloadpatch: null,
onpatch: null
};
var romFile, patch;
@ -384,10 +400,6 @@ var RomPatcherWeb = (function () {
webWorkerCrc.onerror = event => { // listen for events from the worker
_setToastError('webWorkerCrc error: ' + event.message);
};
/* zip-js web worker */
zip.useWebWorkers = true;
zip.workerScriptsPath = ROM_PATCHER_JS_PATH + 'modules/zip.js/';
const _getChecksumStartOffset = function () {
if (romFile) {
@ -402,12 +414,177 @@ var RomPatcherWeb = (function () {
}
const _getScriptPath = function () {
const currentScripts = document.querySelectorAll('script');
var scriptPath;
if (document.currentScript) {
scriptPath = document.currentScript.src;
} else {
for (var i = 0; i < currentScripts.length; i++) {
if (currentScripts[i].src.indexOf('RomPatcher.webapp.js') !== -1) {
scriptPath = currentScripts[i].src;
break;
}
}
if (!scriptPath)
scriptPath = './rom-patcher-js/';
}
return scriptPath.substring(0, scriptPath.lastIndexOf('/') + 1);
}
const _getMissingDependencies = function () {
const currentScripts = document.querySelectorAll('script');
const scriptPath = _getScriptPath();
var missingDependencies = [];
for (var i = 0; i < SCRIPT_DEPENDENCIES.length && !isLoaded; i++) {
var isLoaded = false;
for (var j = 0; j < currentScripts.length; j++) {
if (currentScripts[j].src === scriptPath + SCRIPT_DEPENDENCIES[i])
isLoaded = true;
}
if (!isLoaded)
missingDependencies.push(scriptPath + SCRIPT_DEPENDENCIES[i]);
}
return missingDependencies;
}
const _initialize = function (newSettings, embededPatchInfo) {
/* embeded patches */
var validEmbededPatch = false;
if (embededPatchInfo) {
if (typeof embededPatchInfo === 'string')
embededPatchInfo = { file: embededPatchInfo };
if (typeof embededPatchInfo === 'object') {
if (typeof embededPatchInfo.file === 'string') {
validEmbededPatch = true;
} else {
throw new Error('Rom Patcher JS: invalid embeded patch file');
}
}
}
/* check if Rom Patcher JS core is available */
if (typeof RomPatcher !== 'object') {
throw new Error('Rom Patcher JS: core not found');
}
/* check if zip-js web worker is available */
if (typeof zip !== 'object' || typeof zip.useWebWorkers !== 'boolean') {
throw new Error('Rom Patcher JS: zip.js web worker not found');
}
zip.useWebWorkers = true;
zip.workerScriptsPath = ROM_PATCHER_JS_PATH + 'modules/zip.js/';
/* check if all required HTML elements are in DOM */
const htmlInputFileRom = htmlElements.get('input-file-rom');
if (htmlInputFileRom && htmlInputFileRom.tagName === 'INPUT' && htmlInputFileRom.type === 'file') {
htmlInputFileRom.addEventListener('change', function (evt) {
htmlElements.disableAll();
new BinFile(this, RomPatcherWeb.provideRomFile);
});
} else {
throw new Error('Rom Patcher JS: input#rom-patcher-input-file-rom[type=file] not found');
}
const htmlInputFilePatch = htmlElements.get('input-file-patch');
if (htmlInputFilePatch && htmlInputFilePatch.tagName === 'INPUT' && htmlInputFilePatch.type === 'file') {
htmlInputFilePatch.addEventListener('change', function (evt) {
htmlElements.disableAll();
new BinFile(this, RomPatcherWeb.providePatchFile);
});
} else {
throw new Error('Rom Patcher JS: input#rom-patcher-input-file-patch[type=file] not found');
}
const htmlButtonApply = htmlElements.get('button-apply');
if (htmlButtonApply && htmlButtonApply.tagName === 'BUTTON') {
htmlButtonApply.addEventListener('click', RomPatcherWeb.applyPatch);
} else {
throw new Error('Rom Patcher JS: button#rom-patcher-button-apply not found');
}
const htmlCheckboxAlterHeader = htmlElements.get('checkbox-alter-header');
if (htmlCheckboxAlterHeader && htmlCheckboxAlterHeader.tagName === 'INPUT' && htmlCheckboxAlterHeader.type === 'checkbox') {
htmlCheckboxAlterHeader.addEventListener('change', function (evt) {
if (!romFile)
return false;
const headerInfo = RomPatcher.isRomHeadered(romFile);
if (headerInfo) {
htmlElements.disableAll();
webWorkerCrc.postMessage({ u8array: romFile._u8array, fileName: romFile.fileName, checksumStartOffset: _getChecksumStartOffset() }, [romFile._u8array.buffer]);
}
});
}
/* set all default input status just in case HTML is wrong */
htmlElements.disableAll();
/* reset input files */
htmlElements.setValue('input-file-rom', '');
htmlElements.setValue('input-file-patch', '');
/* translatable elements */
const translatableElements = document.querySelectorAll('*[data-localize="yes"]');
for (var i = 0; i < translatableElements.length; i++) {
translatableElements[i].setAttribute('data-localize', translatableElements[i].innerHTML);
}
/* add drag and drop events */
if (newSettings && newSettings.allowDropFiles) {
window.addEventListener('dragover', function (evt) {
if (_dragEventContainsFiles(evt))
evt.preventDefault(); /* needed ! */
});
window.addEventListener('drop', function (evt) {
evt.preventDefault();
if (_dragEventContainsFiles(evt)) {
const droppedFiles = evt.dataTransfer.files;
if (droppedFiles && droppedFiles.length === 1) {
new BinFile(droppedFiles[0], function (binFile) {
if (RomPatcherWeb.getEmbededPatches()) {
RomPatcherWeb.provideRomFile(binFile, true);
} else if (ZIPManager.isZipFile(binFile)) {
ZIPManager.unzipAny(binFile._u8array.buffer);
} else if (RomPatcher.parsePatchFile(binFile)) {
RomPatcherWeb.providePatchFile(binFile, null, true);
} else {
RomPatcherWeb.provideRomFile(binFile, true);
}
});
}
}
});
htmlInputFileRom.addEventListener('drop', function (evt) {
evt.stopPropagation();
});
htmlInputFilePatch.addEventListener('drop', function (evt) {
evt.stopPropagation();
});
}
console.log('Rom Patcher JS initialized');
initialized = true;
/* initialize Rom Patcher */
RomPatcherWeb.setSettings(newSettings);
/* download embeded patch */
if (validEmbededPatch)
_fetchPatchFile(embededPatchInfo);
else
htmlElements.enableAll();
}
/* localization */
const _ = function (str) { return ROM_PATCHER_LOCALE[settings.language] && ROM_PATCHER_LOCALE[settings.language][str] ? ROM_PATCHER_LOCALE[settings.language][str] : str };
var initialized = false;
var loading = 0;
return {
_: function (str) { /* public localization function for external usage purposes */
return _(str);
@ -562,10 +739,14 @@ var RomPatcherWeb = (function () {
RomPatcherWeb.validateCurrentRom(_getChecksumStartOffset());
if (typeof settings.onloadpatch === 'function') {
settings.onloadpatch(binFile, embededPatchInfo, parsedPatch);
}
if (transferFakeFile) {
htmlElements.setFakeFile('input-file-patch', binFile.fileName);
}
}else{
} else {
_setToastError(_('Invalid patch file'));
}
}
@ -606,21 +787,9 @@ var RomPatcherWeb = (function () {
initialize: function (newSettings, embededPatchInfo) {
if (initialized)
throw new Error('Rom Patcher JS was already initialized');
else if (loading)
throw new Error('Rom Patcher JS is already loading or has failed to load');
/* embeded patches */
var validEmbededPatch = false;
if (embededPatchInfo) {
if (typeof embededPatchInfo === 'string')
embededPatchInfo = { file: embededPatchInfo };
if (typeof embededPatchInfo === 'object') {
if (typeof embededPatchInfo.file === 'string') {
validEmbededPatch = true;
} else {
throw new Error('Rom Patcher JS: invalid embeded patch file');
}
}
}
/* check incompatible browsers */
if (
@ -633,101 +802,32 @@ var RomPatcherWeb = (function () {
throw new Error('Rom Patcher JS: incompatible browser');
/* check if all required HTML elements are in DOM */
const htmlInputFileRom = htmlElements.get('input-file-rom');
if (htmlInputFileRom && htmlInputFileRom.tagName === 'INPUT' && htmlInputFileRom.type === 'file') {
htmlInputFileRom.addEventListener('change', function (evt) {
htmlElements.disableAll();
new BinFile(this, RomPatcherWeb.provideRomFile);
});
} else {
throw new Error('Rom Patcher JS: input#rom-patcher-input-file-rom[type=file] not found');
}
const htmlInputFilePatch = htmlElements.get('input-file-patch');
if (htmlInputFilePatch && htmlInputFilePatch.tagName === 'INPUT' && htmlInputFilePatch.type === 'file') {
htmlInputFilePatch.addEventListener('change', function (evt) {
htmlElements.disableAll();
new BinFile(this, RomPatcherWeb.providePatchFile);
});
} else {
throw new Error('Rom Patcher JS: input#rom-patcher-input-file-patch[type=file] not found');
}
const htmlButtonApply = htmlElements.get('button-apply');
if (htmlButtonApply && htmlButtonApply.tagName === 'BUTTON') {
htmlButtonApply.addEventListener('click', RomPatcherWeb.applyPatch);
} else {
throw new Error('Rom Patcher JS: button#rom-patcher-button-apply not found');
}
const htmlCheckboxAlterHeader = htmlElements.get('checkbox-alter-header');
if (htmlCheckboxAlterHeader && htmlCheckboxAlterHeader.tagName === 'INPUT' && htmlCheckboxAlterHeader.type === 'checkbox') {
htmlCheckboxAlterHeader.addEventListener('change', function (evt) {
if (!romFile)
return false;
const headerInfo = RomPatcher.isRomHeadered(romFile);
if (headerInfo) {
/* queue script dependencies */
const missingDependencies = _getMissingDependencies();
loading = missingDependencies.length;
const onLoadScript = function () {
loading--;
if (loading === 0) {
try {
_initialize(newSettings, embededPatchInfo);
} catch (ex) {
_setToastError(ex.message);
htmlElements.disableAll();
webWorkerCrc.postMessage({ u8array: romFile._u8array, fileName: romFile.fileName, checksumStartOffset: _getChecksumStartOffset() }, [romFile._u8array.buffer]);
}
});
}
/* set all default input status just in case HTML is wrong */
htmlElements.setEnabled('button-apply', false);
/* reset input files */
htmlElements.setValue('input-file-rom', '');
htmlElements.setValue('input-file-patch', '');
}
};
const onErrorScript = function () {
throw new Error('Rom Patcher JS: error loading script ' + script.src);
};
console.log('Rom Patcher JS: loading ' + missingDependencies.length + ' dependencies');
missingDependencies.forEach(function (path) {
var script = document.createElement('script');
script.onload = onLoadScript;
script.onerror = onErrorScript;
script.src = path;
/* translatable elements */
const translatableElements = document.querySelectorAll('*[data-localize="yes"]');
for (var i = 0; i < translatableElements.length; i++) {
translatableElements[i].setAttribute('data-localize', translatableElements[i].innerHTML);
}
/* add drag and drop events */
if (newSettings && newSettings.allowDropFiles) {
window.addEventListener('dragover', function (evt) {
if (_dragEventContainsFiles(evt))
evt.preventDefault(); /* needed ! */
});
window.addEventListener('drop', function (evt) {
evt.preventDefault();
if (_dragEventContainsFiles(evt)) {
const droppedFiles = evt.dataTransfer.files;
if (droppedFiles && droppedFiles.length === 1) {
new BinFile(droppedFiles[0], function (binFile) {
if (RomPatcherWeb.getEmbededPatches()) {
RomPatcherWeb.provideRomFile(binFile, true);
} else if (ZIPManager.isZipFile(binFile)) {
ZIPManager.unzipAny(binFile._u8array.buffer);
} else if (RomPatcher.parsePatchFile(binFile)) {
RomPatcherWeb.providePatchFile(binFile, null, true);
} else {
RomPatcherWeb.provideRomFile(binFile, true);
}
});
}
}
});
htmlInputFileRom.addEventListener('drop', function (evt) {
evt.stopPropagation();
});
htmlInputFilePatch.addEventListener('drop', function (evt) {
evt.stopPropagation();
});
}
console.log('Rom Patcher JS initialized');
initialized = true;
/* initialize Rom Patcher */
RomPatcherWeb.setSettings(newSettings);
/* download embeded patch */
if (validEmbededPatch)
_fetchPatchFile(embededPatchInfo);
document.head.appendChild(script);
});
},
applyPatch: function () {
@ -859,6 +959,11 @@ var RomPatcherWeb = (function () {
else if (typeof newSettings.onvalidaterom !== 'undefined')
settings.onvalidaterom = null;
if (typeof newSettings.onloadpatch === 'function')
settings.onloadpatch = newSettings.onloadpatch;
else if (typeof newSettings.onloadpatch !== 'undefined')
settings.onloadpatch = null;
if (typeof newSettings.onpatch === 'function')
settings.onpatch = newSettings.onpatch;
else if (typeof newSettings.onpatch !== 'undefined')
@ -935,11 +1040,11 @@ const ZIPManager = (function (romPatcherWeb) {
const _unzipEntry = function (zippedEntry, onUnzip) {
htmlElements.disableAll();
if (onUnzip === RomPatcherWeb.provideRomFile) {
if (onUnzip === romPatcherWeb.provideRomFile) {
_setRomInputSpinner(true);
} else if (onUnzip === RomPatcherWeb.providePatchFile) {
} else if (onUnzip === romPatcherWeb.providePatchFile) {
_setPatchInputSpinner(true);
}else{
} else {
throw new Error('ZIPManager._unzipEntry: invalid onUnzip callback');
}
zippedEntry.getData(new zip.BlobWriter(), function (blob) {
@ -949,7 +1054,7 @@ const ZIPManager = (function (romPatcherWeb) {
binFile.fileName = zippedEntry.filename;
/* transfer files to input elements */
if (onUnzip === RomPatcherWeb.provideRomFile) {
if (onUnzip === romPatcherWeb.provideRomFile) {
_setRomInputSpinner(false);
onUnzip(binFile, true);
} else {
@ -963,19 +1068,19 @@ const ZIPManager = (function (romPatcherWeb) {
const _showFilePicker = function (zipEntries, onUnzip) {
const _evtClickEntry = function (evt) {
if(typeof dialogZip.close === 'function'){
if (typeof dialogZip.close === 'function') {
dialogZip.close();
}else{
document.getElementById(DIALOG_BACKDROP_FALLBACK_ID).style.display='none';
} else {
document.getElementById(DIALOG_BACKDROP_FALLBACK_ID).style.display = 'none';
}
_unzipEntry(this.zipEntry, onUnzip);
}
if (onUnzip === RomPatcherWeb.provideRomFile) {
if (onUnzip === romPatcherWeb.provideRomFile) {
dialogZipMessage.innerHTML = _('ROM file:');
} else if (onUnzip === RomPatcherWeb.providePatchFile) {
} else if (onUnzip === romPatcherWeb.providePatchFile) {
dialogZipMessage.innerHTML = _('Patch file:');
}else{
} else {
throw new Error('ZIPManager._unzipEntry: invalid onUnzip callback');
}
@ -990,14 +1095,14 @@ const ZIPManager = (function (romPatcherWeb) {
}
if(typeof dialogZip.showModal === 'function'){
if (typeof dialogZip.showModal === 'function') {
if (!document.getElementById(dialogZip.id))
document.body.appendChild(dialogZip);
dialogZip.showModal();
}else{
} else {
/* fallback for incompatible browsers */
if (!document.getElementById(DIALOG_BACKDROP_FALLBACK_ID)){
if (!document.getElementById(DIALOG_BACKDROP_FALLBACK_ID)) {
const dialogBackdrop = document.createElement('div');
dialogBackdrop.id = DIALOG_BACKDROP_FALLBACK_ID;
dialogBackdrop.className = 'rom-patcher-dialog-backdrop';
@ -1014,16 +1119,16 @@ const ZIPManager = (function (romPatcherWeb) {
document.body.appendChild(dialogBackdrop);
}
document.getElementById(DIALOG_BACKDROP_FALLBACK_ID).style.display='flex';
dialogZip.style.display='block';
document.getElementById(DIALOG_BACKDROP_FALLBACK_ID).style.display = 'flex';
dialogZip.style.display = 'block';
}
}
const _unzipError = function (zipReader) {
if (zipReader.message)
console.error('zip.js: ' + zipReader.message);
RomPatcherWeb.enable();
RomPatcherWeb.setErrorMessage(_('Error unzipping file'), 'error');
romPatcherWeb.enable();
romPatcherWeb.setErrorMessage(_('Error unzipping file'), 'error');
};
@ -1042,13 +1147,13 @@ const ZIPManager = (function (romPatcherWeb) {
const filteredEntries = _filterEntriesRoms(zipEntries);
if (filteredEntries.length === 1) {
_unzipEntry(filteredEntries[0], RomPatcherWeb.provideRomFile);
_unzipEntry(filteredEntries[0], romPatcherWeb.provideRomFile);
} else if (filteredEntries.length > 1) {
_showFilePicker(filteredEntries, RomPatcherWeb.provideRomFile);
RomPatcherWeb.enable();
_showFilePicker(filteredEntries, romPatcherWeb.provideRomFile);
romPatcherWeb.enable();
} else {
/* no possible patchable files found in zip, treat zip file as ROM file */
RomPatcherWeb.calculateCurrentRomChecksums();
romPatcherWeb.calculateCurrentRomChecksums();
}
});
},
@ -1066,11 +1171,11 @@ const ZIPManager = (function (romPatcherWeb) {
const filteredEntries = _filterEntriesPatches(zipEntries);
if (filteredEntries.length === 1) {
_unzipEntry(filteredEntries[0], RomPatcherWeb.providePatchFile);
_unzipEntry(filteredEntries[0], romPatcherWeb.providePatchFile);
} else if (filteredEntries.length > 1) {
_showFilePicker(filteredEntries, RomPatcherWeb.providePatchFile);
_showFilePicker(filteredEntries, romPatcherWeb.providePatchFile);
} else {
RomPatcherWeb.providePatchFile(null);
romPatcherWeb.providePatchFile(null);
}
});
@ -1091,16 +1196,16 @@ const ZIPManager = (function (romPatcherWeb) {
if (filteredEntriesRoms.length && filteredEntriesPatches.length === 0) {
if (filteredEntriesRoms.length === 1) {
_unzipEntry(filteredEntriesRoms[0], RomPatcherWeb.provideRomFile);
_unzipEntry(filteredEntriesRoms[0], romPatcherWeb.provideRomFile);
} else {
_showFilePicker(filteredEntriesRoms, RomPatcherWeb.provideRomFile);
RomPatcherWeb.enable();
_showFilePicker(filteredEntriesRoms, romPatcherWeb.provideRomFile);
romPatcherWeb.enable();
}
} else if (filteredEntriesPatches.length && filteredEntriesRoms.length === 0) {
if (filteredEntriesPatches.length === 1) {
_unzipEntry(filteredEntriesPatches[0], RomPatcherWeb.providePatchFile);
_unzipEntry(filteredEntriesPatches[0], romPatcherWeb.providePatchFile);
} else {
_showFilePicker(filteredEntriesPatches, RomPatcherWeb.providePatchFile);
_showFilePicker(filteredEntriesPatches, romPatcherWeb.providePatchFile);
}
} else {
console.warn('ZIPManager.unzipAny: zip file contains both ROMs and patches, cannot guess');
@ -1149,7 +1254,7 @@ const ZIPManager = (function (romPatcherWeb) {
select.addEventListener('change', function (evt) {
const fileIndex = parseInt(this.value);
_unzipEntry(filteredEntries[fileIndex], RomPatcherWeb.providePatchFile);
_unzipEntry(filteredEntries[fileIndex], romPatcherWeb.providePatchFile);
});
} else {
throw new Error('rom-patcher-select-file-patch not found');
@ -1157,10 +1262,10 @@ const ZIPManager = (function (romPatcherWeb) {
}
//_setPatchInputSpinner(false);
_unzipEntry(filteredEntries[0], RomPatcherWeb.providePatchFile);
_unzipEntry(filteredEntries[0], romPatcherWeb.providePatchFile);
} else {
RomPatcherWeb.setErrorMessage(_('No valid patches found in ZIP'), 'error');
RomPatcherWeb.disable();
romPatcherWeb.setErrorMessage(_('No valid patches found in ZIP'), 'error');
romPatcherWeb.disable();
}
});
},
@ -1250,7 +1355,7 @@ const PatchBuilderWeb = (function (romPatcherWeb) {
};
var initialized = false;
return{
return {
isInitialized: function () {
return initialized;
},
@ -1258,17 +1363,21 @@ const PatchBuilderWeb = (function (romPatcherWeb) {
initialize: function () {
if (initialized)
throw new Error('Patch Builder JS was already initialized');
else if (!romPatcherWeb.isInitialized())
throw new Error('Rom Patcher JS must be initialized before Patch Builder JS');
document.getElementById('patch-builder-button-create').disabled = true;
document.getElementById('patch-builder-input-file-original').addEventListener('change', function () {
_setElementsStatus(false);
this.classList.remove('empty');
originalRom = new BinFile(this.files[0], function (evt) {
_setElementsStatus(true);
if (RomPatcher.isRomTooBig(originalRom))
_setToastError(_('Using big files is not recommended'), 'warning');
else if (ZIPManager.isZipFile(originalRom))
_setToastError(_('Patch creation is not compatible with zipped ROMs'), 'warning');
});
});
document.getElementById('patch-builder-input-file-modified').addEventListener('change', function () {
@ -1276,9 +1385,11 @@ const PatchBuilderWeb = (function (romPatcherWeb) {
this.classList.remove('empty');
modifiedRom = new BinFile(this.files[0], function (evt) {
_setElementsStatus(true);
if (RomPatcher.isRomTooBig(modifiedRom))
_setToastError(_('Using big files is not recommended'), 'warning');
else if (ZIPManager.isZipFile(modifiedRom))
_setToastError(_('Patch creation is not compatible with zipped ROMs'), 'warning');
});
});
document.getElementById('patch-builder-button-create').addEventListener('click', function () {
@ -1298,6 +1409,7 @@ const PatchBuilderWeb = (function (romPatcherWeb) {
console.log('Patch Builder JS initialized');
initialized = true;
_setElementsStatus(true);
}
}
}(RomPatcherWeb));

View file

@ -184,14 +184,19 @@ VCDIFF.fromFile=function(file){
function VCDIFF_Parser(binFile, offset)
{
BinFile.call(this, 0);
this.fileSize=binFile.fileSize;
this._u8array=binFile._u8array;
this._dataView=binFile._dataView;
this.offset=offset || 0;
}
VCDIFF_Parser.prototype=Object.create(BinFile.prototype);
/* reimplement readU8, readU32 and skip from BinFile */
/* in web implementation, there are no guarantees BinFile will be dynamically loaded before this one */
/* so we cannot rely on cloning BinFile.prototype */
this.readU8 = binFile.readU8;
this.readU32 = binFile.readU32;
this.skip = binFile.skip;
this.isEOF = binFile.isEOF;
this.seek = binFile.seek;
}
VCDIFF_Parser.prototype.read7BitEncodedInt=function(){
var num=0, bits = 0;