Created
January 31, 2019 22:42
-
-
Save twilight-sparkle-irl/cc2c2663c0b2158f4d4b36e0a6aabd8c to your computer and use it in GitHub Desktop.
a broken smb3 castle scene maker thingy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <!-- | |
| credit to bootsy (@NO_BOOT_DEVICE) | |
| --> | |
| <html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> | |
| <title>smb3.htm</title> | |
| <style type="text/css"> | |
| :root,body { | |
| background-color: black; | |
| color: white; | |
| font-family: Sans-Serif; | |
| text-align: center; | |
| } | |
| h1 { | |
| margin-bottom: 0.1em; | |
| } | |
| h2 { | |
| font-size: 1em; | |
| font-weight: normal; | |
| margin: 0 auto 5em auto; | |
| } | |
| .arrow { | |
| font-size: 2.0em; | |
| font-weight: bold; | |
| margin: 0; | |
| } | |
| #warning { | |
| background-color: darkorange; | |
| color: black; | |
| padding: 0.4em 0.75em; | |
| } | |
| .q { | |
| background-color:darkslategrey; | |
| color:lightgray; | |
| padding: 3px 6px; | |
| font-family: monospace; | |
| } | |
| </style> | |
| <script type="text/javascript"> | |
| Array.prototype.replaceAt = function(index, replacement) { | |
| return [this.slice(0, index), replacement, this.slice(index + replacement.length)].flat(); | |
| } | |
| function warn(x,html) { | |
| document.getElementById('warning').hidden=(x.length===0) | |
| document.getElementById('warning')[(html?'innerHTML':'innerText')] = x; | |
| } | |
| // where i went wrong: https://stackoverflow.com/a/31637761/6726363 | |
| // that's so you can see what i was thinking, not to use it | |
| function htmlSafe(e) { | |
| return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"}) | |
| } | |
| // uncrunch the original screen hex to ppuData (this works i promise) | |
| for(ppuData='FElllk93kjD8Di92h32g19fCDeD7dg30ccccbbb07a33`58593__1`_E^lj^`h]_0g_4[[ghZ`31YD4X0736[bWDDV2E2E2F2FUUUUUUUU2T0505SYYYR06g^RRR06QFCFCPFDFDPOkkNSSSMPPPL0C0C0D0DK15171517J14161416I90909090HffffGIIIIIIIIJJJJJJJJ341C4445LLLLP444531`_6NNNNNNl_0g585hC3A94HHHHH96k^3FhBEd9AD8eABCClCV4CBCBi1DBXEAkljZC3dXlBAD8VD6ldD0CClD1XXVk]eCBD0VCe5DECBDCXD3EANNjZBFDBXD0CCXlD5D8VD3lCV7XN]Be0D6i2lC6D0VD3lCeEl81XlD2D0V9`A39ZD2dD0VD6XldiClD1D0D2DAE9N9`835^`959GGGGG7313F[ba10111213Q20212223Wa24252627Q18f1A1BWa282hA2BQ0A0B0E0FWcc070607MM_1`56573ERYY06MMS5657KKKKKKKKTE2E2F2F2F2FTE2EOOOOOOOOFC';G=/[G-l]/.exec(ppuData);)with(ppuData.split(G))ppuData=join(shift()); | |
| ppuData = ppuData.match(/.{2}/g) | |
| var maxLines = ppuData.filter(x=>x=='92').length | |
| </script> | |
| <script type="text/javascript"> | |
| function update(s) { | |
| if(s.length==0) {document.getElementById('output').value=''} | |
| warn('') // clear warning | |
| document.getElementById('output').value = smb3(s).join`` | |
| } | |
| function smb3(s) { | |
| var convdata = convert(s) | |
| var textData = convdata[0] | |
| var wrappedOrig = convdata[1] | |
| var newPPU = '' | |
| var start = 0 | |
| for(var i=0;i<maxLines;i++) { | |
| console.log(`${i}/${maxLines} (${textData.length}): ${wrappedOrig[i]||'none'}`) | |
| console.log(``) | |
| start = ppuData.indexOf('92',start+1) | |
| console.log(`${ppuData.slice(start,start+10).join` `}`) | |
| console.log(`${(textData[i]||Array(10).fill('FE')).join` `}`) | |
| if(textData.length > i) { | |
| console.log('') | |
| newPPU = ppuData.replaceAt(start, textData[i]) | |
| } else { | |
| newPPU = ppuData.replaceAt(start, Array(10).fill('FE')) // replace with blank lines | |
| } | |
| console.log('-'.repeat(40)) | |
| } | |
| if(i<textData.length){warn(`Text too long. Last chunk accepted was <span class=q>${wrappedOrig[i]}</span>.`,true)} | |
| return newPPU; | |
| } | |
| function convert(s) { | |
| // uses https://datacrystal.romhacking.net/wiki/Super_Mario_Bros._3:TBL | |
| var sS = s.match(/.{1,9}(\s|$)|\S+?(\s|$)/g) | |
| var x = sS.map(actuallyConvert); // we don't handle the throw, the function calling us does. | |
| return [x.map(x=>x.padEnd(20,'FE').match(/.{2}/g)),sS] // pad all strings to 20 chars with spaces, and also return original wrapped for error purposes | |
| } | |
| function actuallyConvert(s){ | |
| var x = [...s].map(function (m) { | |
| return { | |
| "w":"81","x":"88","A":"B0","B":"B1","C":"B2","D":"B3","E":"B4","F":"B5","G":"B6","H":"B7","I":"B8","J":"B9","K":"BA","L":"BB","M":"BC","N":"BD","O":"BE","P":"BF","Q":"C0","R":"C1","S":"C2","T":"C3","U":"C4","V":"C5","W":"C6","X":"C7","Y":"C8","Z":"C9","a":"D0","b":"D1","c":"D2","d":"D3","e":"D4","f":"D5","g":"D6","h":"D7","i":"D8","j":"D9","k":"DA","l":"DB","m":"DC","n":"DD","o":"DE","p":"DF","q":"CA","r":"CB","s":"CC","t":"CD","u":"CE","v":"CF","y":"8C","z":"8F",",":"9A",".":"E9","'":"AB","!":"EA","?":"EB"," ":"FE" | |
| }[m] || `[${m}]`; | |
| }).join``; | |
| if(x.includes('[')) { | |
| warn(x.match(/\[.\]/g).map(x=>`Invalid character: ${x[1]}`).join`\n`) | |
| x = x.replace(/\[.\]/g,'FE') // 1f is an X character if loud failure is necessary | |
| } | |
| return x; | |
| } | |
| </script> | |
| </head> | |
| <body> | |
| <h1>smb3.htm</h1> | |
| <h3>paste output to 0x2800 in the PPU Bus memory</h3> | |
| <p><textarea id="input" cols="80" rows="12" onkeyup="update(this.value)" onchange="update(this.value)" autofocus=""></textarea></p> | |
| <p class="arrow">↓</p> | |
| <p><textarea id="output" cols="80" rows="12" readonly="readonly"></textarea></p> | |
| <p id="warning"></p> | |
| <script>update(document.getElementById('input').value)</script> | |
| </body></html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment