mirror of
https://github.com/marcrobledo/RomPatcher.js.git
synced 2025-06-27 16:25:54 +00:00
GUI redesign among other fixes
This commit is contained in:
parent
eb40a592b5
commit
a56fa9d4e8
13 changed files with 251 additions and 314 deletions
|
@ -1,26 +0,0 @@
|
||||||
/* ByteFlipper.js v20170717 - Marc Robledo 2013-2017 - http://www.marcrobledo.com/license */
|
|
||||||
function flipFile(){
|
|
||||||
var type=el('radio8').checked?8:4;
|
|
||||||
if(tempFile.fileSize>MAX_ROM_SIZE){
|
|
||||||
MarcDialogs.alert('Too big file');
|
|
||||||
return false;
|
|
||||||
}else if(tempFile.fileSize%type!==0){
|
|
||||||
MarcDialogs.alert('File is not divisible by '+type);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var tempFile2=new MarcBinFile(tempFile.fileSize);
|
|
||||||
var offset=0;
|
|
||||||
for(var i=0; i<tempFile.fileSize; i+=type){
|
|
||||||
tempFile2.writeBytes(offset, tempFile.readBytes(offset, type).reverse());
|
|
||||||
offset+=type;
|
|
||||||
}
|
|
||||||
tempFile2.fileName=tempFile.fileName.replace(/\.(.*?)$/, ' (byteflipped).$1');
|
|
||||||
tempFile2.save();
|
|
||||||
}
|
|
||||||
function flipBytesInFile(){
|
|
||||||
if(el('input-file-flip').files.length)
|
|
||||||
tempFile=new MarcBinFile(el('input-file-flip'), flipFile);
|
|
||||||
else
|
|
||||||
MarcDialogs.alert('No file selected');
|
|
||||||
}
|
|
|
@ -1,4 +1,4 @@
|
||||||
# RomPatcher.js
|
# Rom Patcher JS
|
||||||
A ROM patcher made in HTML5.
|
A ROM patcher made in HTML5.
|
||||||
|
|
||||||
**Features:**
|
**Features:**
|
||||||
|
@ -11,3 +11,4 @@ A ROM patcher made in HTML5.
|
||||||
* shows ROM CRC32, MD5 and SHA-1 before patching
|
* shows ROM CRC32, MD5 and SHA-1 before patching
|
||||||
* can remove SNES headers before patching
|
* can remove SNES headers before patching
|
||||||
* made in Vanilla JS
|
* made in Vanilla JS
|
||||||
|
* can be run in any modern web browser, including mobile
|
||||||
|
|
319
RomPatcher.css
319
RomPatcher.css
|
@ -1,19 +1,41 @@
|
||||||
/* WebApps CSS template by Marc Robledo v20170722 */
|
/* WebApps CSS template by Marc Robledo v20180428 */
|
||||||
/* minify at https://cssminifier.com/ + https://www.base64-image.de/ */
|
/* minify at https://cssminifier.com/ + https://www.base64-image.de/ */
|
||||||
|
|
||||||
/* @FONT-FACES */
|
/* @FONT-FACES */
|
||||||
@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,400i,700,800');
|
@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,700');
|
||||||
|
@import url(https://fonts.googleapis.com/css?family=Roboto+Mono:300);
|
||||||
|
|
||||||
body{
|
body{
|
||||||
margin:0;
|
margin:0;
|
||||||
font:14px 'Open Sans',sans-serif;
|
font:15px 'Open Sans',sans-serif;
|
||||||
cursor:default;
|
cursor:default;
|
||||||
margin:0px 0 40px;
|
line-height:1.8;
|
||||||
background-color:#f1f2f3;
|
background-color:#31343a;
|
||||||
color:#3c3c3c
|
color:#3c3c3c;
|
||||||
|
-moz-user-select:none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-ms-user-select:none;
|
||||||
|
-o-user-select:none;
|
||||||
|
user-select:none
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* flex main column */
|
||||||
|
html, body{height:100%}
|
||||||
|
#column{
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
height: 100%;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
header{padding: 5% 0 8%}
|
||||||
|
header h1{display:none}
|
||||||
|
footer{padding: 50px 0 20px}
|
||||||
|
#wrapper{flex-basis:100%}
|
||||||
|
|
||||||
|
|
||||||
|
.clickable{cursor:pointer}
|
||||||
|
|
||||||
|
|
||||||
/* flex box */
|
/* flex box */
|
||||||
.row{
|
.row{
|
||||||
display:flex;
|
display:flex;
|
||||||
|
@ -21,81 +43,36 @@ body{
|
||||||
align-items:center; /* vertical align */
|
align-items:center; /* vertical align */
|
||||||
justify-content:space-between
|
justify-content:space-between
|
||||||
}
|
}
|
||||||
.columns.c1,.columns.one{width:7.33333%}
|
.leftcol{width:35%;text-align:right}
|
||||||
.columns.c2,.columns.two{width:15.66667%}
|
.rightcol{width:63%}
|
||||||
.columns.c3,.columns.three{width:24%}
|
.leftcol,.rightcol{margin-bottom:8px}
|
||||||
.columns.c4,.columns.four{width:32.33333%}
|
|
||||||
.columns.c5,.columns.five{width:40.66667%}
|
|
||||||
.columns.c6,.columns.six{width:49%}
|
|
||||||
.columns.c7,.columns.seven{width:57.33333%}
|
|
||||||
.columns.c8,.columns.eight{width:65.66667%}
|
|
||||||
.columns.c9,.columns.nine{width:74%}
|
|
||||||
.columns.c10,.columns.ten{width:82.33333%}
|
|
||||||
.columns.c11,.columns.eleven{width:90.66667%}
|
|
||||||
.columns.c12,.columns.twelve{width:99%}
|
|
||||||
#the-app .columns{margin-bottom:3px}
|
|
||||||
|
|
||||||
|
|
||||||
.container{background-color:#e4e7ea;padding:15px;border-radius:5px;}
|
|
||||||
.container-description{text-align:center;margin-bottom:10px;color:#888d92;font-size:95%;}
|
|
||||||
|
|
||||||
/* useful classes */
|
|
||||||
.help:hover{cursor:help}
|
|
||||||
.hidden{display:none}
|
|
||||||
.mono{font-family:monospace;color:#888}
|
|
||||||
.clickable{cursor:pointer} /* also Safari iOS fix for clickable elements */
|
|
||||||
.text-ellipsis{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
||||||
.text-left{text-align:left}
|
|
||||||
.text-right{text-align:right}
|
|
||||||
.text-center{text-align:center}
|
|
||||||
.text-justify{text-align:justify}
|
|
||||||
.round{border-radius:3px}
|
|
||||||
/* colors */
|
|
||||||
.bg-light-gray{background-color:rgba(216,216,216,.99)}
|
|
||||||
.bg-mid-gray{background-color:rgba(144,144,144,.99);color:white}
|
|
||||||
.bg-dark-gray{background-color:rgba(72,72,72,.99);color:white}
|
|
||||||
.bg-red{background-color:#e74c3c}
|
|
||||||
.bg-orange{background-color:#f39c12}
|
|
||||||
.bg-blue{background-color:#3498db}
|
|
||||||
.bg-green{background-color:#25ba84}
|
|
||||||
.fnt-white{color:white}
|
|
||||||
.fnt-light-gray{color:#d8d8d8}
|
|
||||||
.fnt-mid-gray{color:#909090}
|
|
||||||
.fnt-dark-gray{color:#48484}
|
|
||||||
.fnt-red{color:#e74c3c}
|
|
||||||
/*.fnt-red{color:#fe5d05}*/
|
|
||||||
.fnt-orange{color:#f39c12}
|
|
||||||
/*.fnt-orange{color:#feb806}*/
|
|
||||||
.fnt-blue{color:#3498db}
|
|
||||||
.fnt-green{color:#25ba84}
|
|
||||||
/*.fnt-green{color:#9ac430}*/
|
|
||||||
.border-white{border-color:white}
|
|
||||||
.border-light-gray{border-color:#d8d8d8}
|
|
||||||
.border-mid-gray{border-color:#909090}
|
|
||||||
.border-dark-gray{border-color:#48484}
|
|
||||||
|
|
||||||
/* Icons */
|
|
||||||
i.icon{
|
/* icons */
|
||||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALAAAAAkCAYAAAApQLALAAAFm0lEQVR42u2cf2hWVRjHX+d0ldbyj4JSKwOzFKeMHGQhFBREU8KgENLWD6KCoh+QxRAjo/qjKCL7SVk6SoVgJNjW0n4IlUGtsloZlNF01rJXKzZfy92+D3suPHu4977n3t079r73OfDB+Z5z7r3vPZ+de85zzl3B87yCYVQq/g9ewn+rmbfAf+C3GHUmgpWgExT5Ph0GXeAGUGvSZSNwFshUKTfkWlAPJoPv+NqP82eTWM6akLpzQLcXnb4G83Iu3WrwOTgtZr3zwc9gVVQPHEfO8Spw1Dmj8h7gPLpJB9X1/wX28M+vBUhM8vZ7bulQjiVeK+5Dd8y6G7gePRWvr+YeOOy8UddzCvjTUcAS9wZy2KB73i9BM5gFloAOlf8N9+jjXbg02+8RdQ/WONY7B7wNZoDtXPeXau6Bg87tci1rVbkfwEbwmfr8WVVvpco/AE4Fi8EmcBXL+q0qd2OFyOvShtPBCSF5E8AT6lgPOl7DuWCfGH6RxG1gYRY9cJyURX2X44WVbVCitnHP6ue3irwfwQUir1OdYys3Wg//fzeXe1WV60p4H8aiB41z7kt5wkrf5ySVR0OtF0T9IXCX4zWcB35V5+8sF4UYTQ883gSO8xTQ6cyA6EJ/yPGK6vN/ubfwOO9iMC2gMYopCZRGDzqaX6Be9Ut5ouh5X1Ty3uF4DTSn2K/O26eGbtYDh5Qd4iiELrM35Fhh6Sho5Nn2Fwm+R5ryZjmUa+SJqZ/e4znFK+Izmnjd4ni82QHy/g7musSB8zoGforjvX66LmCIcVzk74zogf20nfN3hOQXMxoCjPaXP0n9RjUJPqqeSCtiyKufVH+ABXmKAyeJQhR4YuGnv8E9oInjjr1qklYn6nWFNDTNlO/m3ico7aigCZxLOy7iRRuZjoFrYox5ewPkXRhnJS7PceAtjsOXIofH/HqrQsp9yuPfn0Lyb6qiKIRPk+iJKdx4dYxFiqBhQ4OtxLlBYa5djgIPqUdirZi0eWqYMVtEI2TqCRlnV0McuJGfPs0x6uiFI5owz7e9EPGYysOB1dyryjFxOzfIV+D2gLpz1USmXA/eUIX3L63Orj9qzDuWPXCls1nc1PkinBZWfh6vsEWlHpM3UuCyY14TOPuhSAv35HI3Gk3Ybq6QYUPF70ajMcxzvBtrgPmeg9JNGVzE/WCQG7uF9xG4JloVWy4mDa3WqPkVeAovdw6VmcC0caA6rYsYFMcngZ8B2xx5SQjsxx+tYXMoMMn7SYyej/Zz1vsH6Wu+hFgAOsAAOAI2g7PBDNAGDoNB0AUupDoBA/iWBF9ieYVFPIwMBH5DiEmB53c5DreboTDH+97whu+PxczcF5iE/Ad4iv2gN+BzEvkiE9hIQ+AlahdWuUovi/KXs8AfBEhajo9MYCMNgTeJxn/aodKjovybLHApgcDHTGAjDYH3iQna6Q6V6nmDhr/eTwL3JRD4oAlspCGwv3NoIEbFQ3LWDxkfTiDwYyawkYbAchvcGQ6VpomthUUWeBJojyHvO6AuQOBbE3yJFSZwvgX+UDT+OodKctvhLhFGI4m3OshLoteFhNG6wVne8KsoLkwXURETOKcC38kNv4f3bz7OEunCM1lwub/1PiEwUQtej5B3C4teCBE4jWQNmzOBp/BEjgReIwS90hv54p5OB/wVOSEwUQOeD5B3A5goy5rARloLGYt5SZfeIF0G7vVG/hmkOiVJiaUuBAhMTABPCnnXs9gFE9jIai/EFTwp28vjyqkib7IQ5AhYKg8SILDPOoo2hOWXEZj2hd7GkYkoOkxgE9iHohDrWZ6T1TbBft48MzPjV1c8vVQtuMwbfsPXp8bCaCbweH2BsN0h5msCm8AmsGECm8BGbgUupShwyRrVBB5rWr2Rf8klSmBaxl4kKKhXih6yRs0X/wMhEBsJUtVSfgAAAABJRU5ErkJggg==');
|
button.with-dot:before{
|
||||||
|
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAQAAABKmM6bAAAAWElEQVQI12P4zwCGIv/V/stC2CCC63/J/5f/f////n/nf3OIUMn/v/9h4M5/NZCWR/8R4N//FgagCd/+I4PVIFVPUFR1oZt1778Bso3fEDZC3CULxFwgNgDirn13m99yDAAAAABJRU5ErkJggg==');
|
||||||
|
background-size:100% 100%;
|
||||||
|
display:inline-block;
|
||||||
|
vertical-align:middle;
|
||||||
|
width:4px;height:4px;
|
||||||
|
content:"";
|
||||||
|
margin-right:10px;
|
||||||
|
}
|
||||||
|
footer .icon, #crc32.valid:after{
|
||||||
|
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAQCAYAAABQrvyxAAACUElEQVRIx9XWzUtUURzG8atp04svtCiI3v6EQFIoInBREFgEQtC+VVCLWoQLMTKqRUEbU4uKaOht5a7IoDcoWkiLIKKVgqUUvkGMM2revid+V55u5+qdS5ANfEDvPXN4npl7zpkgDMMgpgFX8QEF8xG9aPKM/6f0n7W4ifkw+eXu5VG33Aq48G/C9K8B1EeTjLTsdrbjMQqYwn1sw2bkMYlp9GOHe89CiDNBuU5jAOujSe5KsFY8wVe8NaN4hsN4bWP7pIAL9B1hzGcMe667IjszFuhAaN65CfbIJ5tP8bVdl/F7rcBzT8ilvMxQ4JyEd9rdBHck0JUUBc7L+HtWoJShwEyswCasSghegUux8G2/7jHBoCzQDSkKuGd/1t4zZAVGMhQYlQLNmEA/1sTCV6JHgs/jxMJ9JihamEIZq3/M3lO0AmczFLggBYYloCuxWj753lj4Y78VZIJxeSQ2pgi/Dj9s/IQVqEZfGeEfIScFGjAmQZ+iDjfk2hyO/vF4McELKdCZokCbjH8l26gr8TBFeFc059lGXYlxCVyUv2dxxLs+mOC4hXkPt7AuYqsn+BYrOCcFTkkBpwq3Fwn/wIoGCedAIyZji3UGrYk7kx1ig1agXQLul/DNnsPsS3QiSwGnEt2e8LewQscmbKNN8k2UcGjRrdUm2YVp9OAgTqJKCuRi4UtWKvAUcCpwWcJ3WbEgRYHocRpCy5Jng4TcZ4vyk522NXJvpYSfwgF9vDwFIp1ut0m6/7d/zAW2C3XhG2rlerVdu2ZrYVn+Gv0v/QQllGUdmIg+uwAAAABJRU5ErkJggg==');
|
||||||
|
}
|
||||||
|
footer .icon{
|
||||||
background-position:0px 0px;
|
background-position:0px 0px;
|
||||||
display:inline-block;
|
display:inline-block;
|
||||||
vertical-align:middle;
|
vertical-align:middle;
|
||||||
width:16px;height:16px
|
width:16px;height:16px
|
||||||
}
|
}
|
||||||
i.icon.reset,i.icon.blank{background-position:-0px 0px}
|
footer .icon.github{background-position:0px 0px}
|
||||||
i.icon.add,i.icon.plus{background-position:-16px 0px}
|
footer .icon.heart{background-position:-16px 0px}
|
||||||
i.icon.remove,i.icon.minus{background-position:-32px 0px}
|
footer .icon.check{background-position:-32px 0px}
|
||||||
i.icon.close{background-position:-48px 0px}
|
|
||||||
i.icon.config,i.icon.settings{background-position:-64px 0px}
|
|
||||||
i.icon.help{background-position:-80px 0px}
|
|
||||||
i.icon.down{background-position:-96px 0px}
|
|
||||||
i.icon.up{background-position:-112px 0px}
|
|
||||||
i.icon.sort{background-position:-128px 0px}
|
|
||||||
i.icon.check,i.icon.accept,i.icon.save{background-position:-144px 0px}
|
|
||||||
i.icon.pencil,i.icon.edit{background-position:-160px 0px}
|
|
||||||
i.icon.github{background-position:0px -16px}
|
|
||||||
i.icon.heart{background-position:-16px -16px}
|
|
||||||
i.icon.disk{background-position:-32px -16px;width:20px;height:20px}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -104,116 +81,82 @@ i.icon.disk{background-position:-32px -16px;width:20px;height:20px}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* header+footer */
|
||||||
|
header{text-align:center}
|
||||||
|
header h1{margin:0}
|
||||||
|
header img{max-width:90%}
|
||||||
|
|
||||||
/* header+toolbar+footer */
|
footer{
|
||||||
#header{
|
text-align:center;
|
||||||
color:white;
|
color:#767b86;
|
||||||
/*position:fixed;*/
|
font-size:85%;
|
||||||
top:0;left:0;
|
|
||||||
width:100%;
|
|
||||||
z-index:100;
|
|
||||||
}
|
}
|
||||||
#header-top{
|
footer a{
|
||||||
background-color:#43454a;
|
color:#969ba6;
|
||||||
padding:16px 0
|
|
||||||
}
|
|
||||||
#header h1 img{height:24px; vertical-align:middle}
|
|
||||||
#header h1{font-size:140%;margin:0;display:inline-block}
|
|
||||||
#header h1 small{color:#717377;font-size:60%}
|
|
||||||
#toolbar{margin-top:10px}
|
|
||||||
|
|
||||||
|
|
||||||
.header-buttons{
|
|
||||||
font-size:85%
|
|
||||||
}
|
|
||||||
.header-buttons a{
|
|
||||||
color:white;
|
|
||||||
text-decoration:none;
|
text-decoration:none;
|
||||||
border-bottom:1px solid #5d5f63;
|
border-bottom:1px solid #464b56;
|
||||||
margin-right:10px
|
}
|
||||||
|
footer a:hover{
|
||||||
|
color:white;
|
||||||
|
border-color:#41d5ff;
|
||||||
}
|
}
|
||||||
.header-buttons a:hover{border-color:#41d5ff}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
hr{border:none;border-top:1px dotted #bbb;margin:15px 0}
|
hr{border:none;border-top:1px dotted #bbb;margin:15px 0}
|
||||||
h3{
|
|
||||||
/*border-bottom:2px solid #888;*/
|
/* tabs */
|
||||||
font-size:13px;
|
#tabs div{
|
||||||
padding:10px 0;
|
width:50%;
|
||||||
font-weight:normal;
|
display:inline-block;
|
||||||
text-align:center;
|
text-align:center;
|
||||||
margin: 20px 0 0;
|
box-sizing:border-box;
|
||||||
|
padding: 10px;
|
||||||
|
color:#646871;
|
||||||
|
border-radius: 2px 2px 0 0;
|
||||||
|
transition: .15s all;
|
||||||
|
border-top: 3px solid transparent;
|
||||||
|
}
|
||||||
|
#tabs div:hover{color:white;background-color:#2e3137}
|
||||||
|
#tabs div.selected{
|
||||||
|
background-color:#f9fafa;
|
||||||
color:black;
|
color:black;
|
||||||
}
|
}
|
||||||
h3:before,h3:after{
|
.tab{background-color:#f9fafa;padding:30px 15px}
|
||||||
content:"";
|
#tab0{border-radius: 0px 2px 2px 2px}
|
||||||
display:inline-block;
|
#tab1{border-radius: 2px 0px 2px 2px;display:none}
|
||||||
width:130px;
|
#tabs div:first-child.selected{border-color: #e74c3c;}
|
||||||
height:1px;
|
#tabs div:last-child.selected{border-color: #25ba84;/*border-color: #3498db;*/}
|
||||||
background-color:red;
|
|
||||||
vertical-align:middle;
|
|
||||||
}
|
|
||||||
h3:before{
|
|
||||||
margin-right:5px;
|
|
||||||
background:linear-gradient(to right, transparent 0%,#818181 100%);
|
|
||||||
}
|
|
||||||
h3:after{
|
|
||||||
margin-left:5px;
|
|
||||||
background:linear-gradient(to left, transparent 0%,#818181 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
h3.red:before{background:linear-gradient(to right, transparent 0%,#e74c3c 100%)}
|
|
||||||
h3.red:after{background:linear-gradient(to left, transparent 0%,#e74c3c 100%)}
|
|
||||||
h3.orange:before{background:linear-gradient(to right, transparent 0%,#f39c12 100%)}
|
|
||||||
h3.orange:after{background:linear-gradient(to left, transparent 0%,#f39c12 100%)}
|
|
||||||
h3.blue:before{background:linear-gradient(to right, transparent 0%,#3498db 100%)}
|
|
||||||
h3.blue:after{background:linear-gradient(to left, transparent 0%,#3498db 100%)}
|
|
||||||
h3.green:before{background:linear-gradient(to right, transparent 0%,#25ba84 100%)}
|
|
||||||
h3.green:after{background:linear-gradient(to left, transparent 0%,#25ba84 100%)}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
table{width:100%}
|
|
||||||
tbody tr:nth-child(even){background-color:#f2f2f2}
|
|
||||||
th{background-color:#d4d4d4}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* forms */
|
/* forms */
|
||||||
textarea, input[type=file]{
|
input[type=file],select{
|
||||||
box-sizing:border-box;
|
box-sizing:border-box;
|
||||||
max-width:100%;
|
max-width:100%;
|
||||||
}
|
font-family:inherit;
|
||||||
input[type=text],input[type=number],select{
|
font-size:100%;
|
||||||
padding:6px 10px;
|
|
||||||
outline:0;
|
outline:0;
|
||||||
width:250px;
|
border:none;
|
||||||
max-width:90%;
|
border-radius:3px;
|
||||||
font:14px 'Open Sans', sans-serif;
|
background-color:#edefef;
|
||||||
border:1px solid #191919;
|
|
||||||
border-radius:4px;
|
|
||||||
box-sizing:border-box;
|
|
||||||
background-color:#191919;
|
|
||||||
color:#f2f2f2;
|
|
||||||
letter-spacing:.02em;
|
|
||||||
}
|
}
|
||||||
input[type=text]:hover,input[type=number]:hover,select:hover{
|
input[type=file]{padding:6px 10px}
|
||||||
background-color:#222;
|
select{
|
||||||
|
padding:6px 18px 6px 10px;
|
||||||
|
-webkit-appearance:none;
|
||||||
|
-moz-appearance:none;
|
||||||
|
text-overflow:'';
|
||||||
|
|
||||||
|
background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgeD0iMTJweCIgeT0iMHB4IiB3aWR0aD0iMjRweCIgaGVpZ2h0PSIzcHgiIHZpZXdCb3g9IjAgMCA2IDMiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDYgMyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBvbHlnb24gcG9pbnRzPSI1Ljk5MiwwIDIuOTkyLDMgLTAuMDA4LDAgIi8+PC9zdmc+");
|
||||||
|
background-position:100% center;
|
||||||
|
background-repeat:no-repeat;
|
||||||
}
|
}
|
||||||
input[type=text]:focus,input[type=number]:focus,select:focus{
|
select::-ms-expand{display:none}
|
||||||
border-color:#41d5ff;
|
input[type=file]:hover,select:hover{background-color:#dee1e1}
|
||||||
box-shadow:#35a1c0 0 0 3px;
|
|
||||||
}
|
|
||||||
input[type=text].error,input[type=number].error,select.error{
|
|
||||||
box-shadow:#f88 0 0 3px;
|
|
||||||
border-color:red
|
|
||||||
}
|
|
||||||
input[type=text].small,input[type=number].small,select.small{width:70px}
|
|
||||||
input[type=text].medium,input[type=number].medium,select.medium{width:130px}
|
|
||||||
input[type=text].fw,input[type=number].fw,select.fw{width:100% !important;max-width:100% !important}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -234,9 +177,6 @@ button{
|
||||||
|
|
||||||
box-sizing:border-box
|
box-sizing:border-box
|
||||||
}
|
}
|
||||||
button.small{
|
|
||||||
min-width:1px
|
|
||||||
}
|
|
||||||
button:hover{
|
button:hover{
|
||||||
cursor:pointer;
|
cursor:pointer;
|
||||||
background-color:#6e7177;
|
background-color:#6e7177;
|
||||||
|
@ -245,9 +185,7 @@ button:active{
|
||||||
background-color:#47494f;
|
background-color:#47494f;
|
||||||
transform:translateY(1px)
|
transform:translateY(1px)
|
||||||
}
|
}
|
||||||
button:disabled{opacity:.35}
|
button:disabled{opacity:.35 !important;cursor:not-allowed}
|
||||||
button.colored{color:white;background-color:#40a2c9}
|
|
||||||
button.colored:hover{background-color:#63bfe3}
|
|
||||||
button.close{color:white;background-color:#}
|
button.close{color:white;background-color:#}
|
||||||
button.no-text.with-icon:before{margin-right:0px}
|
button.no-text.with-icon:before{margin-right:0px}
|
||||||
|
|
||||||
|
@ -257,14 +195,28 @@ button.no-text.with-icon:before{margin-right:0px}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#rom-info{font-family:'Roboto Mono',monospace;color:#888;font-size:12px}
|
||||||
|
#rom-info .rightcol{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||||
|
#crc32.valid{color:green}
|
||||||
|
/*#crc32.valid:after{content:" \002713"}*/
|
||||||
|
#crc32.invalid{color: red}
|
||||||
|
|
||||||
|
|
||||||
|
#crc32.valid:after{
|
||||||
|
background-position:0px 0px;
|
||||||
|
display:inline-block;
|
||||||
|
vertical-align:middle;
|
||||||
|
width:16px;height:16px;
|
||||||
|
background-position:-32px 0px;
|
||||||
|
content:"";
|
||||||
|
margin-left:4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#wrapper{
|
||||||
|
box-sizing:border-box;
|
||||||
.wrapper{
|
max-width:95%;
|
||||||
max-width:900px;
|
width:600px;
|
||||||
margin:0 auto
|
margin:0 auto
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,17 +224,10 @@ button.no-text.with-icon:before{margin-right:0px}
|
||||||
|
|
||||||
|
|
||||||
/* responsive */
|
/* responsive */
|
||||||
@media only screen and (max-width:961px){
|
@media only screen and (max-width:641px){
|
||||||
.wrapper{max-width:auto; padding-left:10px;padding-right:10px;}
|
#wrapper{font-size:14px}
|
||||||
}
|
#rom-info{font-size:11px}
|
||||||
@media only screen and (max-width:721px){
|
header img{max-height:96px}
|
||||||
#header .columns-6,#header .columns.six{width:100%;text-align:center}
|
|
||||||
h1 img{margin-bottom:15px}
|
|
||||||
#the-app{font-size:13px}
|
|
||||||
h3:before,h3:after{width:40px}
|
|
||||||
}
|
|
||||||
@media only screen and (max-width:481px){
|
|
||||||
#the-app{font-size:12px}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -308,19 +253,17 @@ button.no-text.with-icon:before{margin-right:0px}
|
||||||
transform:translateY(-10px);
|
transform:translateY(-10px);
|
||||||
transition:visibility 0s .2s, opacity .2s ease-in, transform .2s ease-in;
|
transition:visibility 0s .2s, opacity .2s ease-in, transform .2s ease-in;
|
||||||
|
|
||||||
background-color:#45484f;
|
background-color:#f9fafa;
|
||||||
padding:15px;
|
padding:15px;
|
||||||
min-width:360px;
|
min-width:360px;
|
||||||
max-width:80%;
|
max-width:80%;
|
||||||
border-radius:4px;
|
border-radius:3px;
|
||||||
box-shadow:0 5px 15px 0 rgba(0,0,0,.5);
|
box-shadow:0 5px 15px 0 rgba(0,0,0,.5);
|
||||||
line-height:1.8;
|
line-height:1.8;
|
||||||
color:#f2f2f2;
|
|
||||||
}
|
}
|
||||||
.dialog.active{transform:translateY(0px)}
|
.dialog.active{transform:translateY(0px)}
|
||||||
.dialog button{color:#f2f2f2}
|
|
||||||
.buttons{
|
.buttons{
|
||||||
margin-top:20px;
|
margin-top:20px;
|
||||||
text-align:center
|
text-align:right
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* RomPatcher.js v20180427 - Marc Robledo 2016-2018 - http://www.marcrobledo.com/license */
|
/* RomPatcher.js v20180428 - Marc Robledo 2016-2018 - http://www.marcrobledo.com/license */
|
||||||
var MAX_ROM_SIZE=33554432;
|
var MAX_ROM_SIZE=33554432;
|
||||||
var romFile, headeredRomFile, unheaderedRomFile, patch, romFile1, romFile2, tempFile;
|
var romFile, headeredRomFile, unheaderedRomFile, patch, romFile1, romFile2, tempFile;
|
||||||
/* Shortcuts */
|
/* Shortcuts */
|
||||||
|
@ -18,7 +18,6 @@ addEvent(window,'load',function(){
|
||||||
el('input-file-patch').value='';
|
el('input-file-patch').value='';
|
||||||
el('input-file-rom1').value='';
|
el('input-file-rom1').value='';
|
||||||
el('input-file-rom2').value='';
|
el('input-file-rom2').value='';
|
||||||
el('input-file-flip').value='';
|
|
||||||
|
|
||||||
addEvent(el('input-file-rom'), 'change', function(){
|
addEvent(el('input-file-rom'), 'change', function(){
|
||||||
romFile=new MarcBinFile(this, function(){
|
romFile=new MarcBinFile(this, function(){
|
||||||
|
@ -40,6 +39,7 @@ addEvent(window,'load',function(){
|
||||||
}
|
}
|
||||||
|
|
||||||
updateChecksums(romFile);
|
updateChecksums(romFile);
|
||||||
|
validateSource();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
addEvent(el('input-file-patch'), 'change', function(){
|
addEvent(el('input-file-patch'), 'change', function(){
|
||||||
|
@ -67,6 +67,7 @@ addEvent(window,'load',function(){
|
||||||
|
|
||||||
|
|
||||||
updateChecksums(romFile);
|
updateChecksums(romFile);
|
||||||
|
validateSource();
|
||||||
});
|
});
|
||||||
|
|
||||||
addEvent(el('checkbox-addheader'), 'change', function(){
|
addEvent(el('checkbox-addheader'), 'change', function(){
|
||||||
|
@ -82,7 +83,10 @@ addEvent(window,'load',function(){
|
||||||
else
|
else
|
||||||
romFile=unheaderedRomFile;
|
romFile=unheaderedRomFile;
|
||||||
|
|
||||||
|
validateSource();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setTab(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
function isSnesRom(fileName){return /\.(smc|sfc|fig|swc)$/.test(fileName)}
|
function isSnesRom(fileName){return /\.(smc|sfc|fig|swc)$/.test(fileName)}
|
||||||
|
@ -91,7 +95,7 @@ function isHeadered(fileSize,headerSize){return isPowerOfTwo(fileSize-headerSize
|
||||||
|
|
||||||
|
|
||||||
function updateChecksums(file){
|
function updateChecksums(file){
|
||||||
el('rom-info').style.display='block';
|
el('rom-info').style.display='flex';
|
||||||
sha1(file);
|
sha1(file);
|
||||||
|
|
||||||
var crc32str=crc32(file).toString(16);
|
var crc32str=crc32(file).toString(16);
|
||||||
|
@ -101,6 +105,13 @@ function updateChecksums(file){
|
||||||
el('md5').innerHTML=md5(file);
|
el('md5').innerHTML=md5(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function validateSource(){
|
||||||
|
if(patch && romFile && typeof patch.validateSource !== 'undefined'){
|
||||||
|
el('crc32').className=patch.validateSource(romFile)?'valid':'invalid';
|
||||||
|
}else{
|
||||||
|
el('crc32').className='';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function _readPatchFile(){
|
function _readPatchFile(){
|
||||||
|
@ -119,6 +130,7 @@ function _readPatchFile(){
|
||||||
}*/else {
|
}*/else {
|
||||||
MarcDialogs.alert('Invalid IPS/UPS/APS/BPS file');
|
MarcDialogs.alert('Invalid IPS/UPS/APS/BPS file');
|
||||||
}
|
}
|
||||||
|
validateSource();
|
||||||
}
|
}
|
||||||
function openPatchFile(f){tempFile=new MarcBinFile(f, _readPatchFile)}
|
function openPatchFile(f){tempFile=new MarcBinFile(f, _readPatchFile)}
|
||||||
function applyPatchFile(p,r){
|
function applyPatchFile(p,r){
|
||||||
|
@ -141,36 +153,51 @@ function applyPatchFile(p,r){
|
||||||
|
|
||||||
|
|
||||||
function createPatchFile(){
|
function createPatchFile(){
|
||||||
|
var mode=el('patch-type').value;
|
||||||
if(!romFile1 || !romFile2){
|
if(!romFile1 || !romFile2){
|
||||||
MarcDialogs.alert('No original/modified ROM file specified');
|
MarcDialogs.alert('No original/modified ROM file specified');
|
||||||
return false;
|
return false;
|
||||||
}else if(el('radio-ips').checked && (romFile1.fileSize>MAX_IPS_SIZE || romFile2.fileSize>MAX_IPS_SIZE)){
|
}else if(mode==='ips' && (romFile1.fileSize>MAX_IPS_SIZE || romFile2.fileSize>MAX_IPS_SIZE)){
|
||||||
MarcDialogs.alert('Files are too big for IPS format');
|
MarcDialogs.alert('Files are too big for IPS format');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var newPatch;
|
var newPatch;
|
||||||
if(el('radio-ips').checked){
|
if(mode==='ips'){
|
||||||
newPatch=createIPSFromFiles(romFile1, romFile2);
|
newPatch=createIPSFromFiles(romFile1, romFile2);
|
||||||
}else if(el('radio-ups').checked){
|
}else if(mode==='ups'){
|
||||||
newPatch=createUPSFromFiles(romFile1, romFile2);
|
newPatch=createUPSFromFiles(romFile1, romFile2);
|
||||||
}else if(el('radio-aps').checked){
|
}else if(mode==='aps'){
|
||||||
newPatch=createAPSFromFiles(romFile1, romFile2, false);
|
newPatch=createAPSFromFiles(romFile1, romFile2, false);
|
||||||
}else if(el('radio-apsn64').checked){
|
}else if(mode==='apsn64'){
|
||||||
newPatch=createAPSFromFiles(romFile1, romFile2, true);
|
newPatch=createAPSFromFiles(romFile1, romFile2, true);
|
||||||
}/*else if(el('radio-apsgba').checked){
|
}/*else if(el('radio-apsgba').checked){
|
||||||
newPatch=createAPSGBAFromFiles(romFile1, romFile2);
|
newPatch=createAPSGBAFromFiles(romFile1, romFile2);
|
||||||
}else if(el('radio-bps').checked){
|
}else if(el('radio-bps').checked){
|
||||||
newPatch=createBPSFromFiles(romFile1, romFile2);
|
newPatch=createBPSFromFiles(romFile1, romFile2);
|
||||||
}*/
|
}*/
|
||||||
newPatch.export().save();
|
newPatch.export(romFile2.fileName.replace(/\.[^\.]+$/,'')).save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function setTab(tab){
|
||||||
|
for(var i=0; i<2; i++){
|
||||||
|
if(i===tab){
|
||||||
|
el('tab'+i).style.display='block';
|
||||||
|
el('tabs').children[i].className='selected';
|
||||||
|
}else{
|
||||||
|
el('tab'+i).style.display=i===tab?'block':'none';
|
||||||
|
el('tabs').children[i].className='clickable'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* CRC32/MD5/SHA-1 calculators */
|
/* CRC32/MD5/SHA-1 calculators */
|
||||||
var HEX_CHR='0123456789abcdef'.split('');
|
var HEX_CHR='0123456789abcdef'.split('');
|
||||||
|
|
|
@ -12,7 +12,7 @@ limitations under the License.
|
||||||
mod by marcrobledo, original from: https://github.com/GoogleChrome/samples/blob/gh-pages/service-worker/basic/service-worker.js
|
mod by marcrobledo, original from: https://github.com/GoogleChrome/samples/blob/gh-pages/service-worker/basic/service-worker.js
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const PRECACHE_ID='v20180427b';
|
const PRECACHE_ID='v20180428';
|
||||||
const PRECACHE_FILES=[
|
const PRECACHE_FILES=[
|
||||||
'index.html','./',
|
'index.html','./',
|
||||||
'RomPatcher.css',
|
'RomPatcher.css',
|
||||||
|
@ -22,8 +22,7 @@ const PRECACHE_FILES=[
|
||||||
'ips.js',
|
'ips.js',
|
||||||
'ups.js',
|
'ups.js',
|
||||||
'aps.js',
|
'aps.js',
|
||||||
'bps.js',
|
'bps.js'
|
||||||
'ByteFlipper.js'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
6
aps.js
6
aps.js
|
@ -1,4 +1,4 @@
|
||||||
/* APS (N64) module for RomPatcher.js v20180427 - Marc Robledo 2017-2018 - http://www.marcrobledo.com/license */
|
/* APS (N64) module for RomPatcher.js v20180428 - Marc Robledo 2017-2018 - http://www.marcrobledo.com/license */
|
||||||
/* File format specification: https://github.com/btimofeev/UniPatcher/wiki/APS-(N64) */
|
/* File format specification: https://github.com/btimofeev/UniPatcher/wiki/APS-(N64) */
|
||||||
|
|
||||||
var RECORD_RLE=0x0000;
|
var RECORD_RLE=0x0000;
|
||||||
|
@ -38,7 +38,7 @@ APS.prototype.toString=function(){
|
||||||
s+='\nHeader: '+JSON.stringify(this.header);
|
s+='\nHeader: '+JSON.stringify(this.header);
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
APS.prototype.export=function(){
|
APS.prototype.export=function(fileName){
|
||||||
var patchFileSize=(this.headerType===1)?78:61;
|
var patchFileSize=(this.headerType===1)?78:61;
|
||||||
|
|
||||||
for(var i=0; i<this.records.length; i++){
|
for(var i=0; i<this.records.length; i++){
|
||||||
|
@ -50,7 +50,7 @@ APS.prototype.export=function(){
|
||||||
|
|
||||||
tempFile=new MarcBinFile(patchFileSize);
|
tempFile=new MarcBinFile(patchFileSize);
|
||||||
tempFile.littleEndian=true;
|
tempFile.littleEndian=true;
|
||||||
tempFile.fileName='patch.aps';
|
tempFile.fileName=fileName+'.aps';
|
||||||
tempFile.writeString(0, APS_MAGIC, APS_MAGIC.length);
|
tempFile.writeString(0, APS_MAGIC, APS_MAGIC.length);
|
||||||
tempFile.writeByte(5, this.headerType);
|
tempFile.writeByte(5, this.headerType);
|
||||||
tempFile.writeByte(6, this.encodingMethod);
|
tempFile.writeByte(6, this.encodingMethod);
|
||||||
|
|
5
bps.js
5
bps.js
|
@ -1,4 +1,4 @@
|
||||||
/* BPS module for RomPatcher.js v20171112 - Marc Robledo 2016-2017 - http://www.marcrobledo.com/license */
|
/* BPS module for RomPatcher.js v20180428 - Marc Robledo 2016-2018 - http://www.marcrobledo.com/license */
|
||||||
/* File format specification: https://www.romhacking.net/documents/746/ */
|
/* File format specification: https://www.romhacking.net/documents/746/ */
|
||||||
|
|
||||||
var BPS_MAGIC='BPS1';
|
var BPS_MAGIC='BPS1';
|
||||||
|
@ -28,8 +28,9 @@ BPS.prototype.toString=function(){
|
||||||
/*BPS.prototype.export=function(){
|
/*BPS.prototype.export=function(){
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
BPS.prototype.validateSource=function(romFile){return this.sourceChecksum===crc32(romFile,false)}
|
||||||
BPS.prototype.apply=function(romFile){
|
BPS.prototype.apply=function(romFile){
|
||||||
if(this.sourceChecksum!==crc32(romFile,false)){
|
if(!this.validateSource(romFile)){
|
||||||
MarcDialogs.alert('Error: invalid source ROM checksum');
|
MarcDialogs.alert('Error: invalid source ROM checksum');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
123
index.html
123
index.html
|
@ -1,137 +1,110 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>RomPatcher.js</title>
|
<title>Rom Patcher JS</title>
|
||||||
<meta http-equiv="content-Type" content="text/html; charset=UTF-8"/>
|
<meta http-equiv="content-Type" content="text/html; charset=UTF-8"/>
|
||||||
<meta name="description" content="A web-based IPS/UPS/APS/BPS ROM patcher."/>
|
<meta name="description" content="A web-based IPS/UPS/APS/BPS ROM patcher."/>
|
||||||
<meta name="keywords" content="ips,ups,aps,bps,patcher,online,html5,rom,patch,hack,translation"/>
|
<meta name="keywords" content="ips,ups,aps,bps,patcher,online,html5,web,online,rom,patch,hack,translation"/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
|
||||||
|
<link rel="manifest" href="./manifest.json"/>
|
||||||
<link rel="shortcut icon" href="./favicon.png"/>
|
<link rel="shortcut icon" href="./favicon.png"/>
|
||||||
<link type="text/css" rel="stylesheet" href="./RomPatcher.css" media="all"/>
|
<link type="text/css" rel="stylesheet" href="./RomPatcher.css" media="all"/>
|
||||||
<script type="text/javascript" src="./RomPatcher.js"></script>
|
<script type="text/javascript" src="./RomPatcher.js"></script>
|
||||||
<script type="text/javascript" src="./ips.js"></script>
|
<script type="text/javascript" src="./ips.js"></script>
|
||||||
<script type="text/javascript" src="./ups.js"></script>
|
<script type="text/javascript" src="./ups.js"></script>
|
||||||
<script type="text/javascript" src="./aps.js"></script>
|
<script type="text/javascript" src="./aps.js"></script>
|
||||||
<!-- <script type="text/javascript" src="./apsgba.js"></script> -->
|
|
||||||
<script type="text/javascript" src="./bps.js"></script>
|
<script type="text/javascript" src="./bps.js"></script>
|
||||||
<script type="text/javascript" src="./ByteFlipper.js"></script>
|
|
||||||
|
<!-- <script type="text/javascript" src="./apsgba.js"></script> -->
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body unselectable="on" onselectstart="return false"><div id="column">
|
||||||
|
|
||||||
|
|
||||||
<!-- HEADER -->
|
<!-- HEADER -->
|
||||||
<div id="header">
|
<header><img src="logo.png" /><h1>RomPatcher.js</h1></header>
|
||||||
<div id="header-top">
|
|
||||||
<div class="row wrapper">
|
|
||||||
<h1 class="six columns text-left"><img src="logo.png" /><span class="hidden">RomPatcher.js</span></h1>
|
|
||||||
<div class="six columns header-buttons text-right">
|
|
||||||
by <a href="/">Marc Robledo</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>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- APP -->
|
<!-- APP -->
|
||||||
<div class="wrapper" id="the-app">
|
<div id="wrapper">
|
||||||
<h3 class="red">Apply patch</h3>
|
<div id="tabs"><div class="selected clickable" onclick="setTab(0)">Apply patch</div><div class="clickable" onclick="setTab(1)">Create patch</div></div>
|
||||||
<div class="container-description">Apply a patch to your ROM</div>
|
|
||||||
<div class="container">
|
<div id="tab0" class="tab">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="six columns text-right"><label for="input-file-rom">ROM file:</label></div>
|
<div class="leftcol"><label for="input-file-rom">ROM file:</label></div>
|
||||||
<div class="six columns">
|
<div class="rightcol">
|
||||||
<input type="file" id="input-file-rom" />
|
<input type="file" id="input-file-rom" />
|
||||||
<div id="rom-info" class="mono" style="display:none;font-size:12px">
|
|
||||||
CRC32: <span id="crc32"></span><br/>
|
|
||||||
MD5: <span id="md5"></span><br/>
|
|
||||||
SHA-1: <span id="sha1"></span><br/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row" id="rom-info">
|
||||||
|
<div class="leftcol">CRC32:</div><div class="rightcol"><span id="crc32"></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>
|
||||||
<div class="row" id="row-removeheader" style="display:none">
|
<div class="row" id="row-removeheader" style="display:none">
|
||||||
<div class="six columns text-right"><label for="checkbox-removeheader">Remove header before patching:</label></div>
|
<div class="leftcol"><label for="checkbox-removeheader">Remove header before patching:</label></div>
|
||||||
<div class="six columns">
|
<div class="rightcol">
|
||||||
<input type="checkbox" id="checkbox-removeheader" />
|
<input type="checkbox" id="checkbox-removeheader" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row" id="row-addheader" style="display:none">
|
<div class="row" id="row-addheader" style="display:none">
|
||||||
<div class="six columns text-right"><label for="checkbox-addheader">Patch needs a headered ROM:</label></div>
|
<div class="leftcol"><label for="checkbox-addheader">Patch needs a headered ROM:</label></div>
|
||||||
<div class="six columns">
|
<div class="rightcol">
|
||||||
<input type="checkbox" id="checkbox-addheader" />
|
<input type="checkbox" id="checkbox-addheader" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row" title="Compatible formats: IPS, UPS, APS and BPS">
|
||||||
<div class="six columns text-right"><label for="input-file-patch">Patch file <small>(IPS/UPS/APS/BPS)</small>:</label></div>
|
<div class="leftcol"><label for="input-file-patch">Patch file:</label></div>
|
||||||
<div class="six columns">
|
<div class="rightcol">
|
||||||
<input type="file" id="input-file-patch" />
|
<input type="file" id="input-file-patch" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<button class="with-icon icon9" onclick="applyPatchFile(patch, romFile)"><i class="icon check"></i> Apply patch</button>
|
<button class="with-dot" onclick="applyPatchFile(patch, romFile)">Apply patch</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 class="blue">Create patch</h3>
|
<div id="tab1" class="tab">
|
||||||
<div class="container-description">Create a patch from two different ROMs </div>
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="six columns text-right"><label for="input-file-rom1">Original ROM:</label></div>
|
<div class="leftcol"><label for="input-file-rom1">Original ROM:</label></div>
|
||||||
<div class="six columns end">
|
<div class="rightcol">
|
||||||
<input type="file" id="input-file-rom1" />
|
<input type="file" id="input-file-rom1" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="six columns text-right"><label for="input-file-rom2">Modified ROM:</label></div>
|
<div class="leftcol"><label for="input-file-rom2">Modified ROM:</label></div>
|
||||||
<div class="six columns end">
|
<div class="rightcol">
|
||||||
<input type="file" id="input-file-rom2" />
|
<input type="file" id="input-file-rom2" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="six columns text-right">Patch type</div>
|
<div class="leftcol">Patch type:</div>
|
||||||
<div class="six columns end">
|
<div class="rightcol">
|
||||||
<input type="radio" id="radio-ips" name="patch-type" checked /><label for="radio-ips">IPS</label>
|
<select id="patch-type">
|
||||||
<input type="radio" id="radio-ups" name="patch-type" /><label for="radio-ups">UPS</label>
|
<option value="ips">IPS</option>
|
||||||
<input type="radio" id="radio-aps" name="patch-type" /><label for="radio-aps">APS</label>
|
<option value="ups">UPS</option>
|
||||||
<input type="radio" id="radio-apsn64" name="patch-type" /><label for="radio-apsn64">APS (N64)</label>
|
<option value="aps">APS</option>
|
||||||
<!-- <input type="radio" id="radio-bps" name="patch-type" /><label for="radio-bps">BPS</label> -->
|
<option value="apsn64">APS (N64)</option>
|
||||||
|
<!-- <option value="bps">BPS</option> -->
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<button class="with-icon icon9" onclick="createPatchFile()"><i class="icon settings"></i> Create patch</button>
|
<button class="with-dot" onclick="createPatchFile()">Create patch</button>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 class="green">Byte flipper</h3>
|
|
||||||
<div class="container-description">This tool flips bytes in a file in order to change its endianness</div>
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
<div class="six columns text-right"><label for="input-file-flip">File</label></div>
|
|
||||||
<div class="six columns"><input type="file" id="input-file-flip" /></div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="six columns text-right">Bytes to flip</div>
|
|
||||||
<div class="six columns">
|
|
||||||
<input type="radio" value="4" id="radio4" name="radio-bytes" checked /><label for="radio4">4 <small>(N64 ROMs and savegames)</small></label>
|
|
||||||
<input type="radio" value="8" id="radio8" name="radio-bytes" /><label for="radio8">8 <small>(old GBA flashcards)</small></label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="buttons">
|
|
||||||
<button onclick="flipBytesInFile()" id="button-save"><i class="icon settings"></i> Flip bytes</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- FOOTER -->
|
||||||
|
<footer>
|
||||||
|
Rom Patcher JS <small>rev 20170428</small> by <a href="/">Marc Robledo</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>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</div></body></html>
|
||||||
</body></html>
|
|
7
ips.js
7
ips.js
|
@ -1,4 +1,4 @@
|
||||||
/* IPS module for RomPatcher.js v20180427 - Marc Robledo 2016-2018 - http://www.marcrobledo.com/license */
|
/* IPS module for RomPatcher.js v20180428 - Marc Robledo 2016-2018 - http://www.marcrobledo.com/license */
|
||||||
/* File format specification: http://www.smwiki.net/wiki/IPS_file_format */
|
/* File format specification: http://www.smwiki.net/wiki/IPS_file_format */
|
||||||
|
|
||||||
var MAX_IPS_SIZE=16777216;
|
var MAX_IPS_SIZE=16777216;
|
||||||
|
@ -33,7 +33,7 @@ IPS.prototype.toString=function(){
|
||||||
s+='\nTruncate at: 0x'+this.truncate.toString(16);
|
s+='\nTruncate at: 0x'+this.truncate.toString(16);
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
IPS.prototype.export=function(){
|
IPS.prototype.export=function(fileName){
|
||||||
var binFileSize=0;
|
var binFileSize=0;
|
||||||
binFileSize+=5; //PATCH string
|
binFileSize+=5; //PATCH string
|
||||||
for(var i=0; i<this.records.length; i++){
|
for(var i=0; i<this.records.length; i++){
|
||||||
|
@ -48,7 +48,7 @@ IPS.prototype.export=function(){
|
||||||
|
|
||||||
tempFile=new MarcBinFile(binFileSize);
|
tempFile=new MarcBinFile(binFileSize);
|
||||||
tempFile.littleEndian=false;
|
tempFile.littleEndian=false;
|
||||||
tempFile.fileName='patch.ips';
|
tempFile.fileName=fileName+'.ips';
|
||||||
tempFile.writeString(0, 'PATCH', 5);
|
tempFile.writeString(0, 'PATCH', 5);
|
||||||
var seek=5;
|
var seek=5;
|
||||||
for(var i=0; i<this.records.length; i++){
|
for(var i=0; i<this.records.length; i++){
|
||||||
|
@ -75,6 +75,7 @@ IPS.prototype.export=function(){
|
||||||
|
|
||||||
return tempFile
|
return tempFile
|
||||||
}
|
}
|
||||||
|
IPS.prototype.validateInput=function(romFile){return '?'}
|
||||||
IPS.prototype.apply=function(romFile){
|
IPS.prototype.apply=function(romFile){
|
||||||
var newFileSize=romFile.fileSize;
|
var newFileSize=romFile.fileSize;
|
||||||
for(var i=0; i<this.records.length; i++){
|
for(var i=0; i<this.records.length; i++){
|
||||||
|
|
BIN
logo.png
BIN
logo.png
Binary file not shown.
Before Width: | Height: | Size: 2.1 KiB |
BIN
logo192.png
Normal file
BIN
logo192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.5 KiB |
17
manifest.json
Normal file
17
manifest.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"short_name":"Rom Patcher JS",
|
||||||
|
"name":"Rom Patcher JS",
|
||||||
|
"icons":[
|
||||||
|
{
|
||||||
|
"src": "logo192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png",
|
||||||
|
"density": "1.0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"start_url": "index.html",
|
||||||
|
"display": "standalone",
|
||||||
|
"orientation": "portrait",
|
||||||
|
"theme_color": "#31343a",
|
||||||
|
"background_color": "#31343a"
|
||||||
|
}
|
9
ups.js
9
ups.js
|
@ -1,4 +1,4 @@
|
||||||
/* UPS module for RomPatcher.js v20180427 - Marc Robledo 2017-2018 - http://www.marcrobledo.com/license */
|
/* UPS module for RomPatcher.js v20180428 - Marc Robledo 2017-2018 - http://www.marcrobledo.com/license */
|
||||||
/* File format specification: http://www.romhacking.net/documents/392/ */
|
/* File format specification: http://www.romhacking.net/documents/392/ */
|
||||||
|
|
||||||
var UPS_MAGIC='UPS1';
|
var UPS_MAGIC='UPS1';
|
||||||
|
@ -21,7 +21,7 @@ UPS.prototype.toString=function(){
|
||||||
s+='\nOutput file checksum: '+this.checksumOutput;
|
s+='\nOutput file checksum: '+this.checksumOutput;
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
UPS.prototype.export=function(){
|
UPS.prototype.export=function(fileName){
|
||||||
var encodedSizeInput=encodeVLV(this.sizeInput);
|
var encodedSizeInput=encodeVLV(this.sizeInput);
|
||||||
var encodedSizeOutput=encodeVLV(this.sizeOutput);
|
var encodedSizeOutput=encodeVLV(this.sizeOutput);
|
||||||
var encodedRecords=[];
|
var encodedRecords=[];
|
||||||
|
@ -38,7 +38,7 @@ UPS.prototype.export=function(){
|
||||||
|
|
||||||
tempFile=new MarcBinFile(binFileSize);
|
tempFile=new MarcBinFile(binFileSize);
|
||||||
tempFile.littleEndian=false;
|
tempFile.littleEndian=false;
|
||||||
tempFile.fileName='patch.ups';
|
tempFile.fileName=fileName+'.ups';
|
||||||
tempFile.writeString(0, UPS_MAGIC, UPS_MAGIC.length);
|
tempFile.writeString(0, UPS_MAGIC, UPS_MAGIC.length);
|
||||||
|
|
||||||
tempFile.writeBytes(4, encodedSizeInput);
|
tempFile.writeBytes(4, encodedSizeInput);
|
||||||
|
@ -60,8 +60,9 @@ UPS.prototype.export=function(){
|
||||||
|
|
||||||
return tempFile
|
return tempFile
|
||||||
}
|
}
|
||||||
|
UPS.prototype.validateSource=function(romFile){return crc32(romFile)===this.checksumInput}
|
||||||
UPS.prototype.apply=function(romFile){
|
UPS.prototype.apply=function(romFile){
|
||||||
if(crc32(romFile)!==this.checksumInput){
|
if(!this.validateSource(romFile)){
|
||||||
MarcDialogs.alert('Error: invalid input ROM checksum');
|
MarcDialogs.alert('Error: invalid input ROM checksum');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue