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

feat (web): settings.requireValidation

feat (web): settings.oninitialize event
feat (web): allow optional embeded patches (will appear as checkboxes)
fix (web): allow null object as settings
This commit is contained in:
Marc Robledo 2024-08-14 20:16:14 +02:00
parent 9ec774421e
commit c5c39a7703
5 changed files with 270 additions and 117 deletions

View file

@ -6,7 +6,7 @@
*/ */
var PRECACHE_ID = 'rom-patcher-js'; var PRECACHE_ID = 'rom-patcher-js';
var PRECACHE_VERSION = 'v30rc1b'; var PRECACHE_VERSION = 'v30rc2';
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">RC1</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">RC2</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

@ -18,6 +18,7 @@
try { try {
RomPatcherWeb.initialize({ RomPatcherWeb.initialize({
language: 'en', //default: en language: 'en', //default: en
requireValidation: false
}, { }, {
file: './my_patch.zip', //zip containing patches file: './my_patch.zip', //zip containing patches
name: 'Game (English v1.0)', name: 'Game (English v1.0)',
@ -49,7 +50,7 @@
<!-- <!--
The following elements are required for Rom Patcher JS to work: The following elements are required for Rom Patcher JS to work:
#rom-patcher-input-file-rom #rom-patcher-input-file-rom
#rom-patcher-input-file-patch #rom-patcher-select-patch
#rom-patcher-button-apply #rom-patcher-button-apply
The rest of elements are informative and can be removed, though it's recommended to keep them for a better user experience. The rest of elements are informative and can be removed, though it's recommended to keep them for a better user experience.
--> -->
@ -83,8 +84,7 @@
<div class="text-right"><label for="rom-patcher-input-file-patch" data-localize="yes">Patch file:</label> <div class="text-right"><label for="rom-patcher-input-file-patch" data-localize="yes">Patch file:</label>
</div> </div>
<div class="rom-patcher-container-input"> <div class="rom-patcher-container-input">
<input type="file" id="rom-patcher-input-file-patch" class="empty" <select id="rom-patcher-select-patch"></select>
accept=".ips,.ups,.bps,.aps,.rup,.ppf,.mod,.xdelta,.vcdiff,.zip" disabled />
</div> </div>
</div> </div>
<div class="rom-patcher-row margin-bottom" id="rom-patcher-row-patch-description"> <div class="rom-patcher-row margin-bottom" id="rom-patcher-row-patch-description">

View file

@ -59,9 +59,11 @@ var RomPatcherWeb = (function () {
language: typeof navigator.language === 'string' ? navigator.language.substring(0, 2) : 'en', language: typeof navigator.language === 'string' ? navigator.language.substring(0, 2) : 'en',
outputSuffix: true, outputSuffix: true,
fixChecksum: false, fixChecksum: false,
requireValidation: false,
allowDropFiles: false, allowDropFiles: false,
oninitialize: null,
onloadrom: null, onloadrom: null,
onvalidaterom: null, onvalidaterom: null,
onloadpatch: null, onloadpatch: null,
@ -71,7 +73,7 @@ var RomPatcherWeb = (function () {
/* embeded patches */ /* embeded patches */
var embededPatchesInfo = null; var currentEmbededPatches = null;
const _parseEmbededPatchInfo = function (embededPatchInfo) { const _parseEmbededPatchInfo = function (embededPatchInfo) {
const parsedPatch = { const parsedPatch = {
file: embededPatchInfo.file.trim(), file: embededPatchInfo.file.trim(),
@ -92,6 +94,8 @@ var RomPatcherWeb = (function () {
parsedPatch.description = embededPatchInfo.description; parsedPatch.description = embededPatchInfo.description;
} }
parsedPatch.optional = !!embededPatchInfo.optional;
if (typeof embededPatchInfo.outputName === 'string') { if (typeof embededPatchInfo.outputName === 'string') {
parsedPatch.outputName = embededPatchInfo.outputName; parsedPatch.outputName = embededPatchInfo.outputName;
} }
@ -123,58 +127,68 @@ var RomPatcherWeb = (function () {
return parsedPatch; return parsedPatch;
} }
var isFetching = false;
const _fetchPatchFile = function (embededPatchInfo) { const _fetchPatchFile = function (embededPatchInfo) {
if (isFetching)
throw new Error('Rom Patcher JS: already fetching another file');
isFetching = true;
htmlElements.disableAll(); htmlElements.disableAll();
const spinnerHtml = '<span class="rom-patcher-spinner" id="rom-patcher-spinner-patch"></span>'; const spinnerHtml = '<span class="rom-patcher-spinner" id="rom-patcher-spinner-patch"></span>';
htmlElements.hide('select-patch');
const loadingSpan = document.createElement('span'); htmlElements.empty('select-patch');
loadingSpan.id = 'rom-patcher-span-loading-embeded-patch'; htmlElements.removeClass('select-patch', 'single');
loadingSpan.innerHTML = _('Downloading...') + ' ' + spinnerHtml; htmlElements.removeClass('select-patch', 'multiple');
htmlElements.setEnabled('select-patch', false);
const inputFilePatch = htmlElements.get('input-file-patch'); htmlElements.empty('container-optional-patches');
if (inputFilePatch) { htmlElements.setText('span-loading-embeded-patch', _('Downloading...') + ' ' + spinnerHtml);
inputFilePatch.parentElement.replaceChild(loadingSpan, inputFilePatch); htmlElements.show('span-loading-embeded-patch');
} else {
throw new Error('Rom Patcher JS: input#rom-patcher-input-file-patch[type=file] not found');
}
fetch(decodeURI(embededPatchInfo.file))
var uri = decodeURI(embededPatchInfo.file);
fetch(uri)
.then(result => result.arrayBuffer()) // Gets the response and returns it as a blob .then(result => result.arrayBuffer()) // Gets the response and returns it as a blob
.then(arrayBuffer => { .then(arrayBuffer => {
const fetchedFile = new BinFile(arrayBuffer); const fetchedFile = new BinFile(arrayBuffer);
if (ZIPManager.isZipFile(fetchedFile)) { if (ZIPManager.isZipFile(fetchedFile)) {
if (typeof embededPatchInfo.patches === 'object') { if (typeof embededPatchInfo.patches === 'object') {
if (Array.isArray(embededPatchInfo.patches)) { if (Array.isArray(embededPatchInfo.patches)) {
embededPatchesInfo = embededPatchInfo.patches.map((embededPatchInfo) => _parseEmbededPatchInfo(embededPatchInfo)); currentEmbededPatches = embededPatchInfo.patches.map((embededPatchInfo) => _parseEmbededPatchInfo(embededPatchInfo));
} else { } else {
console.warn('Rom Patcher JS: Invalid patches object for embeded patch', embededPatchInfo); console.warn('Rom Patcher JS: Invalid patches object for embeded patch', embededPatchInfo);
} }
} else { } else {
embededPatchesInfo = [_parseEmbededPatchInfo(embededPatchInfo)]; currentEmbededPatches = [_parseEmbededPatchInfo(embededPatchInfo)];
} }
loadingSpan.innerHTML = _('Unzipping...') + ' ' + spinnerHtml; htmlElements.setText('span-loading-embeded-patch', _('Unzipping...') + ' ' + spinnerHtml);
ZIPManager.unzipEmbededPatches(arrayBuffer, embededPatchesInfo);
ZIPManager.unzipEmbededPatches(arrayBuffer, currentEmbededPatches);
} else { } else {
embededPatchesInfo = [_parseEmbededPatchInfo(embededPatchInfo)]; const parsedPatch = _parseEmbededPatchInfo(embededPatchInfo);
loadingSpan.innerHTML = embededPatchesInfo[0].name;
_setPatchInputSpinner(false); 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; fetchedFile.fileName = embededPatchInfo.file;
RomPatcherWeb.providePatchFile(fetchedFile); RomPatcherWeb.providePatchFile(fetchedFile);
} }
isFetching = false;
}) })
.catch(function (evt) { .catch(function (evt) {
isFetching = false;
_setToastError((_('Error downloading %s') + '<br />' + evt.message).replace('%s', embededPatchInfo.file.replace(/^.*[\/\\]/g, ''))); _setToastError((_('Error downloading %s') + '<br />' + evt.message).replace('%s', embededPatchInfo.file.replace(/^.*[\/\\]/g, '')));
}); });
}; };
const _getEmbededPatchInfo = function (fileName) { const _getEmbededPatchInfo = function (fileName) {
if (embededPatchesInfo) if (currentEmbededPatches)
return embededPatchesInfo.find((embededPatchInfo) => embededPatchInfo.file === fileName); return currentEmbededPatches.find((embededPatchInfo) => embededPatchInfo.file === fileName);
return null; return null;
} }
@ -187,13 +201,17 @@ var RomPatcherWeb = (function () {
return hexString return hexString
} }
const _setElementsStatus = function (status) { const _setElementsStatus = function (status, applyButtonStatus) {
htmlElements.setEnabled('input-file-rom', status); htmlElements.setEnabled('input-file-rom', status);
htmlElements.setEnabled('input-file-patch', 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); 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); htmlElements.setEnabled('button-apply', status);
} else { } else {
htmlElements.setEnabled('button-apply', false); htmlElements.setEnabled('button-apply', false);
@ -201,7 +219,7 @@ var RomPatcherWeb = (function () {
}; };
const _setInputFileSpinner = function (inputFileId, status) { 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; const spinnerId = 'spinner-' + inputFileId;
htmlElements.removeClass(elementId, 'empty'); htmlElements.removeClass(elementId, 'empty');
@ -213,8 +231,13 @@ var RomPatcherWeb = (function () {
spinner.className = 'rom-patcher-spinner'; spinner.className = 'rom-patcher-spinner';
const htmlInputFile = htmlElements.get(elementId); const htmlInputFile = htmlElements.get(elementId);
if (htmlInputFile) if (htmlInputFile){
if(elementId === 'select-patch'){
htmlInputFile.parentElement.insertBefore(spinner, htmlElements.get('span-loading-embeded-patch'));
}else{
htmlInputFile.parentElement.appendChild(spinner); htmlInputFile.parentElement.appendChild(spinner);
}
}
htmlElements.addClass(elementId, 'loading'); htmlElements.addClass(elementId, 'loading');
htmlElements.removeClass(elementId, 'valid'); htmlElements.removeClass(elementId, 'valid');
@ -313,6 +336,10 @@ var RomPatcherWeb = (function () {
document.getElementById('rom-patcher-' + id).innerHTML = text; 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) { addClass: function (id, className) {
if (document.getElementById('rom-patcher-' + id)) if (document.getElementById('rom-patcher-' + id))
document.getElementById('rom-patcher-' + id).classList.add(className); document.getElementById('rom-patcher-' + id).classList.add(className);
@ -360,10 +387,25 @@ var RomPatcherWeb = (function () {
htmlElements.enableAll(); htmlElements.enableAll();
_setApplyButtonSpinner(false); _setApplyButtonSpinner(false);
if (event.data.patchedRomU8Array && !event.data.errorMessage) { 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; 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<optionalPatches.length; i++){
/* could be improved by using webWorkerApply to apply optional patches */
if(optionalPatches[i].checkbox.checked)
patchedRom = RomPatcher.applyPatch(patchedRom, optionalPatches[i].parsedPatch, {requireValidation:false, fixChecksum: true});
}
patchedRom.fileName = originalFileName;
}
}
if (typeof settings.onpatch === 'function') if (typeof settings.onpatch === 'function')
settings.onpatch(patchedRom); settings.onpatch(patchedRom);
patchedRom.save(); patchedRom.save();
_setToastError(); _setToastError();
} else { } else {
@ -394,8 +436,8 @@ var RomPatcherWeb = (function () {
htmlElements.addClass('row-info-rom', 'show'); htmlElements.addClass('row-info-rom', 'show');
} }
RomPatcherWeb.validateCurrentRom(event.data.checksumStartOffset); validRom = RomPatcherWeb.validateCurrentRom(event.data.checksumStartOffset);
htmlElements.enableAll(); _setElementsStatus(true, validRom);
}; };
webWorkerCrc.onerror = event => { // listen for events from the worker webWorkerCrc.onerror = event => { // listen for events from the worker
_setToastError('webWorkerCrc error: ' + event.message); _setToastError('webWorkerCrc error: ' + event.message);
@ -447,22 +489,29 @@ var RomPatcherWeb = (function () {
return missingDependencies; return missingDependencies;
} }
const _initialize = function (newSettings, embededPatchInfo) {
/* embeded patches */
var validEmbededPatch = false;
const _checkEmbededPatchParameter = function (embededPatchInfo) {
if (embededPatchInfo) { if (embededPatchInfo) {
if (typeof embededPatchInfo === 'string') if (typeof embededPatchInfo === 'string')
embededPatchInfo = { file: embededPatchInfo }; embededPatchInfo = { file: embededPatchInfo };
if (typeof embededPatchInfo === 'object') { if (typeof embededPatchInfo !== 'object')
if (typeof embededPatchInfo.file === 'string') { throw new Error('Rom Patcher JS: invalid embeded patch parameter');
validEmbededPatch = true; else if (typeof embededPatchInfo.file !== 'string')
} else { throw new Error('Rom Patcher JS: embeded patch missing file property');
throw new Error('Rom Patcher JS: invalid embeded patch file');
} return embededPatchInfo;
} }
return false;
} }
const _initialize = function (newSettings, embededPatchInfo) {
/* embeded patches */
var validEmbededPatch = _checkEmbededPatchParameter(embededPatchInfo);
/* check if Rom Patcher JS core is available */ /* check if Rom Patcher JS core is available */
@ -489,6 +538,25 @@ var RomPatcherWeb = (function () {
} else { } else {
throw new Error('Rom Patcher JS: input#rom-patcher-input-file-rom[type=file] not found'); throw new Error('Rom Patcher JS: input#rom-patcher-input-file-rom[type=file] not found');
} }
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 {
const htmlInputFilePatch = htmlElements.get('input-file-patch'); const htmlInputFilePatch = htmlElements.get('input-file-patch');
if (htmlInputFilePatch && htmlInputFilePatch.tagName === 'INPUT' && htmlInputFilePatch.type === 'file') { if (htmlInputFilePatch && htmlInputFilePatch.tagName === 'INPUT' && htmlInputFilePatch.type === 'file') {
htmlInputFilePatch.addEventListener('change', function (evt) { htmlInputFilePatch.addEventListener('change', function (evt) {
@ -498,6 +566,7 @@ var RomPatcherWeb = (function () {
} else { } else {
throw new Error('Rom Patcher JS: input#rom-patcher-input-file-patch[type=file] not found'); throw new Error('Rom Patcher JS: input#rom-patcher-input-file-patch[type=file] not found');
} }
}
const htmlButtonApply = htmlElements.get('button-apply'); const htmlButtonApply = htmlElements.get('button-apply');
if (htmlButtonApply && htmlButtonApply.tagName === 'BUTTON') { if (htmlButtonApply && htmlButtonApply.tagName === 'BUTTON') {
htmlButtonApply.addEventListener('click', RomPatcherWeb.applyPatch); htmlButtonApply.addEventListener('click', RomPatcherWeb.applyPatch);
@ -558,10 +627,12 @@ var RomPatcherWeb = (function () {
htmlInputFileRom.addEventListener('drop', function (evt) { htmlInputFileRom.addEventListener('drop', function (evt) {
evt.stopPropagation(); evt.stopPropagation();
}); });
htmlInputFilePatch.addEventListener('drop', function (evt) { if (!validEmbededPatch) {
htmlElements.get('input-file-patch').addEventListener('drop', function (evt) {
evt.stopPropagation(); evt.stopPropagation();
}); });
} }
}
console.log('Rom Patcher JS initialized'); console.log('Rom Patcher JS initialized');
initialized = true; initialized = true;
@ -572,9 +643,12 @@ var RomPatcherWeb = (function () {
/* download embeded patch */ /* download embeded patch */
if (validEmbededPatch) if (validEmbededPatch)
_fetchPatchFile(embededPatchInfo); _fetchPatchFile(validEmbededPatch);
else else
htmlElements.enableAll(); htmlElements.enableAll();
if (typeof settings.oninitialize === 'function')
settings.oninitialize(this);
} }
@ -597,7 +671,7 @@ var RomPatcherWeb = (function () {
return initialized; return initialized;
}, },
getEmbededPatches: function () { getEmbededPatches: function () {
return embededPatchesInfo; return currentEmbededPatches;
}, },
provideRomFile: function (binFile, transferFakeFile) { provideRomFile: function (binFile, transferFakeFile) {
@ -766,21 +840,23 @@ var RomPatcherWeb = (function () {
}, },
pickEmbededFile: function (fileName) { 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'); throw new Error('Invalid embeded patch file name');
const selectFilePatch = htmlElements.get('select-file-patch'); const selectPatch = htmlElements.get('select-patch');
if (selectFilePatch) { for(var i=0; i<selectPatch.children.length; i++){
const embededPatchInfo = _getEmbededPatchInfo(fileName); if(selectPatch.children[i].patchFileName === fileName){
if (embededPatchInfo && typeof embededPatchInfo.selectIndex === 'number' && selectFilePatch.value != embededPatchInfo.selectIndex) { if(selectPatch.value != selectPatch.children[i].value){
selectFilePatch.value = embededPatchInfo.selectIndex; selectPatch.value = selectPatch.children[i].value;
/* create and dispatch change event */ /* create and dispatch change event */
const evt = new Event('change'); const evt = new Event('change');
selectFilePatch.dispatchEvent(evt); selectPatch.dispatchEvent(evt);
}
break;
} }
} else {
console.warn('RomPatcherWeb.pickEmbededFile: select-file-patch not found');
} }
}, },
@ -829,11 +905,22 @@ var RomPatcherWeb = (function () {
document.head.appendChild(script); document.head.appendChild(script);
}); });
}, },
setEmbededPatches: function (embededPatchInfo) {
if(!currentEmbededPatches)
throw new Error('Rom Patcher JS: not in embeded patch mode');
/* embeded patches */
var validEmbededPatch = _checkEmbededPatchParameter(embededPatchInfo);
if(!validEmbededPatch)
throw new Error('Rom Patcher JS: invalid embeded patch parameter');
_fetchPatchFile(validEmbededPatch);
},
applyPatch: function () { applyPatch: function () {
if (romFile && patch) { if (romFile && patch) {
const romPatcherOptions = { const romPatcherOptions = {
requireValidation: false, requireValidation: settings.requireValidation,
removeHeader: RomPatcher.isRomHeadered(romFile) && htmlElements.isChecked('checkbox-alter-header'), removeHeader: RomPatcher.isRomHeadered(romFile) && htmlElements.isChecked('checkbox-alter-header'),
addHeader: RomPatcher.canRomGetHeader(romFile) && htmlElements.isChecked('checkbox-alter-header'), addHeader: RomPatcher.canRomGetHeader(romFile) && htmlElements.isChecked('checkbox-alter-header'),
fixChecksum: settings.fixChecksum, fixChecksum: settings.fixChecksum,
@ -902,12 +989,16 @@ var RomPatcherWeb = (function () {
if (typeof settings.onvalidaterom === 'function') if (typeof settings.onvalidaterom === 'function')
settings.onvalidaterom(romFile, validRom); settings.onvalidaterom(romFile, validRom);
return validRom;
} else { } else {
htmlElements.removeClass('input-file-rom', 'valid'); htmlElements.removeClass('input-file-rom', 'valid');
htmlElements.removeClass('input-file-rom', 'invalid'); htmlElements.removeClass('input-file-rom', 'invalid');
_setToastError(); _setToastError();
if (romFile && patch && typeof settings.onvalidaterom === 'function') if (romFile && patch && typeof settings.onvalidaterom === 'function')
settings.onvalidaterom(romFile, true); settings.onvalidaterom(romFile, true);
return (romFile && patch);
} }
}, },
@ -936,18 +1027,23 @@ var RomPatcherWeb = (function () {
return settings.language; return settings.language;
}, },
setSettings: function (newSettings) { setSettings: function (newSettings) {
if (typeof newSettings === 'object') { if (newSettings && typeof newSettings === 'object') {
if (typeof newSettings.language === 'string') { if (typeof newSettings.language === 'string')
settings.language = newSettings.language; settings.language = newSettings.language;
RomPatcherWeb.translateUI();
}
if (typeof newSettings.outputSuffix === 'boolean') { if (typeof newSettings.outputSuffix === 'boolean')
settings.outputSuffix = newSettings.outputSuffix; settings.outputSuffix = newSettings.outputSuffix;
}
if (typeof newSettings.fixChecksum === 'boolean') { if (typeof newSettings.fixChecksum === 'boolean')
settings.fixChecksum = newSettings.fixChecksum; settings.fixChecksum = newSettings.fixChecksum;
}
if (typeof newSettings.requireValidation === 'boolean')
settings.requireValidation = newSettings.requireValidation;
if (typeof newSettings.oninitialize === 'function')
settings.oninitialize = newSettings.oninitialize;
else if (typeof newSettings.oninitialize !== 'undefined')
settings.oninitialize = null;
if (typeof newSettings.onloadrom === 'function') if (typeof newSettings.onloadrom === 'function')
settings.onloadrom = newSettings.onloadrom; settings.onloadrom = newSettings.onloadrom;
@ -969,6 +1065,7 @@ var RomPatcherWeb = (function () {
else if (typeof newSettings.onpatch !== 'undefined') else if (typeof newSettings.onpatch !== 'undefined')
settings.onpatch = null; settings.onpatch = null;
} }
RomPatcherWeb.translateUI();
} }
} }
}()); }());
@ -1226,43 +1323,83 @@ const ZIPManager = (function (romPatcherWeb) {
const filteredEntries = _filterEntriesPatches(zipEntries); const filteredEntries = _filterEntriesPatches(zipEntries);
if (filteredEntries.length) { if (filteredEntries.length) {
if (filteredEntries.length === 1) { const selectablePatches = [];
if (embededPatchesInfo) { const optionalPatches = [];
embededPatchesInfo[0].file = filteredEntries[0].filename;
htmlElements.setText('span-loading-embeded-patch', embededPatchesInfo[0].file);
} else {
htmlElements.setText('span-loading-embeded-patch', filteredEntries[0].filename);
}
} else {
var select = document.createElement('select');
select.id = 'rom-patcher-select-file-patch';
const spanLoadingEmbededPatch = htmlElements.get('span-loading-embeded-patch');
if (spanLoadingEmbededPatch) {
spanLoadingEmbededPatch.parentElement.replaceChild(select, spanLoadingEmbededPatch);
for (var i = 0; i < filteredEntries.length; i++) { for (var i = 0; i < filteredEntries.length; i++) {
const embededPatchInfo = embededPatchesInfo.find((embededPatchInfo) => embededPatchInfo.file === filteredEntries[i].filename); const embededPatchInfo = embededPatchesInfo.find((embededPatchInfo) => embededPatchInfo.file === filteredEntries[i].filename);
var option = document.createElement('option'); if (embededPatchInfo && embededPatchInfo.optional)
option.innerHTML = embededPatchInfo ? embededPatchInfo.name : filteredEntries[i].filename; optionalPatches.push(filteredEntries[i]);
else
selectablePatches.push(filteredEntries[i]);
}
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.value = i;
select.appendChild(option); option.patchFileName = selectablePatches[i].filename;
if (embededPatchInfo) { htmlElements.get('select-patch').appendChild(option);
embededPatchInfo.selectIndex = i;
}
} }
htmlElements.get('select-patch')._unzipSelectedPatch = function(fileIndex){
_unzipEntry(selectablePatches[fileIndex], romPatcherWeb.providePatchFile);
};
select.addEventListener('change', function (evt) { for (var i = 0; i < optionalPatches.length; i++) {
const fileIndex = parseInt(this.value); const embededPatchInfo = embededPatchesInfo.find((embededPatchInfo) => embededPatchInfo.file === optionalPatches[i].filename);
_unzipEntry(filteredEntries[fileIndex], romPatcherWeb.providePatchFile);
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);
}); });
} else {
throw new Error('rom-patcher-select-file-patch not found');
}
} }
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);
//_setPatchInputSpinner(false);
_unzipEntry(filteredEntries[0], romPatcherWeb.providePatchFile);
} else { } else {
romPatcherWeb.setErrorMessage(_('No valid patches found in ZIP'), 'error'); romPatcherWeb.setErrorMessage(_('No valid patches found in ZIP'), 'error');
romPatcherWeb.disable(); romPatcherWeb.disable();

View file

@ -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;
}