From c5917c0e81464ab17940c574895a46046700a8a5 Mon Sep 17 00:00:00 2001 From: Lisa Milne Date: Tue, 12 Dec 2023 17:03:04 +1000 Subject: [PATCH] tty part 2 - theoretically --- clite/bios.js | 12 ++ clite/core.js | 118 ++++++++++- clite/vga.js | 576 -------------------------------------------------- 3 files changed, 120 insertions(+), 586 deletions(-) delete mode 100644 clite/vga.js diff --git a/clite/bios.js b/clite/bios.js index 81b7962..6986789 100644 --- a/clite/bios.js +++ b/clite/bios.js @@ -424,18 +424,26 @@ bios.input.keyboard = { switch (key) { case "Down": case "ArrowDown": + k.char = String.fromCharCode(17); + k.lchr = k.char; k.code = 17; break; case "Up": case "ArrowUp": + k.char = String.fromCharCode(18); + k.lchr = k.char; k.code = 18; break; case "Left": case "ArrowLeft": + k.char = String.fromCharCode(19); + k.lchr = k.char; k.code = 19; break; case "Right": case "ArrowRight": + k.char = String.fromCharCode(20); + k.lchr = k.char; k.code = 20; break; case "Enter": @@ -445,9 +453,13 @@ bios.input.keyboard = { break; case "Esc": case "Escape": + k.char = String.fromCharCode(27); + k.lchr = k.char; k.code = 27; break; case "Shift": + k.char = String.fromCharCode(15); + k.lchr = k.char; k.code = 15; break; case "Tab": diff --git a/clite/core.js b/clite/core.js index aa94732..395d707 100644 --- a/clite/core.js +++ b/clite/core.js @@ -548,6 +548,7 @@ license.txt:/etc/license:0:0:-rw-r--r--`; } } function init5(env,io) { + clite.tty.clear(0); clite.proc.setLogin(io.pid,1); clite.lib.exec('/bin/sh',['sh'],env,io); } @@ -2217,6 +2218,22 @@ clite.tty = { }else{ clite.console.drawAt(updateX,updateY,clite.tty.data.ttys[id].data[updateY][updateX]); } + }, + popLine:function(t) { + var off = -1; + var l = ''; + for (var i=0; i=clite.tty.data.ttys.length) + return false; + + var t = clite.tty.data.ttys[id]; + if (t.raw) { + if (t.buff.length > 0) { + var k = t.buff.shift(); + cb(k.char); + return true; + } + }else{ + var l = clite.tty.internal.popLine(t); + if (l != null) { + cb(l); + return true; + } + } + + clite.tty.data.ttys[id].rcb = cb; + + return true; }, write:function(id,str) { if (id<0 || id>=clite.tty.data.ttys.length) @@ -2278,6 +2355,27 @@ clite.tty = { clite.tty.internal.write(id,ch); } } + }, + clear:function(id) { + if (id<0 || id>=clite.tty.data.ttys.length) + return; + var t = clite.tty.data.ttys[id]; + + for (var y=0; y<25; y++) { + t.data[y] = []; + for (var x=0; x<80; x++) { + t.data[y].push({bg:t.bg,fg:t.fg,bk:false,ch:' '}); + } + } + + t.x = 0; + t.y = 0; + + if (id != clite.tty.data.activeID) + return; + + clite.console.drawBuff(t.data); + clite.console.setCursor(0,0); } }; @@ -2314,10 +2412,10 @@ clite.console = { if (clite.console.data.state == 1) { for (var y=0; y<25; y++) { for (var x=0; x<80; x++) { - unix.vga.io.write(x,y,buff[y][x].ch); - unix.vga.io.writeSet(0,x,y,buff[y][x].bg); - unix.vga.io.writeSet(1,x,y,buff[y][x].fg); - unix.vga.io.writeSet(2,x,y,buff[y][x].bk); + clite.console.data.vgaio.write(x,y,buff[y][x].ch); + clite.console.data.vgaio.writeSet(0,x,y,buff[y][x].bg); + clite.console.data.vgaio.writeSet(1,x,y,buff[y][x].fg); + clite.console.data.vgaio.writeSet(2,x,y,buff[y][x].bk); } } } @@ -2325,10 +2423,10 @@ clite.console = { drawLine:function(y,buff) { if (clite.console.data.state == 1) { for (var x=0; x<80; x++) { - unix.vga.io.write(x,y,buff[x].ch); - unix.vga.io.writeSet(0,x,y,buff[x].bg); - unix.vga.io.writeSet(1,x,y,buff[x].fg); - unix.vga.io.writeSet(2,x,y,buff[x].bk); + clite.console.data.vgaio.write(x,y,buff[x].ch); + clite.console.data.vgaio.writeSet(0,x,y,buff[x].bg); + clite.console.data.vgaio.writeSet(1,x,y,buff[x].fg); + clite.console.data.vgaio.writeSet(2,x,y,buff[x].bk); } } }, diff --git a/clite/vga.js b/clite/vga.js deleted file mode 100644 index 239ce86..0000000 --- a/clite/vga.js +++ /dev/null @@ -1,576 +0,0 @@ - -var bios = { - data:{ - version:0.1, - vga:null, - id:'BIOS' - }, - lib:{ - code:{ - base:null, - load:function(name,callback) { - var head = document.getElementsByTagName('head')[0]; - var script = document.createElement('script'); - var file = ''; - if (bios.lib.code.base != null) - file += bios.lib.code.base+'/'; - file +=name+'.js'; - script.type = 'text/javascript'; - script.src = file; - script.onload = callback; - head.appendChild(script); - } - }, - getHex:function(s) { - if (typeof s === 'string') - s = parseInt(s); - if (typeof s !== 'number') - return '0'; - return s.toString(16).toUpperCase(); - }, - writeStringVC:function(x,y,v) { - for (var i=0; i= 80) - break; - bios.video.internal.write(x+i,y,v[i]); - } - }, - writeStringVGA:function(x,y,v,fg) { - for (var i=0; i= 80) - break; - bios.data.vga.write(x+i,y,v[i]); - } - if (typeof fg === 'undefined') - return; - for (var i=0; i= 80) - break; - bios.data.vga.writeSet(1,x+i,y,fg); - } - } - }, - input:{ - el:null, - devices:[], - readers:[], - device:{ - register:function(name,data) { - if (typeof bios.input.devices[name] !== 'undefined') - return false; - if (typeof data !== 'object') - return false; - if (typeof data.element === 'undefined') - return false; - bios.input.devices[name] = data; - bios.input.el = document.getElementById('input'); - bios.input.el.appendChild(data.element); - return true; - }, - deregister:function(name) { - } - }, - reader:{ - register:function(name,caller) { - if (typeof bios.input.devices[name] === 'undefined') - return null; - bios.input.readers[caller] = name; - return bios.input.devices[name]; - }, - deregister:function(name) { - if (typeof bios.input.readers[name] === 'undefined') - return; - delete bios.input.readers[name]; - } - } - }, - output:{ - el:null, - devices:{}, - writers:[], - device:{ - register:function(name,data) { - if (typeof bios.output.devices[name] !== 'undefined') - return false; - if (typeof data !== 'object') - return false; - if (typeof data.element === 'undefined') - return false; - bios.output.devices[name] = data; - if (name === 'vga') - return true; - if (data.element) { - bios.output.el = document.getElementById('output'); - bios.output.el.appendChild(data.element); - } - return true; - }, - deregister:function(name) { - if (typeof bios.output.devices[name] === 'undefined') - return; - if (name !== 'vga' && bios.output.devices[name].element) - bios.output.el.removeChild(bios.output.devices[name].element); - delete bios.output.devices[name]; - } - }, - writer:{ - register:function(name,caller) { - if (typeof bios.output.devices[name] === 'undefined') - return null; - bios.output.writers[caller] = name; - return bios.output.devices[name]; - }, - deregister:function(name) { - if (typeof bios.output.writers[name] === 'undefined') - return; - delete bios.output.writers[name]; - } - }, - }, - io:{ - data:{ - interrupts:{} - }, - read:function(c) { - switch (c) { - case 0: - return bios.data.id; - break; - default:; - } - return null; - }, - write:function(c,d) { - switch (c) { - case 0: - bios.data.id = d; - document.title = d; - break; - case 1: - bios.fault.data.handler = d; - break; - case 2: - bios.io.interrupt.setHandler('kbd',d); - break; - default:; - } - }, - wait:function(cb,ms) { - if (bios.fault.data.faulted) - return; - setTimeout(function() { - try{ - cb(); - }catch(e) { - bios.fault.process(e); - } - },ms); - }, - interrupt:{ - create:function(name,faults) { - if (typeof bios.io.data.interrupts[name] !== 'undefined') - return false; - bios.io.data.interrupts[name] = { - name:name, - crit:faults, - handler:null - }; - return true; - }, - setHandler:function(name,cb) { - if (typeof bios.io.data.interrupts[name] === 'undefined') - return false; - bios.io.data.interrupts[name].handler = cb; - return true; - }, - fire:function(name,data) { - if (typeof bios.io.data.interrupts[name] === 'undefined') - return; - if (bios.io.data.interrupts[name].handler == null) { - if (bios.io.data.interrupts[name].crit) { - bios.fault.process(new Error('Unhandled Interrupt')); - } - return; - } - try{ - bios.io.data.interrupts[name].handler(data); - }catch(e) { - bios.fault.process(new Error('Unhandled Interrupt')); - } - } - }, - setCPU:function(data) {}, - getCPU:function() {} - }, - fault:{ - data:{ - handler:null, - faulted:false - }, - process:function(e) { - if (!bios.fault.data.handler) - return bios.fault.triple(e); - try{ - bios.fault.data.handler(e.message); - }catch(err) { - bios.fault.triple(e); - } - }, - triple:function(e) { - bios.fault.data.faulted = true; - console.log('Triple Fault'); - throw e; - } - }, - init:function() { - bios.io.write(0,'WEB BIOS '+bios.data.version); - bios.video.init(); - bios.lib.writeStringVC(2,0,'JS Basic Input Output System'); - var v = bios.data.version.toString(); - bios.lib.writeStringVC(78-v.length,0,v); - bios.lib.writeStringVC(3,1,'Initialising...'); - bios.lib.writeStringVC(3,2,'Video Core:'); - bios.lib.writeStringVC(25,2,'Done'); - bios.lib.writeStringVC(3,3,'Video Graphics Array:'); - bios.video.initVGA(); - bios.data.vga = bios.output.writer.register('vga','biosvga'); - if (bios.data.vga == null) { - bios.lib.writeStringVC(25,3,'Failed'); - return; - } - for (var i=0; i<80; i++) { - bios.data.vga.writeSet(0,i,0,15); - bios.data.vga.writeSet(1,i,0,0); - } - for (var i=25; i<30; i++) { - bios.data.vga.writeSet(1,i,2,2); - } - bios.lib.writeStringVGA(25,3,'Done',2); - - bios.lib.writeStringVGA(3,4,'Keyboard:'); - bios.keyboard.init(); - bios.lib.writeStringVGA(25,4,'Done',2); - - bios.lib.writeStringVGA(3,5,'Audio:'); - bios.audio.init(); - bios.lib.writeStringVGA(25,5,'Done',2); - - bios.lib.writeStringVGA(3,7,'Seeking Bootable Device...'); - - var d = bios.storage.io.test(); - - for (var i=0; i 79 || y < 0 || y > 24) - return; - var c = bios.video.getPix(x,y); - c.textContent = v; - }, - setBG:function(x,y,id) { - if (id < 0 || id > 15) - return; - var c = bios.video.getPix(x,y); - c.data.bg = bios.lib.getHex(id); - c.className = bios.video.internal.dataToClass(c.data); - }, - setFG:function(x,y,id) { - if (id < 0 || id > 15) - return; - var c = bios.video.getPix(x,y); - c.data.fg = bios.lib.getHex(id); - c.className = bios.video.internal.dataToClass(c.data); - }, - setBlink:function(x,y,id) { - if (typeof id !== 'boolean') - return; - var c = bios.video.getPix(x,y); - c.data.bk = id; - c.className = bios.video.internal.dataToClass(c.data); - }, - writeSet:function(name,x,y,id) { - if (x < 0 || x > 79 || y < 0 || y > 24) - return; - switch(name) { - case 0: - bios.video.internal.setBG(x,y,id); - break; - case 1: - bios.video.internal.setFG(x,y,id); - break; - case 2: - bios.video.internal.setBlink(x,y,id); - break; - default:; - } - }, - dataToClass:function(d) { - var c = 'vga-b'+d.bg+' vga-f'+d.fg; - if (d.bk) - c += ' vga-blink'; - return c; - } - }, - io:{}, - getElement:function() { - bios.video.data.el = document.getElementById('vga'); - if (typeof bios.video.data.el !== 'undefined' && bios.video.data.el != null) - return bios.video.data.el; - bios.video.data.el = document.createNode('div'); - bios.video.data.el.id = 'vga'; - bios.video.data.el.className = 'vga'; - document.body.appendChild(bios.video.data.el); - return bios.video.data.el; - }, - getPix:function(x,y) { - return document.getElementById('vga-'+y+'-'+x); - }, - setMode:function(modedata) { - if (modedata === null || typeof modedata !== 'object') - return false; - if (typeof modedata.write !== 'function') - return false; - if (typeof modedata.el === 'undefined') - modedata.el = bios.video.getElement(); - if (bios.video.data.el == modedata.el) { - modedata.el.innerHTML = ''; - }else{ - if (modedata.el.parentNode != bios.video.data.el) - bios.video.data.el.appendChild(modedata.el); - } - bios.video.io = modedata; - return true; - }, - init:function() { - bios.video.internal.el = bios.video.getElement(); - if (!bios.video.setMode(bios.video.internal)) - return false; - bios.video.data.el.innerHTML = ''; - var ypx; - var xpx; - var c = document.createElement('span'); - c.textContent = 'W'; - bios.video.data.el.appendChild(c); - ypx = c.offsetHeight; - xpx = c.offsetWidth; - bios.video.data.el.innerHTML = ''; - bios.video.data.el.style.width = (xpx*80)+'px'; - bios.video.data.el.style.height = (ypx*25)+'px'; - bios.video.data.el.style.position = 'relative'; - for (var y=0; y<25; y++) { - for (var x=0; x<80; x++) { - var c = document.createElement('div'); - c.className = 'vga-b0 vga-fF'; - c.style.position = 'absolute'; - c.style.top = (y*ypx)+'px'; - c.style.left = (x*xpx)+'px'; - c.style.width = xpx+'px'; - c.style.height = ypx+'px'; - c.data = {bg:'0',fg:'F',bk:false}; - c.id = 'vga-'+y+'-'+x; - bios.video.data.el.appendChild(c); - } - } - bios.video.data.isinit = true; - return bios.video.data.isinit; - }, - initVGA:function() { - var e = bios.video.getElement(); - e.style.cursor = 'none'; - bios.output.device.register('vga',{element:e,write:bios.video.io.write,writeSet:bios.video.io.writeSet,reinit:bios.video.reinit}); - }, - reinit:function() { - } -}; - -bios.keyboard = { - data:{ - el:null - }, - internal:{ - rawDown:function(e) { - if (e.isComposing) - return; - var k = { - down:true, - code:0, - char:0, - lchr:0 - }; - if (e.key.length == 1) { - k.char = e.key; - k.lchr = e.key.toLowerCase(); - k.code = k.lchr.charCodeAt(0); - }else{ - bios.keyboard.internal.getKeyData(e.key,k); - } - //console.log('rawDown: "'+k.char+'":"'+k.lchr+'":"'+k.code+'"'); - if (k.code == 0) - return false; - bios.io.interrupt.fire('kbd',k); - return false; - }, - rawUp:function(e) { - if (e.isComposing) - return; - var k = { - down:false, - code:0, - char:0, - lchr:0 - }; - if (e.key.length == 1) { - k.char = e.key; - k.lchr = e.key.toLowerCase(); - k.code = k.lchr.charCodeAt(0); - }else{ - bios.keyboard.internal.getKeyData(e.key,k); - } - if (k.code == 0) - return false; - bios.io.interrupt.fire('kbd',k); - return false; - }, - resetFocus:function(e) { - bios.io.wait(function() {document.getElementById('kbd').focus()},1); - return false; - }, - getKeyData:function(key,k) { - switch (key) { - case "Down": - case "ArrowDown": - k.code = 17; - break; - case "Up": - case "ArrowUp": - k.code = 18; - break; - case "Left": - case "ArrowLeft": - k.code = 19; - break; - case "Right": - case "ArrowRight": - k.code = 20; - break; - case "Enter": - k.char = String.fromCharCode(10); - k.lchr = k.char; - k.code = 10; - break; - case "Esc": - case "Escape": - k.code = 27; - break; - case "Shift": - k.code = 15; - break; - case "Tab": - k.char = String.fromCharCode(9); - k.lchr = k.char; - k.code = 9; - break; - case "Delete": - k.char = String.fromCharCode(127); - k.lchr = k.char; - k.code = 127; - break; - default: - k.code = key; - } - } - }, - getElement:function() { - bios.keyboard.data.el = document.getElementById('kbd'); - if (typeof bios.keyboard.data.el === 'undefined' || bios.keyboard.data.el == null) { - bios.keyboard.data.el = document.createElement('textarea'); - bios.keyboard.data.el.id = 'kbd'; - bios.keyboard.data.el.className = 'kbd'; - bios.keyboard.data.el.style.zIndex = '100'; - bios.keyboard.data.el.style.display = 'block'; - } - bios.keyboard.data.el.addEventListener('keydown',bios.keyboard.internal.rawDown); - bios.keyboard.data.el.addEventListener('keyup',bios.keyboard.internal.rawUp); - bios.keyboard.data.el.addEventListener('focusout',bios.keyboard.internal.resetFocus); - return bios.keyboard.data.el; - }, - init:function() { - var e = bios.keyboard.getElement(); - bios.io.interrupt.create('kbd',false); - // register the device without a read call, as this device fires interrupts - bios.input.device.register('kbd',{element:e,read:null,reinit:bios.video.reinit}); - e.focus(); - bios.keyboard.internal.resetFocus(); - }, - reinit:function() { - } -}; - -bios.audio = { - data:{ - isinit:false, - noped:false, - bell:null, - output:null, - input:null - }, - init:function() { - bios.audio.data.output = new Audio(); - bios.audio.data.bell = new Audio('beep.mp3'); - bios.audio.data.bell.addEventListener("canplaythrough", function(e) { - // play it as soon as possible to test if audio is possible - var promise = bios.audio.data.bell.play(); - if (promise !== undefined) { - promise.then(_ => { - bios.audio.data.isinit = true; - }).catch(error => { - bios.audio.data.noped = true; - }); - } - }); - bios.output.device.register('bell',{element:null,write:bios.audio.bell,writeSet:function() {},reinit:function() {}}); - }, - bell:function() { - if (!bios.audio.data.isinit) - return; - bios.audio.data.bell.play(); - }, - reinit:function() { - } -};