diff --git a/_cache_service_worker.js b/_cache_service_worker.js
index cb38938..51b05fe 100644
--- a/_cache_service_worker.js
+++ b/_cache_service_worker.js
@@ -6,7 +6,7 @@
*/
var PRECACHE_ID = 'rom-patcher-js';
-var PRECACHE_VERSION = 'v30rc1b';
+var PRECACHE_VERSION = 'v30rc2';
var PRECACHE_URLS = [
'/RomPatcher.js/', '/RomPatcher.js/index.html',
'/RomPatcher.js/manifest.json',
diff --git a/index.html b/index.html
index 153938d..536a7f4 100644
--- a/index.html
+++ b/index.html
@@ -151,7 +151,7 @@
- Rom Patcher JS v3.0 RC1 by Marc Robledo
+ Rom Patcher JS v3.0 RC2 by Marc Robledo
See on GitHub
Donate
diff --git a/index_template.html b/index_template.html
index eb308c6..66123e2 100644
--- a/index_template.html
+++ b/index_template.html
@@ -18,6 +18,7 @@
try {
RomPatcherWeb.initialize({
language: 'en', //default: en
+ requireValidation: false
}, {
file: './my_patch.zip', //zip containing patches
name: 'Game (English v1.0)',
@@ -49,7 +50,7 @@
@@ -83,8 +84,7 @@
-
+
diff --git a/rom-patcher-js/RomPatcher.webapp.js b/rom-patcher-js/RomPatcher.webapp.js
index c55da1f..155ff98 100644
--- a/rom-patcher-js/RomPatcher.webapp.js
+++ b/rom-patcher-js/RomPatcher.webapp.js
@@ -59,9 +59,11 @@ var RomPatcherWeb = (function () {
language: typeof navigator.language === 'string' ? navigator.language.substring(0, 2) : 'en',
outputSuffix: true,
fixChecksum: false,
+ requireValidation: false,
allowDropFiles: false,
+ oninitialize: null,
onloadrom: null,
onvalidaterom: null,
onloadpatch: null,
@@ -71,7 +73,7 @@ var RomPatcherWeb = (function () {
/* embeded patches */
- var embededPatchesInfo = null;
+ var currentEmbededPatches = null;
const _parseEmbededPatchInfo = function (embededPatchInfo) {
const parsedPatch = {
file: embededPatchInfo.file.trim(),
@@ -92,6 +94,8 @@ var RomPatcherWeb = (function () {
parsedPatch.description = embededPatchInfo.description;
}
+ parsedPatch.optional = !!embededPatchInfo.optional;
+
if (typeof embededPatchInfo.outputName === 'string') {
parsedPatch.outputName = embededPatchInfo.outputName;
}
@@ -123,58 +127,68 @@ var RomPatcherWeb = (function () {
return parsedPatch;
}
+ var isFetching = false;
const _fetchPatchFile = function (embededPatchInfo) {
+ if (isFetching)
+ throw new Error('Rom Patcher JS: already fetching another file');
+ isFetching = true;
+
htmlElements.disableAll();
const spinnerHtml = '';
-
- const loadingSpan = document.createElement('span');
- loadingSpan.id = 'rom-patcher-span-loading-embeded-patch';
- loadingSpan.innerHTML = _('Downloading...') + ' ' + spinnerHtml;
-
- const inputFilePatch = htmlElements.get('input-file-patch');
- if (inputFilePatch) {
- inputFilePatch.parentElement.replaceChild(loadingSpan, inputFilePatch);
- } else {
- throw new Error('Rom Patcher JS: input#rom-patcher-input-file-patch[type=file] not found');
- }
+ htmlElements.hide('select-patch');
+ htmlElements.empty('select-patch');
+ htmlElements.removeClass('select-patch', 'single');
+ htmlElements.removeClass('select-patch', 'multiple');
+ htmlElements.setEnabled('select-patch', false);
+ htmlElements.empty('container-optional-patches');
+ htmlElements.setText('span-loading-embeded-patch', _('Downloading...') + ' ' + spinnerHtml);
+ htmlElements.show('span-loading-embeded-patch');
-
- var uri = decodeURI(embededPatchInfo.file);
-
- fetch(uri)
+ fetch(decodeURI(embededPatchInfo.file))
.then(result => result.arrayBuffer()) // Gets the response and returns it as a blob
.then(arrayBuffer => {
const fetchedFile = new BinFile(arrayBuffer);
if (ZIPManager.isZipFile(fetchedFile)) {
if (typeof embededPatchInfo.patches === 'object') {
if (Array.isArray(embededPatchInfo.patches)) {
- embededPatchesInfo = embededPatchInfo.patches.map((embededPatchInfo) => _parseEmbededPatchInfo(embededPatchInfo));
+ currentEmbededPatches = embededPatchInfo.patches.map((embededPatchInfo) => _parseEmbededPatchInfo(embededPatchInfo));
} else {
console.warn('Rom Patcher JS: Invalid patches object for embeded patch', embededPatchInfo);
}
} else {
- embededPatchesInfo = [_parseEmbededPatchInfo(embededPatchInfo)];
+ currentEmbededPatches = [_parseEmbededPatchInfo(embededPatchInfo)];
}
- loadingSpan.innerHTML = _('Unzipping...') + ' ' + spinnerHtml;
- ZIPManager.unzipEmbededPatches(arrayBuffer, embededPatchesInfo);
+ htmlElements.setText('span-loading-embeded-patch', _('Unzipping...') + ' ' + spinnerHtml);
+
+ ZIPManager.unzipEmbededPatches(arrayBuffer, currentEmbededPatches);
} else {
- embededPatchesInfo = [_parseEmbededPatchInfo(embededPatchInfo)];
- loadingSpan.innerHTML = embededPatchesInfo[0].name;
- _setPatchInputSpinner(false);
+ const parsedPatch = _parseEmbededPatchInfo(embededPatchInfo);
+
+ currentEmbededPatches = [parsedPatch];
+ const option = document.createElement('option');
+ option.innerHTML = parsedPatch.name;
+ htmlElements.get('select-patch').appendChild(option);
+ htmlElements.setEnabled('select-patch', false);
+ htmlElements.addClass('select-patch', 'single');
+ htmlElements.hide('span-loading-embeded-patch');
+ htmlElements.show('select-patch');
+
fetchedFile.fileName = embededPatchInfo.file;
RomPatcherWeb.providePatchFile(fetchedFile);
}
+ isFetching = false;
})
.catch(function (evt) {
+ isFetching = false;
_setToastError((_('Error downloading %s') + '
' + evt.message).replace('%s', embededPatchInfo.file.replace(/^.*[\/\\]/g, '')));
});
};
const _getEmbededPatchInfo = function (fileName) {
- if (embededPatchesInfo)
- return embededPatchesInfo.find((embededPatchInfo) => embededPatchInfo.file === fileName);
+ if (currentEmbededPatches)
+ return currentEmbededPatches.find((embededPatchInfo) => embededPatchInfo.file === fileName);
return null;
}
@@ -187,13 +201,17 @@ var RomPatcherWeb = (function () {
return hexString
}
- const _setElementsStatus = function (status) {
+ const _setElementsStatus = function (status, applyButtonStatus) {
htmlElements.setEnabled('input-file-rom', status);
htmlElements.setEnabled('input-file-patch', status);
- htmlElements.setEnabled('select-file-patch', status);
+ if (htmlElements.get('select-patch')) {
+ htmlElements.setEnabled('select-patch', htmlElements.get('select-patch').children.length > 1 ? status : false);
+ }
htmlElements.setEnabled('checkbox-alter-header', status);
- if (romFile && status && (patch /* || embededPatchesInfo */)) {
+ if (romFile && patch && status) {
+ if (settings.requireValidation && typeof applyButtonStatus !== 'undefined')
+ status = !!applyButtonStatus;
htmlElements.setEnabled('button-apply', status);
} else {
htmlElements.setEnabled('button-apply', false);
@@ -201,7 +219,7 @@ var RomPatcherWeb = (function () {
};
const _setInputFileSpinner = function (inputFileId, status) {
- const elementId = embededPatchesInfo && inputFileId === 'patch' ? ('select-file-' + inputFileId) : ('input-file-' + inputFileId);
+ const elementId = currentEmbededPatches && inputFileId === 'patch' ? ('select-' + inputFileId) : ('input-file-' + inputFileId);
const spinnerId = 'spinner-' + inputFileId;
htmlElements.removeClass(elementId, 'empty');
@@ -213,8 +231,13 @@ var RomPatcherWeb = (function () {
spinner.className = 'rom-patcher-spinner';
const htmlInputFile = htmlElements.get(elementId);
- if (htmlInputFile)
- htmlInputFile.parentElement.appendChild(spinner);
+ if (htmlInputFile){
+ if(elementId === 'select-patch'){
+ htmlInputFile.parentElement.insertBefore(spinner, htmlElements.get('span-loading-embeded-patch'));
+ }else{
+ htmlInputFile.parentElement.appendChild(spinner);
+ }
+ }
htmlElements.addClass(elementId, 'loading');
htmlElements.removeClass(elementId, 'valid');
@@ -313,6 +336,10 @@ var RomPatcherWeb = (function () {
document.getElementById('rom-patcher-' + id).innerHTML = text;
},
+ empty: function (id) {
+ if (document.getElementById('rom-patcher-' + id))
+ document.getElementById('rom-patcher-' + id).innerHTML = '';
+ },
addClass: function (id, className) {
if (document.getElementById('rom-patcher-' + id))
document.getElementById('rom-patcher-' + id).classList.add(className);
@@ -360,10 +387,25 @@ var RomPatcherWeb = (function () {
htmlElements.enableAll();
_setApplyButtonSpinner(false);
if (event.data.patchedRomU8Array && !event.data.errorMessage) {
- const patchedRom = new BinFile(event.data.patchedRomU8Array.buffer);
+ var patchedRom = new BinFile(event.data.patchedRomU8Array.buffer);
patchedRom.fileName = event.data.patchedRomFileName;
+
+ if(currentEmbededPatches){
+ const optionalPatches = currentEmbededPatches.filter((embededPatchInfo) => embededPatchInfo.optional);
+ if(optionalPatches.length){
+ const originalFileName = patchedRom.fileName;
+ for(var i=0; i { // listen for events from the worker
_setToastError('webWorkerCrc error: ' + event.message);
@@ -447,22 +489,29 @@ var RomPatcherWeb = (function () {
return missingDependencies;
}
- const _initialize = function (newSettings, embededPatchInfo) {
- /* embeded patches */
- var validEmbededPatch = false;
+
+
+
+ const _checkEmbededPatchParameter = function (embededPatchInfo) {
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');
- }
- }
+ if (typeof embededPatchInfo !== 'object')
+ throw new Error('Rom Patcher JS: invalid embeded patch parameter');
+ else if (typeof embededPatchInfo.file !== 'string')
+ throw new Error('Rom Patcher JS: embeded patch missing file property');
+
+ return embededPatchInfo;
}
+ return false;
+ }
+
+ const _initialize = function (newSettings, embededPatchInfo) {
+ /* embeded patches */
+ var validEmbededPatch = _checkEmbededPatchParameter(embededPatchInfo);
+
/* check if Rom Patcher JS core is available */
@@ -489,14 +538,34 @@ var RomPatcherWeb = (function () {
} 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);
- });
+ if (validEmbededPatch) {
+ const htmlSelectPatch = htmlElements.get('select-patch');
+ if (htmlSelectPatch && htmlSelectPatch.tagName === 'SELECT') {
+ htmlSelectPatch.addEventListener('change', function (evt) {
+ const zippedEntryIndex = parseInt(this.value);
+ this._unzipSelectedPatch(zippedEntryIndex);
+ });
+ } else {
+ throw new Error('Rom Patcher JS: select#rom-patcher-select-patch not found');
+ }
+ const loadingSpan = document.createElement('span');
+ loadingSpan.id = 'rom-patcher-span-loading-embeded-patch';
+ loadingSpan.style.display = 'none';
+ htmlSelectPatch.parentElement.appendChild(loadingSpan);
+ const containerOptionalPatches = document.createElement('div');
+ containerOptionalPatches.id = 'rom-patcher-container-optional-patches';
+ containerOptionalPatches.style.display = 'none';
+ htmlSelectPatch.parentElement.appendChild(containerOptionalPatches);
} else {
- throw new Error('Rom Patcher JS: input#rom-patcher-input-file-patch[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') {
@@ -558,9 +627,11 @@ var RomPatcherWeb = (function () {
htmlInputFileRom.addEventListener('drop', function (evt) {
evt.stopPropagation();
});
- htmlInputFilePatch.addEventListener('drop', function (evt) {
- evt.stopPropagation();
- });
+ if (!validEmbededPatch) {
+ htmlElements.get('input-file-patch').addEventListener('drop', function (evt) {
+ evt.stopPropagation();
+ });
+ }
}
console.log('Rom Patcher JS initialized');
@@ -572,9 +643,12 @@ var RomPatcherWeb = (function () {
/* download embeded patch */
if (validEmbededPatch)
- _fetchPatchFile(embededPatchInfo);
+ _fetchPatchFile(validEmbededPatch);
else
htmlElements.enableAll();
+
+ if (typeof settings.oninitialize === 'function')
+ settings.oninitialize(this);
}
@@ -597,7 +671,7 @@ var RomPatcherWeb = (function () {
return initialized;
},
getEmbededPatches: function () {
- return embededPatchesInfo;
+ return currentEmbededPatches;
},
provideRomFile: function (binFile, transferFakeFile) {
@@ -766,21 +840,23 @@ var RomPatcherWeb = (function () {
},
pickEmbededFile: function (fileName) {
- if (typeof fileName !== 'string')
+ if(!currentEmbededPatches)
+ throw new Error('No embeded patches available');
+ else if (typeof fileName !== 'string')
throw new Error('Invalid embeded patch file name');
- const selectFilePatch = htmlElements.get('select-file-patch');
- if (selectFilePatch) {
- const embededPatchInfo = _getEmbededPatchInfo(fileName);
- if (embededPatchInfo && typeof embededPatchInfo.selectIndex === 'number' && selectFilePatch.value != embededPatchInfo.selectIndex) {
- selectFilePatch.value = embededPatchInfo.selectIndex;
-
- /* create and dispatch change event */
- const evt = new Event('change');
- selectFilePatch.dispatchEvent(evt);
+ const selectPatch = htmlElements.get('select-patch');
+ for(var i=0; i embededPatchInfo.file === filteredEntries[i].filename);
- var option = document.createElement('option');
- option.innerHTML = embededPatchInfo ? embededPatchInfo.name : filteredEntries[i].filename;
- option.value = i;
- select.appendChild(option);
- if (embededPatchInfo) {
- embededPatchInfo.selectIndex = i;
- }
- }
-
- select.addEventListener('change', function (evt) {
- const fileIndex = parseInt(this.value);
- _unzipEntry(filteredEntries[fileIndex], romPatcherWeb.providePatchFile);
- });
- } else {
- throw new Error('rom-patcher-select-file-patch not found');
- }
+ const selectablePatches = [];
+ const optionalPatches = [];
+ for (var i = 0; i < filteredEntries.length; i++) {
+ const embededPatchInfo = embededPatchesInfo.find((embededPatchInfo) => embededPatchInfo.file === filteredEntries[i].filename);
+ if (embededPatchInfo && embededPatchInfo.optional)
+ optionalPatches.push(filteredEntries[i]);
+ else
+ selectablePatches.push(filteredEntries[i]);
}
- //_setPatchInputSpinner(false);
- _unzipEntry(filteredEntries[0], romPatcherWeb.providePatchFile);
+ if (!selectablePatches.length) {
+ romPatcherWeb.setErrorMessage(_('No valid non-optional patches found in ZIP'), 'error');
+ romPatcherWeb.disable();
+ throw new Error('No valid non-optional patches found in ZIP');
+ }
+
+ if (embededPatchesInfo.length && embededPatchesInfo.length === 1 && selectablePatches.length === 1)
+ embededPatchesInfo[0].file = selectablePatches[0].filename;
+
+ for (var i = 0; i < selectablePatches.length; i++) {
+ const embededPatchInfo = embededPatchesInfo.find((embededPatchInfo) => embededPatchInfo.file === selectablePatches[i].filename);
+ const option = document.createElement('option');
+ option.innerHTML = embededPatchInfo && embededPatchInfo.name ? embededPatchInfo.name : selectablePatches[i].filename;
+ option.value = i;
+ option.patchFileName = selectablePatches[i].filename;
+ htmlElements.get('select-patch').appendChild(option);
+ }
+ htmlElements.get('select-patch')._unzipSelectedPatch = function(fileIndex){
+ _unzipEntry(selectablePatches[fileIndex], romPatcherWeb.providePatchFile);
+ };
+
+ for (var i = 0; i < optionalPatches.length; i++) {
+ const embededPatchInfo = embededPatchesInfo.find((embededPatchInfo) => embededPatchInfo.file === optionalPatches[i].filename);
+
+ const checkbox = document.createElement('input');
+ checkbox.type = 'checkbox';
+ checkbox.value = i;
+ checkbox.checked = false;
+ checkbox.disabled = true;
+ embededPatchInfo.checkbox = checkbox;
+
+ const label = document.createElement('label');
+ label.className = 'rom-patcher-checkbox-optional-patch';
+ label.appendChild(checkbox);
+ label.appendChild(document.createTextNode(embededPatchInfo.name || embededPatchInfo.file));
+ if (embededPatchInfo.description)
+ label.title = embededPatchInfo.description;
+
+ htmlElements.get('container-optional-patches').appendChild(label);
+
+ optionalPatches[i].getData(new zip.BlobWriter(), function (blob) {
+ const fileReader = new FileReader();
+ fileReader.onload = function () {
+ const binFile = new BinFile(this.result);
+ binFile.fileName = 'optional_patch.unk';
+ embededPatchInfo.parsedPatch = RomPatcher.parsePatchFile(binFile);
+ checkbox.disabled = false;
+ };
+ fileReader.readAsArrayBuffer(blob);
+ });
+ }
+ if (optionalPatches.length === 1)
+ htmlElements.show('container-optional-patches');
+
+
+
+ if (selectablePatches.length === 1)
+ htmlElements.addClass('select-patch', 'single');
+ else
+ htmlElements.addClass('select-patch', 'multiple');
+
+ htmlElements.setEnabled('select-patch', false);
+ htmlElements.hide('span-loading-embeded-patch');
+ htmlElements.show('select-patch');
+
+ _unzipEntry(selectablePatches[0], romPatcherWeb.providePatchFile);
+
} else {
romPatcherWeb.setErrorMessage(_('No valid patches found in ZIP'), 'error');
romPatcherWeb.disable();
diff --git a/rom-patcher-js/style.css b/rom-patcher-js/style.css
index 1265ccd..1465f9d 100644
--- a/rom-patcher-js/style.css
+++ b/rom-patcher-js/style.css
@@ -356,6 +356,22 @@
+#rom-patcher-container #rom-patcher-select-patch{
+ display:none
+}
+#rom-patcher-container #rom-patcher-select-patch.single{
+ background-image: none;
+ background-color: transparent;
+ color: inherit !important;
+ padding-left: 0;
+}
+
+
+
+
+
+
+