204 lines
5.3 KiB
JavaScript
204 lines
5.3 KiB
JavaScript
;(function(w, d) {
|
|
|
|
var screenBuffer = "", inputBuffer = "", screenDom, inputRes = "",
|
|
floader, vm
|
|
|
|
/* screen rendering routine */
|
|
function renderScreen() {
|
|
screenDom.textContent = screenBuffer + inputBuffer + "\u258f"
|
|
screenDom.scrollTop = screenDom.scrollHeight
|
|
}
|
|
|
|
/* external program loading routine */
|
|
function loadProgFileHandler(e) {
|
|
if(e.target.files.length > 0) {
|
|
var fobj = e.target.files[0], rdr = new FileReader()
|
|
rdr.onload = function() {
|
|
var progsrc = rdr.result
|
|
if(progsrc.length > 0) {
|
|
var instrs = progsrc.split(/\s+/), i, l = instrs.length,
|
|
instr, lno, cmd, x, y, z, icount = 0
|
|
for(i=0;i<l;i++) {
|
|
instr = parseInt(instrs[i] || 0)
|
|
if(icount == 0) lno = instr
|
|
else if(icount == 1) cmd = instr
|
|
else if(icount == 2) x = instr
|
|
else if(icount == 3) y = instr
|
|
else if(icount == 4) z = instr
|
|
icount++
|
|
if(icount == 5) {
|
|
vm.ilenter(lno, cmd, x, y, z)
|
|
icount = 0
|
|
}
|
|
}
|
|
lineOut("\nProgram " + fobj.name + " loaded successfully\n> ")
|
|
}
|
|
}
|
|
if(fobj) rdr.readAsText(fobj)
|
|
}
|
|
}
|
|
|
|
/* main input routine:
|
|
* digits 0 to 9, 10 is space,
|
|
* 11 is minus/backspace, 12 is enter, 13 is decimal point,
|
|
* 14 is program load action */
|
|
function doInput(number) {
|
|
if(number >= 0 && number < 10) /* normal digit */
|
|
inputBuffer += ("" + number)
|
|
else if(number == 10) /* space */
|
|
inputBuffer += " "
|
|
else if(number == 11) { /* backspace or minus */
|
|
if(inputBuffer.length == 0)
|
|
inputBuffer += "-"
|
|
else
|
|
inputBuffer = inputBuffer.slice(0, inputBuffer.length - 1)
|
|
} else if(number == 12) { /* enter */
|
|
screenBuffer += inputBuffer + "\n"
|
|
inputRes = inputBuffer
|
|
inputBuffer = ""
|
|
} else if(number == 13) /* decimal point */
|
|
inputBuffer += "."
|
|
else if(number == 14) floader.click() /* trigger program loader */
|
|
renderScreen()
|
|
}
|
|
|
|
function setupInput() {
|
|
/* setup physical keys */
|
|
w.addEventListener("keydown", function(e) {
|
|
switch(e.key) {
|
|
case "0":
|
|
case "1":
|
|
case "2":
|
|
case "3":
|
|
case "4":
|
|
case "5":
|
|
case "6":
|
|
case "7":
|
|
case "8":
|
|
case "9":
|
|
e.preventDefault()
|
|
doInput(parseInt(e.key))
|
|
break
|
|
case "+":
|
|
case "/":
|
|
case " ":
|
|
case "Call":
|
|
case "ArrowDown":
|
|
e.preventDefault()
|
|
doInput(10)
|
|
break
|
|
case "Backspace":
|
|
case "Back":
|
|
case "ArrowLeft":
|
|
case "Delete":
|
|
case "-":
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
doInput(11)
|
|
break
|
|
case "#":
|
|
case "Enter":
|
|
e.preventDefault()
|
|
doInput(12)
|
|
break
|
|
case "*":
|
|
case ",":
|
|
case ".":
|
|
e.preventDefault()
|
|
doInput(13)
|
|
break
|
|
case "l":
|
|
case "L":
|
|
case "ArrowUp":
|
|
case "SoftLeft":
|
|
e.preventDefault()
|
|
doInput(14)
|
|
break
|
|
}
|
|
}, false)
|
|
/* setup virtual keys */
|
|
w.addEventListener("click", function(e) {
|
|
switch(e.target.id) {
|
|
case "b0":
|
|
case "b1":
|
|
case "b2":
|
|
case "b3":
|
|
case "b4":
|
|
case "b5":
|
|
case "b6":
|
|
case "b7":
|
|
case "b8":
|
|
case "b9":
|
|
e.preventDefault()
|
|
doInput(parseInt(e.target.id.slice(1)))
|
|
break
|
|
case "bspc":
|
|
e.preventDefault()
|
|
doInput(10)
|
|
break
|
|
case "bbksp":
|
|
e.preventDefault()
|
|
doInput(11)
|
|
break
|
|
case "benter":
|
|
e.preventDefault()
|
|
doInput(12)
|
|
break
|
|
case "bpoint":
|
|
e.preventDefault()
|
|
doInput(13)
|
|
break
|
|
case "bprogload":
|
|
e.preventDefault()
|
|
doInput(14)
|
|
break
|
|
}
|
|
}, false)
|
|
}
|
|
|
|
function lineOut(s) { /* line output routine */
|
|
screenBuffer += s
|
|
renderScreen()
|
|
}
|
|
|
|
function charOut(c) { /* character output routine */
|
|
screenBuffer += String.fromCharCode(+c)
|
|
renderScreen()
|
|
}
|
|
|
|
function lineIn(cb) {
|
|
inputRes = ""
|
|
var inv = setInterval(function resWait() {
|
|
if(inputRes != "") {
|
|
clearInterval(inv)
|
|
cb(inputRes)
|
|
inputRes = ""
|
|
}
|
|
}, 100)
|
|
}
|
|
|
|
function main() { /* UI entry point */
|
|
screenDom = d.getElementById("screenfield")
|
|
floader = d.getElementById("programloadfield")
|
|
floader.addEventListener("change", loadProgFileHandler, false)
|
|
setupInput()
|
|
prompt = "> "
|
|
vm = createmu808(lineOut, charOut, lineIn)
|
|
lineOut("mu808 v1 by Luxferre\nPROGMEM: 16383 steps\nDATAMEM: 16384 floats\n")
|
|
;(function repl() {
|
|
lineOut(prompt)
|
|
lineIn(function(entryString) {
|
|
var eparts = entryString.split(/[^\-0-9]+/).slice(0, 5),
|
|
lno = parseInt(eparts[0] || 0),
|
|
cmd = parseInt(eparts[1] || 0),
|
|
x = parseInt(eparts[2] || 0),
|
|
y = parseInt(eparts[3] || 0),
|
|
z = parseInt(eparts[4] || 0)
|
|
vm.ilenter(lno, cmd, x, y, z, repl)
|
|
})
|
|
})()
|
|
}
|
|
|
|
w.addEventListener("DOMContentLoaded", main, false)
|
|
})(window, document)
|