mirror of
https://github.com/marcrobledo/RomPatcher.js.git
synced 2025-06-27 16:25:54 +00:00
fixed MD5 hashing with >512MB files, ignore txt, readmes,etc files in zips, multiple predefined patches is now a dropdown, allowing user to choose and change patch without having to refresh the app
This commit is contained in:
parent
bcc714f179
commit
458d7297e4
7 changed files with 366 additions and 251 deletions
|
@ -29,7 +29,7 @@ caches.keys().then(function(cacheNames){
|
||||||
});
|
});
|
||||||
|
|
||||||
var PRECACHE_ID='rom-patcher-js';
|
var PRECACHE_ID='rom-patcher-js';
|
||||||
var PRECACHE_VERSION='v12';
|
var PRECACHE_VERSION='v14';
|
||||||
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',
|
||||||
|
@ -48,7 +48,6 @@ var PRECACHE_URLS=[
|
||||||
'/RomPatcher.js/js/zip.js/zip.js',
|
'/RomPatcher.js/js/zip.js/zip.js',
|
||||||
'/RomPatcher.js/js/zip.js/z-worker.js',
|
'/RomPatcher.js/js/zip.js/z-worker.js',
|
||||||
'/RomPatcher.js/js/zip.js/inflate.js',
|
'/RomPatcher.js/js/zip.js/inflate.js',
|
||||||
'/RomPatcher.js/js/formats/zip.js',
|
|
||||||
'/RomPatcher.js/js/formats/ips.js',
|
'/RomPatcher.js/js/formats/ips.js',
|
||||||
'/RomPatcher.js/js/formats/ups.js',
|
'/RomPatcher.js/js/formats/ups.js',
|
||||||
'/RomPatcher.js/js/formats/aps.js',
|
'/RomPatcher.js/js/formats/aps.js',
|
||||||
|
@ -56,7 +55,8 @@ var PRECACHE_URLS=[
|
||||||
'/RomPatcher.js/js/formats/rup.js',
|
'/RomPatcher.js/js/formats/rup.js',
|
||||||
'/RomPatcher.js/js/formats/ppf.js',
|
'/RomPatcher.js/js/formats/ppf.js',
|
||||||
'/RomPatcher.js/js/formats/pmsr.js',
|
'/RomPatcher.js/js/formats/pmsr.js',
|
||||||
'/RomPatcher.js/js/formats/vcdiff.js'
|
'/RomPatcher.js/js/formats/vcdiff.js',
|
||||||
|
'/RomPatcher.js/js/formats/zip.js'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
90
index.html
90
index.html
|
@ -41,55 +41,42 @@
|
||||||
<script type="text/javascript" src="./js/formats/ppf.js"></script>
|
<script type="text/javascript" src="./js/formats/ppf.js"></script>
|
||||||
<script type="text/javascript" src="./js/formats/pmsr.js"></script>
|
<script type="text/javascript" src="./js/formats/pmsr.js"></script>
|
||||||
<script type="text/javascript" src="./js/formats/vcdiff.js"></script>
|
<script type="text/javascript" src="./js/formats/vcdiff.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="./js/zip.js/zip.js"></script>
|
<script type="text/javascript" src="./js/zip.js/zip.js"></script>
|
||||||
|
<!-- <script type="text/javascript" src="js/libunrar/rpc.js"></script> -->
|
||||||
|
|
||||||
<script type="text/javascript"><!--
|
<script type="text/javascript"><!--
|
||||||
/*
|
// CUSTOM PATCHER EXAMPLE
|
||||||
// PREDEFINED PATCHES EXAMPLE
|
// uncomment this to build your own custom exclusive patcher for your hacks/translations
|
||||||
// uncomment this to enable predefined patches, Rom Patcher JS will fetch patches hosted in your server
|
// user will only need to provide the ROM file, as patches will be fetched from your server!
|
||||||
// - format should be self explanatory
|
// a crc (or various crcs) can be provided for source files, allowing old formats like IPS to have validation!
|
||||||
// - you can add provide crc for source files, allowing IPS to have validation!
|
/*var CUSTOM_PATCHER=[
|
||||||
// - this could be also dynamically generated by your server backend, allowing you to build your own patcher for your projects
|
{ //example: uncompressed file
|
||||||
var PREDEFINED_PATCHES=[
|
file:'./_example/SML2DXv181.ips',
|
||||||
//zip includes a single patch (recommended)
|
name:'Super Mario Land 2 DX v1.8.1 (USA/Europe)',
|
||||||
{patch:'./_example/SONICDX.zip',name:'Sonic 3D Blast Director\'s Cut v1.1',crc:0x44a2ca44},
|
crc:0xd5ec24e4
|
||||||
|
},{ //example: uncompressed file
|
||||||
//if providing a zipped file, multiple patch files within it can be specified (recommended)
|
file:'./_example/SML2DXv181_jap.ips',
|
||||||
{patch:'./_example/SML2DXv181.zip#SML2DXv181.ips',name:'Super Mario Land 2 DX v1.8.1 (USA/Europe)',crc:0xd5ec24e4},
|
name:'Super Mario Land 2 DX v1.8.1 (Japan)',
|
||||||
{patch:'./_example/SML2DXv181.zip#SML2DXv181_jap.ips',name:'Super Mario Land 2 DX v1.8.1 (Japan)',crc:0xa715daf5},
|
crc:0xa715daf5
|
||||||
|
},{ //example: compressed file
|
||||||
//if a patch file is not specified in a zipped file, user will be able to choose the desired patch file in a popup (not recommended, also only a single crc for all patches could be provided)
|
file:'./_example/SML2DXv181.zip',
|
||||||
{patch:'./_example/SML2DXv181.zip',name:'Super Mario Land 2 DX v1.8.1 (All regions)'},
|
name:'Super Mario Land 2 DX v1.8.1 (World)',
|
||||||
|
crc:[0xd5ec24e4,0xa715daf5]
|
||||||
//uncompressed patch (not recommended because of bandwidth purposes)
|
},{ //example: compressed file containing several patches, separate patches provided (recommended)
|
||||||
{patch:'./_example/MarvelousATI_EN_v1.07.xdelta',name:'Marvelous (SFC) ENG Translation v1.07',crc:0xcedf3ba7}
|
file:'./_example/SML2DXv181.zip',
|
||||||
];
|
patches:[{
|
||||||
*/
|
file:'SML2DXv181.ips',
|
||||||
|
name:'Super Mario Land 2 DX v1.8.1 (USA/Europe)',
|
||||||
|
crc:0xd5ec24e4
|
||||||
|
},{
|
||||||
|
file:'SML2DXv181_jap.ips',
|
||||||
|
name:'Super Mario Land 2 DX v1.8.1 (Japan)',
|
||||||
|
crc:0xa715daf5
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
];*/
|
||||||
--></script>
|
--></script>
|
||||||
|
|
||||||
|
|
||||||
<!-- custom code for RHDN -->
|
|
||||||
<!--
|
|
||||||
<?php
|
|
||||||
if(isset($_REQUEST["file"]) && preg_match("/^(hacks|translations)\/\d+$/", $_REQUEST["file"]) && isset($_REQUEST["patch_name"])){
|
|
||||||
$patch="/download/".$_REQUEST["file"];
|
|
||||||
if(isset($_REQUEST["patch"])){
|
|
||||||
$patch.='#'+strip_tags(trim($_REQUEST["patch"]))
|
|
||||||
}
|
|
||||||
$patch_name=strip_tags(trim($_REQUEST["patch_name"]));
|
|
||||||
$crc="";
|
|
||||||
if(isset($_REQUEST["crc"]) && preg_match("/^[0-9a-fA-F]{8}$/", $_REQUEST["crc"])){
|
|
||||||
$crc=', crc:0x'.$_REQUEST["crc"];
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<script type="text/javascript">
|
|
||||||
var PREDEFINED_PATCHES=[{patch:'<?= strip_tags($patch); ?>', name:'<?= strip_tags($patch_name); ?>'<?= $crc?>}];
|
|
||||||
</script>
|
|
||||||
<?php
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
-->
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body><div id="column">
|
<body><div id="column">
|
||||||
|
|
||||||
|
@ -113,13 +100,13 @@
|
||||||
<div class="leftcol">MD5:</div><div class="rightcol"><span id="md5"></span></div>
|
<div class="leftcol">MD5:</div><div class="rightcol"><span id="md5"></span></div>
|
||||||
<div class="leftcol">SHA-1:</div><div class="rightcol"><span id="sha1"></span></div>
|
<div class="leftcol">SHA-1:</div><div class="rightcol"><span id="sha1"></span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row" id="row-removeheader">
|
<div class="row hide" id="row-removeheader">
|
||||||
<div class="leftcol"></div>
|
<div class="leftcol"></div>
|
||||||
<div class="rightcol">
|
<div class="rightcol">
|
||||||
<input type="checkbox" id="checkbox-removeheader" /> <label for="checkbox-removeheader" data-localize="remove_header">Remove header before patching</label>
|
<input type="checkbox" id="checkbox-removeheader" /> <label for="checkbox-removeheader" data-localize="remove_header">Remove header before patching</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row" id="row-addheader">
|
<div class="row hide" id="row-addheader">
|
||||||
<div class="leftcol"></div>
|
<div class="leftcol"></div>
|
||||||
<div class="rightcol">
|
<div class="rightcol">
|
||||||
<input type="checkbox" id="checkbox-addheader" /> <label for="checkbox-addheader" data-localize="add_header">Add temporary header</label> <small>(<label id="headersize" for="checkbox-addheader"></label>)</small>
|
<input type="checkbox" id="checkbox-addheader" /> <label for="checkbox-addheader" data-localize="add_header">Add temporary header</label> <small>(<label id="headersize" for="checkbox-addheader"></label>)</small>
|
||||||
|
@ -186,18 +173,19 @@
|
||||||
<div>
|
<div>
|
||||||
<select id="select-language">
|
<select id="select-language">
|
||||||
<option value="en">English</option>
|
<option value="en">English</option>
|
||||||
<option value="nl">Nederlands</option>
|
<option value="fr">Français</option>
|
||||||
<option value="sv">Svenska</option>
|
|
||||||
<option value="de">Deutsch</option>
|
<option value="de">Deutsch</option>
|
||||||
<option value="es">Español</option>
|
<option value="es">Español</option>
|
||||||
|
<option value="nl">Nederlands</option>
|
||||||
|
<option value="sv">Svenska</option>
|
||||||
<option value="ca">Català</option>
|
<option value="ca">Català</option>
|
||||||
<option value="ptb">Português Brasileiro</option>
|
<option value="pt-br">Português Brasileiro</option>
|
||||||
<option value="ru">Russian</option>
|
<option value="ru">Russian</option>
|
||||||
<option value="ja">日本語</option>
|
<option value="ja">日本語</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
Rom Patcher JS <small>v2.4</small> by <a href="/">Marc Robledo</a>
|
Rom Patcher JS <small>v2.5</small> by <a href="/">Marc Robledo</a>
|
||||||
<br />
|
<br />
|
||||||
<i class="icon github"></i> <a href="https://github.com/marcrobledo/RomPatcher.js/" target="_blank">See on GitHub</a>
|
<i class="icon github"></i> <a href="https://github.com/marcrobledo/RomPatcher.js/" target="_blank">See on GitHub</a>
|
||||||
<i class="icon heart"></i> <a href="https://www.paypal.me/marcrobledo/5" target="_blank" rel="nofollow">Donate</a>
|
<i class="icon heart"></i> <a href="https://www.paypal.me/marcrobledo/5" target="_blank" rel="nofollow">Donate</a>
|
||||||
|
|
217
js/RomPatcher.js
217
js/RomPatcher.js
|
@ -1,4 +1,4 @@
|
||||||
/* Rom Patcher JS v20201106 - Marc Robledo 2016-2020 - http://www.marcrobledo.com/license */
|
/* Rom Patcher JS v20210920 - Marc Robledo 2016-2021 - http://www.marcrobledo.com/license */
|
||||||
|
|
||||||
const TOO_BIG_ROM_SIZE=67108863;
|
const TOO_BIG_ROM_SIZE=67108863;
|
||||||
const HEADERS_INFO=[
|
const HEADERS_INFO=[
|
||||||
|
@ -15,13 +15,12 @@ const HEADERS_INFO=[
|
||||||
const FORCE_HTTPS=true;
|
const FORCE_HTTPS=true;
|
||||||
if(FORCE_HTTPS && location.protocol==='http:')
|
if(FORCE_HTTPS && location.protocol==='http:')
|
||||||
location.href=window.location.href.replace('http:','https:');
|
location.href=window.location.href.replace('http:','https:');
|
||||||
else if(location.protocol==='https:' && 'serviceWorker' in navigator)
|
else if(location.protocol==='https:' && 'serviceWorker' in navigator && window.location.hostname==='www.marcrobledo.com')
|
||||||
navigator.serviceWorker.register('/RomPatcher.js/_cache_service_worker.js', {scope: '/RomPatcher.js/'});
|
navigator.serviceWorker.register('/RomPatcher.js/_cache_service_worker.js', {scope: '/RomPatcher.js/'});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var romFile, patchFile, patch, romFile1, romFile2, tempFile, headerSize, oldHeader;
|
var romFile, patchFile, patch, romFile1, romFile2, tempFile, headerSize, oldHeader;
|
||||||
var fetchedPatches;
|
|
||||||
var userLanguage;
|
var userLanguage;
|
||||||
|
|
||||||
var CAN_USE_WEB_WORKERS=true;
|
var CAN_USE_WEB_WORKERS=true;
|
||||||
|
@ -99,42 +98,78 @@ function _(str){return userLanguage[str] || str}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function fetchPatch(uri){
|
|
||||||
|
|
||||||
|
/* custom patcher */
|
||||||
|
function isCustomPatcherEnabled(){
|
||||||
|
return typeof CUSTOM_PATCHER!=='undefined' && typeof CUSTOM_PATCHER==='object' && CUSTOM_PATCHER.length
|
||||||
|
}
|
||||||
|
function parseCustomPatch(customPatch){
|
||||||
|
patchFile=customPatch.fetchedFile;
|
||||||
|
patchFile.seek(0);
|
||||||
|
_readPatchFile();
|
||||||
|
|
||||||
|
if(typeof patch.validateSource === 'undefined'){
|
||||||
|
if(typeof customPatch.crc==='number'){
|
||||||
|
patch.validateSource=function(romFile,headerSize){
|
||||||
|
return customPatch.crc===crc32(romFile, headerSize)
|
||||||
|
}
|
||||||
|
}else if(typeof customPatch.crc==='object'){
|
||||||
|
patch.validateSource=function(romFile,headerSize){
|
||||||
|
for(var i=0; i<customPatch.crc.length; i++)
|
||||||
|
if(customPatch.crc[i]===crc32(romFile, headerSize))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
validateSource();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function fetchPatch(customPatchIndex, compressedFileIndex){
|
||||||
|
var customPatch=CUSTOM_PATCHER[customPatchIndex];
|
||||||
|
|
||||||
setTabApplyEnabled(false);
|
setTabApplyEnabled(false);
|
||||||
setMessage('apply', _('downloading'), 'loading');
|
setMessage('apply', _('downloading'), 'loading');
|
||||||
|
|
||||||
|
var uri=decodeURI(customPatch.file.trim());
|
||||||
|
|
||||||
var isCompressed=/\#/.test(uri);
|
|
||||||
var patchURI=decodeURI(uri.replace(/\#.*?$/, ''));
|
|
||||||
//console.log(patchURI);
|
//console.log(patchURI);
|
||||||
var compressedName=uri.replace(/^.*?\#/,'');
|
|
||||||
//console.log(compressedName);
|
|
||||||
|
|
||||||
|
|
||||||
if(typeof window.fetch==='function'){
|
if(typeof window.fetch==='function'){
|
||||||
fetch(patchURI)
|
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 => {
|
||||||
fetchedPatches[patchURI]=patchFile=new MarcFile(arrayBuffer);
|
patchFile=CUSTOM_PATCHER[customPatchIndex].fetchedFile=new MarcFile(arrayBuffer);
|
||||||
fetchedPatches[patchURI].fileName=patchURI.replace(/^(.*?\/)+/g, '');
|
patchFile.fileName=customPatch.file.replace(/^.*[\/\\]/g,'');
|
||||||
_readPatchFile();
|
|
||||||
|
if(patchFile.readString(4).startsWith(ZIP_MAGIC))
|
||||||
|
ZIPManager.parseFile(CUSTOM_PATCHER[customPatchIndex].fetchedFile, compressedFileIndex);
|
||||||
|
else
|
||||||
|
parseCustomPatch(CUSTOM_PATCHER[customPatchIndex]);
|
||||||
|
|
||||||
|
setMessage('apply');
|
||||||
})
|
})
|
||||||
.catch(function(evt){
|
.catch(function(evt){
|
||||||
setMessage('apply', _('error_downloading'), 'error');
|
setMessage('apply', (_('error_downloading')/* + evt.message */).replace('%s', CUSTOM_PATCHER[customPatchIndex].file.replace(/^.*[\/\\]/g,'')), 'error');
|
||||||
//setMessage('apply', evt.message, 'error');
|
|
||||||
});
|
});
|
||||||
}else{
|
}else{
|
||||||
var xhr=new XMLHttpRequest();
|
var xhr=new XMLHttpRequest();
|
||||||
xhr.open('GET', patchURI, true);
|
xhr.open('GET', uri, true);
|
||||||
xhr.responseType='arraybuffer';
|
xhr.responseType='arraybuffer';
|
||||||
|
|
||||||
xhr.onload=function(evt){
|
xhr.onload=function(evt){
|
||||||
if(this.status===200){
|
if(this.status===200){
|
||||||
fetchedPatches[patchURI]=patchFile=new MarcFile(xhr.response);
|
patchFile=CUSTOM_PATCHER[customPatchIndex].fetchedFile=new MarcFile(xhr.response);
|
||||||
fetchedPatches[patchURI].fileName=patchURI.replace(/^(.*?\/)+/g, '');
|
patchFile.fileName=customPatch.file.replace(/^.*[\/\\]/g,'');
|
||||||
_readPatchFile();
|
|
||||||
|
if(patchFile.readString(4).startsWith(ZIP_MAGIC))
|
||||||
|
ZIPManager.parseFile(CUSTOM_PATCHER[customPatchIndex].fetchedFile, compressedFileIndex);
|
||||||
|
else
|
||||||
|
parseCustomPatch(CUSTOM_PATCHER[customPatchIndex]);
|
||||||
|
|
||||||
|
setMessage('apply');
|
||||||
}else{
|
}else{
|
||||||
setMessage('apply', _('error_downloading')+' ('+this.status+')', 'error');
|
setMessage('apply', _('error_downloading').replace('%s', CUSTOM_PATCHER[customPatchIndex].file.replace(/^.*[\/\\]/g,''))+' ('+this.status+')', 'error');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -146,29 +181,28 @@ function fetchPatch(uri){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function _parseROM(){
|
function _parseROM(){
|
||||||
el('checkbox-addheader').checked=false;
|
el('checkbox-addheader').checked=false;
|
||||||
el('checkbox-removeheader').checked=false;
|
el('checkbox-removeheader').checked=false;
|
||||||
|
|
||||||
if(romFile.readString(4).startsWith(ZIP_MAGIC)){
|
if(romFile.readString(4).startsWith(ZIP_MAGIC)){
|
||||||
parseZIPFile(romFile);
|
ZIPManager.parseFile(romFile);
|
||||||
setTabApplyEnabled(false);
|
setTabApplyEnabled(false);
|
||||||
}else{
|
}else{
|
||||||
if(headerSize=canHaveFakeHeader(romFile)){
|
if(headerSize=canHaveFakeHeader(romFile)){
|
||||||
el('row-addheader').style.display='flex';
|
el('row-addheader').className='row';
|
||||||
if(headerSize<1024){
|
if(headerSize<1024){
|
||||||
el('headersize').innerHTML=headerSize+'b';
|
el('headersize').innerHTML=headerSize+'b';
|
||||||
}else{
|
}else{
|
||||||
el('headersize').innerHTML=parseInt(headerSize/1024)+'kb';
|
el('headersize').innerHTML=parseInt(headerSize/1024)+'kb';
|
||||||
}
|
}
|
||||||
el('row-removeheader').style.display='none';
|
el('row-removeheader').className='row hide';
|
||||||
}else if(headerSize=hasHeader(romFile)){
|
}else if(headerSize=hasHeader(romFile)){
|
||||||
el('row-addheader').style.display='none';
|
el('row-addheader').className='row hide';
|
||||||
el('row-removeheader').style.display='flex';
|
el('row-removeheader').className='row';
|
||||||
}else{
|
}else{
|
||||||
el('row-addheader').style.display='none';
|
el('row-addheader').className='row hide';
|
||||||
el('row-removeheader').style.display='none';
|
el('row-removeheader').className='row hide';
|
||||||
}
|
}
|
||||||
|
|
||||||
updateChecksums(romFile, 0);
|
updateChecksums(romFile, 0);
|
||||||
|
@ -183,7 +217,7 @@ function setLanguage(langCode){
|
||||||
|
|
||||||
userLanguage=LOCALIZATION[langCode];
|
userLanguage=LOCALIZATION[langCode];
|
||||||
|
|
||||||
document.documentElement.lang = langCode;
|
document.documentElement.lang=langCode;
|
||||||
|
|
||||||
var translatableElements=document.querySelectorAll('*[data-localize]');
|
var translatableElements=document.querySelectorAll('*[data-localize]');
|
||||||
for(var i=0; i<translatableElements.length; i++){
|
for(var i=0; i<translatableElements.length; i++){
|
||||||
|
@ -223,11 +257,6 @@ addEvent(window,'load',function(){
|
||||||
el('input-file-patch').value='';
|
el('input-file-patch').value='';
|
||||||
setTabApplyEnabled(true);
|
setTabApplyEnabled(true);
|
||||||
|
|
||||||
addEvent(el('input-file-rom'), 'change', function(){
|
|
||||||
setTabApplyEnabled(false);
|
|
||||||
romFile=new MarcFile(this, _parseROM);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/* dirty fix for mobile Safari https://stackoverflow.com/a/19323498 */
|
/* dirty fix for mobile Safari https://stackoverflow.com/a/19323498 */
|
||||||
if(/Mobile\/\S+ Safari/.test(navigator.userAgent)){
|
if(/Mobile\/\S+ Safari/.test(navigator.userAgent)){
|
||||||
|
@ -237,36 +266,62 @@ addEvent(window,'load',function(){
|
||||||
|
|
||||||
|
|
||||||
/* predefined patches */
|
/* predefined patches */
|
||||||
if(typeof PREDEFINED_PATCHES!=='undefined'){
|
if(isCustomPatcherEnabled()){
|
||||||
fetchedPatches={};
|
|
||||||
|
|
||||||
var container=el('input-file-patch').parentElement;
|
|
||||||
container.removeChild(el('input-file-patch'));
|
|
||||||
|
|
||||||
var select=document.createElement('select');
|
var select=document.createElement('select');
|
||||||
|
select.disabled=true;
|
||||||
select.id='input-file-patch';
|
select.id='input-file-patch';
|
||||||
for(var i=0; i<PREDEFINED_PATCHES.length; i++){
|
el('input-file-patch').parentElement.replaceChild(select, el('input-file-patch'));
|
||||||
var option=document.createElement('option');
|
select.parentElement.title='';
|
||||||
option.value=PREDEFINED_PATCHES[i].patch;
|
|
||||||
option.innerHTML=PREDEFINED_PATCHES[i].name;
|
|
||||||
select.appendChild(option);
|
|
||||||
}
|
|
||||||
container.appendChild(select)
|
|
||||||
container.parentElement.title='';
|
|
||||||
|
|
||||||
|
for(var i=0; i<CUSTOM_PATCHER.length; i++){
|
||||||
|
CUSTOM_PATCHER[i].fetchedFile=false;
|
||||||
|
|
||||||
|
CUSTOM_PATCHER[i].selectOption=document.createElement('option');
|
||||||
|
CUSTOM_PATCHER[i].selectOption.value=i;
|
||||||
|
CUSTOM_PATCHER[i].selectOption.innerHTML=CUSTOM_PATCHER[i].name || CUSTOM_PATCHER[i].file;
|
||||||
|
select.appendChild(CUSTOM_PATCHER[i].selectOption);
|
||||||
|
|
||||||
|
if(typeof CUSTOM_PATCHER[i].patches==='object'){
|
||||||
|
for(var j=0; j<CUSTOM_PATCHER[i].patches.length; j++){
|
||||||
|
if(j===0){
|
||||||
|
CUSTOM_PATCHER[i].patches[0].selectOption=CUSTOM_PATCHER[i].selectOption;
|
||||||
|
CUSTOM_PATCHER[i].selectOption=null;
|
||||||
|
}else{
|
||||||
|
CUSTOM_PATCHER[i].patches[j].selectOption=document.createElement('option');
|
||||||
|
select.appendChild(CUSTOM_PATCHER[i].patches[j].selectOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_PATCHER[i].patches[j].selectOption.value=i+','+j;
|
||||||
|
CUSTOM_PATCHER[i].patches[j].selectOption.innerHTML=CUSTOM_PATCHER[i].patches[j].name || CUSTOM_PATCHER[i].patches[j].file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
addEvent(select,'change',function(){
|
addEvent(select,'change',function(){
|
||||||
if(fetchedPatches[this.value.replace(/\#.*?$/, '')]){
|
var selectedCustomPatchIndex, selectedCustomPatchCompressedIndex, selectedPatch;
|
||||||
patchFile=fetchedPatches[this.value.replace(/\#.*?$/, '')];
|
|
||||||
patchFile.seek(0);
|
if(/^\d+,\d+$/.test(this.value)){
|
||||||
_readPatchFile();
|
var indexes=this.value.split(',');
|
||||||
|
selectedCustomPatchIndex=parseInt(indexes[0]);
|
||||||
|
selectedCustomPatchCompressedIndex=parseInt(indexes[1]);
|
||||||
|
selectedPatch=CUSTOM_PATCHER[selectedCustomPatchIndex].patches[selectedCustomPatchCompressedIndex];
|
||||||
|
}else{
|
||||||
|
selectedCustomPatchIndex=parseInt(this.value);
|
||||||
|
selectedCustomPatchCompressedIndex=null;
|
||||||
|
selectedPatch=CUSTOM_PATCHER[selectedCustomPatchIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(selectedPatch.fetchedFile){
|
||||||
|
parseCustomPatch(selectedPatch);
|
||||||
}else{
|
}else{
|
||||||
patch=null;
|
patch=null;
|
||||||
patchFile=null;
|
patchFile=null;
|
||||||
fetchPatch(this.value);
|
fetchPatch(selectedCustomPatchIndex, selectedCustomPatchCompressedIndex);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
fetchPatch(select.value);
|
fetchPatch(0, 0);
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
setTabCreateEnabled(true);
|
setTabCreateEnabled(true);
|
||||||
el('input-file-rom1').value='';
|
el('input-file-rom1').value='';
|
||||||
|
@ -290,14 +345,40 @@ addEvent(window,'load',function(){
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* event listeners */
|
||||||
|
addEvent(el('input-file-rom'), 'change', function(){
|
||||||
|
setTabApplyEnabled(false);
|
||||||
|
romFile=new MarcFile(this, _parseROM);
|
||||||
|
});
|
||||||
addEvent(el('checkbox-removeheader'), 'change', function(){
|
addEvent(el('checkbox-removeheader'), 'change', function(){
|
||||||
if(this.checked)
|
if(this.checked)
|
||||||
updateChecksums(romFile, headerSize);
|
updateChecksums(romFile, headerSize);
|
||||||
else
|
else
|
||||||
updateChecksums(romFile, 0);
|
updateChecksums(romFile, 0);
|
||||||
});
|
});
|
||||||
|
addEvent(el('switch-create-button'), 'click', function(){
|
||||||
|
setCreatorMode(!/enabled/.test(el('switch-create').className));
|
||||||
|
});
|
||||||
|
addEvent(el('button-apply'), 'click', function(){
|
||||||
|
applyPatch(patch, romFile, false);
|
||||||
|
});
|
||||||
|
addEvent(el('button-create'), 'click', function(){
|
||||||
|
createPatch(romFile1, romFile2, el('select-patch-type').value);
|
||||||
|
});
|
||||||
|
addEvent(el('select-language'), 'change', function(){
|
||||||
|
setLanguage(this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//setCreatorMode(true);
|
//setCreatorMode(true);
|
||||||
});
|
});
|
||||||
|
@ -390,14 +471,10 @@ function _readPatchFile(){
|
||||||
|
|
||||||
var header=patchFile.readString(6);
|
var header=patchFile.readString(6);
|
||||||
if(header.startsWith(ZIP_MAGIC)){
|
if(header.startsWith(ZIP_MAGIC)){
|
||||||
if(typeof PREDEFINED_PATCHES !== 'undefined' && /\#/.test(el('input-file-patch').value)){
|
|
||||||
parseZIPFile(patchFile, el('input-file-patch').value.replace(/^.*?\#/, ''));
|
|
||||||
}else{
|
|
||||||
parseZIPFile(patchFile);
|
|
||||||
}
|
|
||||||
patch=false;
|
patch=false;
|
||||||
validateSource();
|
validateSource();
|
||||||
setTabApplyEnabled(false);
|
setTabApplyEnabled(false);
|
||||||
|
ZIPManager.parseFile(patchFile);
|
||||||
}else{
|
}else{
|
||||||
if(header.startsWith(IPS_MAGIC)){
|
if(header.startsWith(IPS_MAGIC)){
|
||||||
patch=parseIPSFile(patchFile);
|
patch=parseIPSFile(patchFile);
|
||||||
|
@ -420,12 +497,6 @@ function _readPatchFile(){
|
||||||
setMessage('apply', _('error_invalid_patch'), 'error');
|
setMessage('apply', _('error_invalid_patch'), 'error');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(patch && typeof PREDEFINED_PATCHES!=='undefined' && PREDEFINED_PATCHES[el('input-file-patch').selectedIndex].crc){
|
|
||||||
patch.validateSource=function(romFile, headerSize){
|
|
||||||
return PREDEFINED_PATCHES[el('input-file-patch').selectedIndex].crc===crc32(romFile, headerSize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
validateSource();
|
validateSource();
|
||||||
setTabApplyEnabled(true);
|
setTabApplyEnabled(true);
|
||||||
}
|
}
|
||||||
|
@ -655,7 +726,7 @@ function setTabCreateEnabled(status){
|
||||||
function setTabApplyEnabled(status){
|
function setTabApplyEnabled(status){
|
||||||
setElementEnabled('input-file-rom', status);
|
setElementEnabled('input-file-rom', status);
|
||||||
setElementEnabled('input-file-patch', status);
|
setElementEnabled('input-file-patch', status);
|
||||||
if(romFile && status && (patch || typeof PREDEFINED_PATCHES!=='undefined')){
|
if(romFile && status && (patch || isCustomPatcherEnabled())){
|
||||||
setElementEnabled('button-apply', status);
|
setElementEnabled('button-apply', status);
|
||||||
}else{
|
}else{
|
||||||
setElementEnabled('button-apply', false);
|
setElementEnabled('button-apply', false);
|
||||||
|
@ -676,16 +747,6 @@ function setCreatorMode(creatorMode){
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Event listeners */
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
document.getElementById("switch-create-button").addEventListener('click', function(){setCreatorMode(!/enabled/.test(el('switch-create').className))})
|
|
||||||
document.getElementById("button-apply").addEventListener('click', function(){applyPatch(patch, romFile, false)})
|
|
||||||
document.getElementById("button-create").addEventListener('click', function(){createPatch(romFile1, romFile2, el('select-patch-type').value)})
|
|
||||||
document.getElementById("select-language").addEventListener('change', function(){setLanguage(this.value)})
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* FileSaver.js (source: http://purl.eligrey.com/github/FileSaver.js/blob/master/src/FileSaver.js)
|
/* FileSaver.js (source: http://purl.eligrey.com/github/FileSaver.js/blob/master/src/FileSaver.js)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Rom Patcher JS - CRC32/MD5/SHA-1/checksums calculators v20200926 - Marc Robledo 2016-2020 - http://www.marcrobledo.com/license */
|
/* Rom Patcher JS - CRC32/MD5/SHA-1/checksums calculators v20210815 - Marc Robledo 2016-2021 - http://www.marcrobledo.com/license */
|
||||||
|
|
||||||
function padZeroes(intVal, nBytes){
|
function padZeroes(intVal, nBytes){
|
||||||
var hexString=intVal.toString(16);
|
var hexString=intVal.toString(16);
|
||||||
|
@ -53,6 +53,7 @@ function md5(marcFile, headerSize){
|
||||||
for(i=0;i<16;i++)tail[i]=0;
|
for(i=0;i<16;i++)tail[i]=0;
|
||||||
}
|
}
|
||||||
tail[14]=n*8;
|
tail[14]=n*8;
|
||||||
|
tail[15]=Math.floor(n/536870912) >>> 0; //if file is bigger than 512Mb*8, value is bigger than 32 bits, so it needs two words to store its length
|
||||||
_md5cycle(state,tail);
|
_md5cycle(state,tail);
|
||||||
|
|
||||||
for(var i=0;i<state.length;i++){
|
for(var i=0;i<state.length;i++){
|
||||||
|
|
|
@ -1,83 +1,150 @@
|
||||||
/* ZIP module for Rom Patcher JS v20190531 - Marc Robledo 2016-2019 - http://www.marcrobledo.com/license */
|
/* ZIP module for Rom Patcher JS v20210815 - Marc Robledo 2016-2021 - http://www.marcrobledo.com/license */
|
||||||
|
|
||||||
const ZIP_MAGIC='\x50\x4b\x03\x04';
|
const ZIP_MAGIC='\x50\x4b\x03\x04';
|
||||||
|
|
||||||
function parseZIPFile(zipFile, unzipEntryName){
|
var ZIPManager=(function(){
|
||||||
var regex=(zipFile===patchFile)? /\.(ips|ups|bps|aps|rup|ppf|xdelta)$/i : /\.(\w+)$/i;
|
const FILTER_PATCHES=/\.(ips|ups|bps|aps|rup|ppf|xdelta)$/i;
|
||||||
setMessage('apply', _('unzipping'), 'loading');
|
const FILTER_ROMS=/(?<!\.(txt|diz|rtf|docx?|html?|pdf|jpe?g|gif|png|bmp|zip|rar|7z))$/i;
|
||||||
|
|
||||||
var arrayBuffer=zipFile._u8array.buffer;
|
var _unzipEntry=function(zippedEntry, dest, dest2, parse){
|
||||||
zip.createReader(
|
zippedEntry.getData(new zip.BlobWriter(), function(blob){
|
||||||
new zip.BlobReader(new Blob([arrayBuffer])),
|
|
||||||
function(zipReader){
|
|
||||||
zipReader.getEntries(function(zipEntries){
|
|
||||||
var zippedFiles=[];
|
|
||||||
for(var i=0; i<zipEntries.length; i++){
|
|
||||||
if(typeof unzipEntryName==='string' && unzipEntryName === zipEntries[i].filename){
|
|
||||||
zippedFiles=[zipEntries[i]];
|
|
||||||
break;
|
|
||||||
}else if(regex.test(zipEntries[i].filename)){
|
|
||||||
zippedFiles.push(zipEntries[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(zippedFiles.length>1){
|
|
||||||
var zipOverlay=document.createElement('div');
|
|
||||||
zipOverlay.className='zip-overlay';
|
|
||||||
var zipDialog=document.createElement('div');
|
|
||||||
zipDialog.className='zip-dialog';
|
|
||||||
var zipList=document.createElement('ul');
|
|
||||||
zipList.className='zipped-files'
|
|
||||||
for(var i=0; i<zippedFiles.length; i++){
|
|
||||||
var li=document.createElement('li');
|
|
||||||
li.zipEntry=zippedFiles[i];
|
|
||||||
li.zipEntry.originalZipFile=zipFile;
|
|
||||||
li.innerHTML=zippedFiles[i].filename;
|
|
||||||
addEvent(li, 'click', _evtClickZipEntry);
|
|
||||||
zipList.appendChild(li);
|
|
||||||
}
|
|
||||||
zipDialog.innerHTML=_('patch_file');
|
|
||||||
zipDialog.appendChild(zipList);
|
|
||||||
zipOverlay.appendChild(zipDialog);
|
|
||||||
document.body.appendChild(zipOverlay);
|
|
||||||
}else if(zippedFiles.length===1){
|
|
||||||
zippedFiles[0].originalZipFile=zipFile;
|
|
||||||
unzipEntry(zippedFiles[0]);
|
|
||||||
}else{
|
|
||||||
if(zipFile===romFile){
|
|
||||||
romFile=null;
|
|
||||||
}else{
|
|
||||||
patchFile=null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setTabApplyEnabled(true);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
function(zipReader){
|
|
||||||
setTabApplyEnabled(true);
|
|
||||||
setMessage('apply', _('error_unzipping'), 'error');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function unzipEntry(zipEntry){
|
|
||||||
zipEntry.getData(new zip.BlobWriter(), function(blob){
|
|
||||||
var fileReader=new FileReader();
|
var fileReader=new FileReader();
|
||||||
fileReader.onload=function(){
|
fileReader.onload=function(){
|
||||||
var unzippedFile=new MarcFile(this.result);
|
var unzippedFile=new MarcFile(this.result);
|
||||||
unzippedFile.fileName=zipEntry.filename;
|
unzippedFile.fileName=zippedEntry.filename;
|
||||||
if(zipEntry.originalZipFile===romFile){
|
|
||||||
|
if(dest.patches){
|
||||||
|
dest.patches[dest2].fetchedFile=unzippedFile;
|
||||||
|
if(parse)
|
||||||
|
parseCustomPatch(dest.patches[dest2]);
|
||||||
|
}if(dest===romFile){
|
||||||
romFile=unzippedFile;
|
romFile=unzippedFile;
|
||||||
_parseROM();
|
_parseROM();
|
||||||
}else if(zipEntry.originalZipFile===patchFile){
|
}else if(dest===patchFile){
|
||||||
patchFile=unzippedFile;
|
patchFile=unzippedFile;
|
||||||
_readPatchFile();
|
_readPatchFile();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
fileReader.readAsArrayBuffer(blob);
|
fileReader.readAsArrayBuffer(blob);
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
function _evtClickZipEntry(evt){
|
return{
|
||||||
|
parseFile:function(sourceFile, compressedFileIndex){
|
||||||
|
setMessage('apply', _('unzipping'), 'loading');
|
||||||
|
|
||||||
|
var arrayBuffer=sourceFile._u8array.buffer;
|
||||||
|
zip.createReader(
|
||||||
|
new zip.BlobReader(new Blob([arrayBuffer])),
|
||||||
|
/* success */
|
||||||
|
function(zipReader){
|
||||||
|
zipReader.getEntries(function(zipEntries){
|
||||||
|
var regex=(sourceFile===romFile)? FILTER_ROMS : FILTER_PATCHES;
|
||||||
|
var filteredEntries=[];
|
||||||
|
for(var i=0; i<zipEntries.length; i++){
|
||||||
|
if(regex.test(zipEntries[i].filename) && !zipEntries[i].directory){
|
||||||
|
filteredEntries.push(zipEntries[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var customPatch=false;
|
||||||
|
if(isCustomPatcherEnabled()){
|
||||||
|
for(var i=0; i<CUSTOM_PATCHER.length && !customPatch; i++){
|
||||||
|
if(CUSTOM_PATCHER[i].fetchedFile===sourceFile)
|
||||||
|
customPatch=CUSTOM_PATCHER[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(customPatch){
|
||||||
|
if(customPatch.patches){
|
||||||
|
for(var i=0; i<customPatch.patches.length; i++){
|
||||||
|
for(var j=0; j<filteredEntries.length; j++){
|
||||||
|
if(customPatch.patches[i].file===filteredEntries[j].filename){
|
||||||
|
_unzipEntry(filteredEntries[j], customPatch, i, i===compressedFileIndex);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
var nextOption;
|
||||||
|
var customPatchIndex=CUSTOM_PATCHER.indexOf(customPatch);
|
||||||
|
customPatch.patches=[];
|
||||||
|
for(var i=0; i<filteredEntries.length; i++){
|
||||||
|
customPatch.patches.push({
|
||||||
|
file:filteredEntries[i].filename,
|
||||||
|
fetchedFile:false,
|
||||||
|
name:customPatch.name + ' - ' + filteredEntries[i].filename,
|
||||||
|
crc:customPatch.crc
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var option;
|
||||||
|
if(i===0){
|
||||||
|
option=customPatch.selectOption;
|
||||||
|
nextOption=option.nextSibling;
|
||||||
|
}else{
|
||||||
|
option=document.createElement('option');
|
||||||
|
if(nextOption)
|
||||||
|
el('input-file-patch').insertBefore(option, nextOption);
|
||||||
|
else
|
||||||
|
el('input-file-patch').appendChild(option);
|
||||||
|
}
|
||||||
|
option.value=customPatchIndex+','+i;
|
||||||
|
option.innerHTML=customPatch.patches[i].name;
|
||||||
|
nextOption=option.nextSibling;
|
||||||
|
_unzipEntry(filteredEntries[i], customPatch, i, i===0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
setTabApplyEnabled(false);
|
||||||
|
}else{
|
||||||
|
var _evtClickDialogEntry=function(evt){
|
||||||
document.body.removeChild(this.parentElement.parentElement.parentElement);
|
document.body.removeChild(this.parentElement.parentElement.parentElement);
|
||||||
unzipEntry(this.zipEntry);
|
_unzipEntry(this.zipEntry, sourceFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(filteredEntries.length>1){
|
||||||
|
var zipOverlay=document.createElement('div');
|
||||||
|
zipOverlay.className='zip-overlay';
|
||||||
|
var zipDialog=document.createElement('div');
|
||||||
|
zipDialog.className='zip-dialog';
|
||||||
|
var zipList=document.createElement('ul');
|
||||||
|
zipList.className='zipped-files'
|
||||||
|
for(var i=0; i<filteredEntries.length; i++){
|
||||||
|
var li=document.createElement('li');
|
||||||
|
li.zipEntry=filteredEntries[i];
|
||||||
|
li.innerHTML=filteredEntries[i].filename;
|
||||||
|
addEvent(li, 'click', _evtClickDialogEntry);
|
||||||
|
zipList.appendChild(li);
|
||||||
|
}
|
||||||
|
zipDialog.innerHTML=_('patch_file');
|
||||||
|
zipDialog.appendChild(zipList);
|
||||||
|
zipOverlay.appendChild(zipDialog);
|
||||||
|
document.body.appendChild(zipOverlay);
|
||||||
|
}else if(filteredEntries.length===1){
|
||||||
|
_unzipEntry(filteredEntries[0], sourceFile);
|
||||||
|
}else{
|
||||||
|
if(sourceFile===romFile){
|
||||||
|
romFile=null;
|
||||||
|
}else if(sourceFile===patchFile){
|
||||||
|
patchFile=null;
|
||||||
|
setMessage('apply', _('error_invalid_patch'), 'error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setTabApplyEnabled(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/* failed */
|
||||||
|
function(zipReader){
|
||||||
|
setTabApplyEnabled(true);
|
||||||
|
setMessage('apply', _('error_unzipping'), 'error');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
63
js/locale.js
63
js/locale.js
|
@ -21,11 +21,39 @@ const LOCALIZATION={
|
||||||
'error_crc_input': 'Source ROM checksum mismatch',
|
'error_crc_input': 'Source ROM checksum mismatch',
|
||||||
'error_crc_output': 'Target ROM checksum mismatch',
|
'error_crc_output': 'Target ROM checksum mismatch',
|
||||||
'error_crc_patch': 'Patch checksum mismatch',
|
'error_crc_patch': 'Patch checksum mismatch',
|
||||||
'error_downloading': 'Error downloading patch',
|
'error_downloading': 'Error downloading %s',
|
||||||
'error_unzipping': 'Error unzipping file',
|
'error_unzipping': 'Error unzipping file',
|
||||||
'error_invalid_patch': 'Invalid patch file',
|
'error_invalid_patch': 'Invalid patch file',
|
||||||
'warning_too_big': 'Using big files is not recommended.'
|
'warning_too_big': 'Using big files is not recommended.'
|
||||||
},
|
},
|
||||||
|
'es':{
|
||||||
|
'creator_mode': 'Modo creador',
|
||||||
|
|
||||||
|
'apply_patch': 'Aplicar parche',
|
||||||
|
'rom_file': 'Archivo ROM:',
|
||||||
|
'patch_file': 'Archivo parche:',
|
||||||
|
'remove_header': 'Quitar cabecera',
|
||||||
|
'add_header': 'Añadir cabecera temporal',
|
||||||
|
'compatible_formats': 'Formatos compatibles:',
|
||||||
|
'applying_patch': 'Aplicando parche...',
|
||||||
|
'downloading': 'Descargando...',
|
||||||
|
'unzipping': 'Descomprimiendo...',
|
||||||
|
|
||||||
|
'create_patch': 'Crear parche',
|
||||||
|
'original_rom': 'ROM original:',
|
||||||
|
'modified_rom': 'ROM modificada:',
|
||||||
|
'patch_type': 'Tipo de parche:',
|
||||||
|
'creating_patch': 'Creando parche...',
|
||||||
|
|
||||||
|
'error_crc_input': 'Checksum de ROM original no válida',
|
||||||
|
'error_crc_output': 'Checksum de ROM creada no válida',
|
||||||
|
'error_crc_patch': 'Checksum de parche no válida',
|
||||||
|
'error_downloading': 'Error descargando %s',
|
||||||
|
'error_unzipping': 'Error descomprimiendo archivo',
|
||||||
|
'error_unzipping': 'Error descomprimiendo archivo',
|
||||||
|
'error_invalid_patch': 'Archivo de parche no válido',
|
||||||
|
'warning_too_big': 'No se recomienda usar archivos muy grandes.'
|
||||||
|
},
|
||||||
'nl':{
|
'nl':{
|
||||||
'creator_mode': 'Creator-modus',
|
'creator_mode': 'Creator-modus',
|
||||||
|
|
||||||
|
@ -79,33 +107,6 @@ const LOCALIZATION={
|
||||||
'error_unzipping': 'Det gick inte att packa upp filen',
|
'error_unzipping': 'Det gick inte att packa upp filen',
|
||||||
'error_invalid_patch': 'Ogiltig korrigeringsfil',
|
'error_invalid_patch': 'Ogiltig korrigeringsfil',
|
||||||
'warning_too_big': 'Användning av stora filer rekommenderas inte.'
|
'warning_too_big': 'Användning av stora filer rekommenderas inte.'
|
||||||
},
|
|
||||||
'es':{
|
|
||||||
'creator_mode': 'Modo creador',
|
|
||||||
|
|
||||||
'apply_patch': 'Aplicar parche',
|
|
||||||
'rom_file': 'Archivo ROM:',
|
|
||||||
'patch_file': 'Archivo parche:',
|
|
||||||
'remove_header': 'Quitar cabecera',
|
|
||||||
'add_header': 'Añadir cabecera temporal',
|
|
||||||
'compatible_formats': 'Formatos compatibles:',
|
|
||||||
'applying_patch': 'Aplicando parche...',
|
|
||||||
'downloading': 'Descargando...',
|
|
||||||
'unzipping': 'Descomprimiendo...',
|
|
||||||
|
|
||||||
'create_patch': 'Crear parche',
|
|
||||||
'original_rom': 'ROM original:',
|
|
||||||
'modified_rom': 'ROM modificada:',
|
|
||||||
'patch_type': 'Tipo de parche:',
|
|
||||||
'creating_patch': 'Creando parche...',
|
|
||||||
|
|
||||||
'error_crc_input': 'Checksum de ROM original no válida',
|
|
||||||
'error_crc_output': 'Checksum de ROM creada no válida',
|
|
||||||
'error_crc_patch': 'Checksum de parche no válida',
|
|
||||||
'error_downloading': 'Error descargando parche',
|
|
||||||
'error_unzipping': 'Error descomprimiendo archivo',
|
|
||||||
'error_invalid_patch': 'Archivo de parche no válido',
|
|
||||||
'warning_too_big': 'No se recomienda usar archivos muy grandes.'
|
|
||||||
},
|
},
|
||||||
'ca':{
|
'ca':{
|
||||||
'creator_mode': 'Mode creador',
|
'creator_mode': 'Mode creador',
|
||||||
|
@ -129,7 +130,7 @@ const LOCALIZATION={
|
||||||
'error_crc_input': 'Checksum de ROM original no vàlida',
|
'error_crc_input': 'Checksum de ROM original no vàlida',
|
||||||
'error_crc_output': 'Checksum de ROM creada no vàlida',
|
'error_crc_output': 'Checksum de ROM creada no vàlida',
|
||||||
'error_crc_patch': 'Checksum de pedaç no vàlida',
|
'error_crc_patch': 'Checksum de pedaç no vàlida',
|
||||||
'error_downloading': 'Error descarregant pedaç',
|
'error_downloading': 'Error descarregant %s',
|
||||||
'error_unzipping': 'Error descomprimint arxiu',
|
'error_unzipping': 'Error descomprimint arxiu',
|
||||||
'error_invalid_patch': 'Arxiu de pedaç no vàlid',
|
'error_invalid_patch': 'Arxiu de pedaç no vàlid',
|
||||||
'warning_too_big': 'No es recomana usar arxius molt grans.'
|
'warning_too_big': 'No es recomana usar arxius molt grans.'
|
||||||
|
@ -183,12 +184,12 @@ const LOCALIZATION={
|
||||||
'error_crc_input': 'Prüfsumme der Input-ROM stimmt nicht überein',
|
'error_crc_input': 'Prüfsumme der Input-ROM stimmt nicht überein',
|
||||||
'error_crc_output': 'Prüfsumme der Output-ROM stimmt nicht überein',
|
'error_crc_output': 'Prüfsumme der Output-ROM stimmt nicht überein',
|
||||||
'error_crc_patch': 'Prüfsumme vom Patch stimmt nicht überein',
|
'error_crc_patch': 'Prüfsumme vom Patch stimmt nicht überein',
|
||||||
'error_downloading': 'Fehler beim Herunterladen vom Patch',
|
'error_downloading': 'Fehler beim Herunterladen vom %s',
|
||||||
'error_unzipping': 'Fehler beim Entpacken',
|
'error_unzipping': 'Fehler beim Entpacken',
|
||||||
'error_invalid_patch': 'Ungültiger Patch',
|
'error_invalid_patch': 'Ungültiger Patch',
|
||||||
'warning_too_big': 'Große Dateien zu verwenden ist nicht empfohlen.'
|
'warning_too_big': 'Große Dateien zu verwenden ist nicht empfohlen.'
|
||||||
},
|
},
|
||||||
'ptb':{
|
'pt-br':{
|
||||||
'creator_mode': 'Modo criador',
|
'creator_mode': 'Modo criador',
|
||||||
|
|
||||||
'apply_patch': 'Aplicar patch',
|
'apply_patch': 'Aplicar patch',
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* WebApps CSS template by Marc Robledo v20191106 */
|
/* Rom Patcher JS CSS template by Marc Robledo v20210815 */
|
||||||
/* minify at https://cssminifier.com/ + https://www.base64-image.de/ */
|
/* minify at https://cssminifier.com/ + https://www.base64-image.de/ */
|
||||||
|
|
||||||
/* @FONT-FACES */
|
/* @FONT-FACES */
|
||||||
|
@ -19,11 +19,6 @@ body{
|
||||||
user-select:none
|
user-select:none
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* hide header checkboxes */
|
|
||||||
#row-removeheader,#row-addheader{display:none}
|
|
||||||
|
|
||||||
|
|
||||||
/* flex main column */
|
/* flex main column */
|
||||||
html, body{height:100%}
|
html, body{height:100%}
|
||||||
#column{
|
#column{
|
||||||
|
@ -39,6 +34,7 @@ footer{padding: 50px 0 20px}
|
||||||
|
|
||||||
|
|
||||||
.clickable{cursor:pointer}
|
.clickable{cursor:pointer}
|
||||||
|
.hide{display:none !important}
|
||||||
|
|
||||||
|
|
||||||
/* flex box */
|
/* flex box */
|
||||||
|
@ -185,9 +181,10 @@ input[type=file].enabled:hover,select.enabled:hover{background-color:#dee1e1}
|
||||||
input[type=file].disabled,select.disabled{background-color:transparent}
|
input[type=file].disabled,select.disabled{background-color:transparent}
|
||||||
|
|
||||||
#select-language{
|
#select-language{
|
||||||
background-color:#31343a;
|
background-color:transparent;
|
||||||
color:white;
|
color:white;
|
||||||
cursor:pointer;
|
cursor:pointer;
|
||||||
|
text-align:center;
|
||||||
background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJmaWxsOiNmZmYiIHZlcnNpb249IjEuMSIgeD0iMTJweCIgeT0iMHB4IiB3aWR0aD0iMjRweCIgaGVpZ2h0PSIzcHgiIHZpZXdCb3g9IjAgMCA2IDMiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDYgMyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBvbHlnb24gcG9pbnRzPSI1Ljk5MiwwIDIuOTkyLDMgLTAuMDA4LDAgIi8+PC9zdmc+");
|
background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHN0eWxlPSJmaWxsOiNmZmYiIHZlcnNpb249IjEuMSIgeD0iMTJweCIgeT0iMHB4IiB3aWR0aD0iMjRweCIgaGVpZ2h0PSIzcHgiIHZpZXdCb3g9IjAgMCA2IDMiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDYgMyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBvbHlnb24gcG9pbnRzPSI1Ljk5MiwwIDIuOTkyLDMgLTAuMDA4LDAgIi8+PC9zdmc+");
|
||||||
}
|
}
|
||||||
#select-language:hover,#select-language:focus{
|
#select-language:hover,#select-language:focus{
|
||||||
|
@ -262,7 +259,7 @@ button.no-text.with-icon:before{margin-right:0px}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.message{padding: 3px 10px; border-radius:3px;display:inline}
|
.message{padding: 3px 10px; border-radius:3px;display:inline-block;vertical-align:middle}
|
||||||
.message.error{background-color:#de4205; color:white}
|
.message.error{background-color:#de4205; color:white}
|
||||||
.message.warning{background-color:#ffec68; color:black}
|
.message.warning{background-color:#ffec68; color:black}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue