mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 11:51:49 +09:00
virtual terminal wip
This commit is contained in:
@@ -723,11 +723,24 @@ Object.freeze(_TVDOS.DRV.FS.DEVCON)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
let mkvtcontext = (index, VMEM) => {
|
||||
return { // VT0 is reserved for symlink to physical terminal
|
||||
isActive: (index === 0 || index === "0"),
|
||||
buffer: (index === 0 || index === "0") ? undefined : VMEM
|
||||
// TODO: getCursorYX, setCursorYX, setCursorX, setCursorY, getTextForeBack, setTextFore, setTextBack
|
||||
// all read/write form the VMEM
|
||||
}
|
||||
}
|
||||
|
||||
// byte-to-byte copy of the 512 KB of VRAM
|
||||
function mkdevvt(index) {
|
||||
|
||||
// VT0 is reserved for symlink to the physical terminal
|
||||
if (isNaN(index)) return false // check for non-numerics and undefined
|
||||
if (index !== index || index <= 0) return false // check for NaN, 0 and negative values
|
||||
|
||||
// check if the device already exists
|
||||
if (_TVDOS.DRV.FS['DEV'+index] != undefined) return false
|
||||
if (_TVDOS.DRV.FS['DEVVT'+index] != undefined) return false
|
||||
|
||||
let VDEV = {}
|
||||
let VMEM = new Int8Array(512 * 1024)
|
||||
@@ -782,6 +795,7 @@ VDEV.mkFile = () => {}
|
||||
VDEV.remove = () => {}
|
||||
VDEV.exists = () => true
|
||||
|
||||
_TVDOS.VT_CONTEXTS[index] = mkvtcontext(index, VMEM)
|
||||
_TVDOS.DRV.FS['DEVVT'+index] = VDEV
|
||||
|
||||
Object.freeze(_TVDOS.DRV.FS['DEVVT'+index])
|
||||
@@ -846,6 +860,9 @@ _TVDOS.DRV.FS.DEVPT.mkDir = () => {}
|
||||
_TVDOS.DRV.FS.DEVPT.mkFile = () => {}
|
||||
_TVDOS.DRV.FS.DEVPT.remove = () => {}
|
||||
_TVDOS.DRV.FS.DEVPT.exists = () => true
|
||||
|
||||
mkvtcontext(0)
|
||||
|
||||
Object.freeze(_TVDOS.DRV.FS.DEVPT)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -56,11 +56,33 @@ let runner = undefined
|
||||
|
||||
function startNewInstance() {
|
||||
runner = parallel.attachProgram("TVDOS", parallel.spawnNewContext(), bios)
|
||||
|
||||
serial.println("Starting new instance "+runner)
|
||||
|
||||
parallel.launch(runner)
|
||||
sys.sleep(1000)
|
||||
}
|
||||
|
||||
function startNewInstanceOnVT(vtIndex) {
|
||||
if (isNaN(index) || index !== index) throw Error("VT index must be a numeric value")
|
||||
if (index <= 0) throw Error(`VT index cannot be zero or negative (${vtIndex})`)
|
||||
|
||||
// Ensure VT exists
|
||||
if (!_TVDOS.VT_CONTEXTS[vtIndex]) {
|
||||
mkdevvt(vtIndex)
|
||||
}
|
||||
|
||||
// Create context with VT binding
|
||||
let contextInit = `_TVDOS.CURRENT_VT = ${vtIndex};${bios}`
|
||||
|
||||
runner = parallel.attachProgram(`TVDOS-VT${vtIndex}`, parallel.spawnNewContext(), contextInit)
|
||||
|
||||
serial.println(`Starting new instance ${runner} on VT${vtIndex}`)
|
||||
|
||||
parallel.launch(runner)
|
||||
sys.sleep(50)
|
||||
}
|
||||
|
||||
const randomkeypusher = `
|
||||
while (1) {
|
||||
sys.poke(-38, 65 + (Math.random()*26)|0)
|
||||
|
||||
@@ -456,7 +456,11 @@ con.move = function(y, x) {
|
||||
//print("\x1B["+(y|0)+";"+(x|0)+"H");
|
||||
// NOT using ANSI escape sequence as it conflicts with some multilingual drive which redefines PRINT function
|
||||
// and obviously this method is faster albeit less genuine :p
|
||||
graphics.setCursorYX(y|0, x|0);
|
||||
|
||||
let activeVT = _TVDOS.ACTIVE_VT || 0 // 0 is physical terminal
|
||||
let vt = _TVDOS.VT_CONTEXTS[activeVT]
|
||||
|
||||
vt.setCursorYX(y|0, x|0)
|
||||
};
|
||||
con.addch = function(c) {
|
||||
graphics.putSymbol(c|0);
|
||||
@@ -474,22 +478,25 @@ con.getmaxyx = function() {
|
||||
return graphics.getTermDimension(); // [rows, cols]
|
||||
};
|
||||
con.getyx = function() {
|
||||
return graphics.getCursorYX();
|
||||
let activeVT = _TVDOS.ACTIVE_VT || 0 // 0 is physical terminal
|
||||
let vt = _TVDOS.VT_CONTEXTS[activeVT]
|
||||
|
||||
return vt.getCursorYX()
|
||||
};
|
||||
con.curs_up = function() {
|
||||
let [y,x] = graphics.getCursorYX();
|
||||
let [y,x] = con.getyx();
|
||||
con.move(y-1,x);
|
||||
};
|
||||
con.curs_down = function() {
|
||||
let [y,x] = graphics.getCursorYX();
|
||||
let [y,x] = con.getyx();
|
||||
con.move(y+1,x);
|
||||
};
|
||||
con.curs_left = function() {
|
||||
let [y,x] = graphics.getCursorYX();
|
||||
let [y,x] = con.getyx();
|
||||
con.move(y,x-1);
|
||||
};
|
||||
con.curs_right = function() {
|
||||
let [y,x] = graphics.getCursorYX();
|
||||
let [y,x] = con.getyx();
|
||||
con.move(y,x+1);
|
||||
};
|
||||
con.hitterminate = function() { // ^C
|
||||
|
||||
@@ -4,6 +4,7 @@ import net.torvald.UnsafeHelper
|
||||
import net.torvald.UnsafePtr
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.toHex
|
||||
import net.torvald.tsvm.peripheral.*
|
||||
import org.graalvm.polyglot.Context
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.nio.charset.Charset
|
||||
@@ -67,6 +68,51 @@ class VM(
|
||||
var stopDown = false
|
||||
var sysrqDown = false
|
||||
|
||||
|
||||
private var currentContext: Context? = null
|
||||
|
||||
fun setCurrentJSContext(context: Context) {
|
||||
currentContext = context
|
||||
}
|
||||
|
||||
private fun getCurrentJSContext(): Context {
|
||||
return currentContext ?: throw IllegalStateException("No JavaScript context available")
|
||||
}
|
||||
|
||||
|
||||
|
||||
// VT tracking of the VM
|
||||
private var currentVTIndex = 0 // default to physical terminal
|
||||
private val vtOutputStream = mutableMapOf<Int, OutputStream>()
|
||||
private val vtInputStream = mutableMapOf<Int, InputStream>()
|
||||
|
||||
fun getCurrentVT(): Int {
|
||||
// try to read from JS context
|
||||
try {
|
||||
val context = getCurrentJSContext()
|
||||
val currentVT = context.eval("js", "_TVDOS.CURRENT_VT || 0").asInt()
|
||||
return currentVT
|
||||
}
|
||||
catch (e: Exception) {
|
||||
return currentVTIndex
|
||||
}
|
||||
}
|
||||
|
||||
fun setCurrentVT(vtIndex: Int) {
|
||||
currentVTIndex = vtIndex
|
||||
// Also update JavaScript context if available
|
||||
try {
|
||||
val context = getCurrentJSContext()
|
||||
context.eval("js", "_TVDOS.CURRENT_VT = $vtIndex")
|
||||
}
|
||||
catch (e: Exception) {
|
||||
// Context not available, continue with local tracking
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
var romMapping = 255
|
||||
internal set
|
||||
|
||||
|
||||
@@ -143,14 +143,16 @@ class VMJSR223Delegate(private val vm: VM) {
|
||||
}
|
||||
|
||||
fun print(s: Any) {
|
||||
//System.out.print("[Nashorn] $s")
|
||||
//System.out.print(s)
|
||||
vm.getPrintStream().write("$s".toByteArray(VM.CHARSET))
|
||||
//vm.getPrintStream().write("$s".toByteArray(VM.CHARSET))
|
||||
val vtIndex = vm.getCurrentVT() // Get current VT from VM context
|
||||
val outputStream = vm.getVTOutputStream(vtIndex)
|
||||
outputStream.write("$s".toByteArray(VM.CHARSET))
|
||||
}
|
||||
fun println(s: Any = "") {
|
||||
System.out.println("[Graal] $s")
|
||||
//System.out.println(s)
|
||||
vm.getPrintStream().write(("$s\n").toByteArray(VM.CHARSET))
|
||||
//vm.getPrintStream().write(("$s\n").toByteArray(VM.CHARSET))
|
||||
val vtIndex = vm.getCurrentVT() // Get current VT from VM context
|
||||
val outputStream = vm.getVTOutputStream(vtIndex)
|
||||
outputStream.write("$s\n".toByteArray(VM.CHARSET))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -80,6 +80,9 @@ object VMRunnerFactory {
|
||||
|
||||
val fr = this::class.java.classLoader.getResourceAsStream("net/torvald/tsvm/JS_INIT.js")
|
||||
val prg = fr.readAllBytes().decodeToString()
|
||||
|
||||
vm.setCurrentJSContext(context)
|
||||
|
||||
context.eval("js", sanitiseJS(prg))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user