Skip to content

Instantly share code, notes, and snippets.

@twilight-sparkle-irl
Created January 31, 2019 22:42
Show Gist options
  • Select an option

  • Save twilight-sparkle-irl/cc2c2663c0b2158f4d4b36e0a6aabd8c to your computer and use it in GitHub Desktop.

Select an option

Save twilight-sparkle-irl/cc2c2663c0b2158f4d4b36e0a6aabd8c to your computer and use it in GitHub Desktop.
a broken smb3 castle scene maker thingy
<!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