mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-15 23:46:06 +09:00
more vt stuffs
This commit is contained in:
@@ -768,7 +768,7 @@ VDEV.pwrite = (fd, ptr, count, offset) => {
|
|||||||
VMEM[i + (offset || 0)] = sys.peek(ptr + i)
|
VMEM[i + (offset || 0)] = sys.peek(ptr + i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VDEV.bwrite = (fd, bytes) {
|
VDEV.bwrite = (fd, bytes) => {
|
||||||
if (bytes.length == VMEM.length && bytes instanceof Int8Array) {
|
if (bytes.length == VMEM.length && bytes instanceof Int8Array) {
|
||||||
VMEM = bytes.slice()
|
VMEM = bytes.slice()
|
||||||
}
|
}
|
||||||
@@ -837,7 +837,7 @@ _TVDOS.DRV.FS.DEVPT.pwrite = (fd, ptr, count, offset) => {
|
|||||||
sys.poke(mem - i, sys.peek(ptr + i))
|
sys.poke(mem - i, sys.peek(ptr + i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_TVDOS.DRV.FS.DEVPT.bwrite = (fd, bytes) {
|
_TVDOS.DRV.FS.DEVPT.bwrite = (fd, bytes) => {
|
||||||
let mem = graphics.getGpuMemBase()
|
let mem = graphics.getGpuMemBase()
|
||||||
for (let i = 0; i < bytes.length; i++) {
|
for (let i = 0; i < bytes.length; i++) {
|
||||||
sys.poke(mem - i, bytes[i])
|
sys.poke(mem - i, bytes[i])
|
||||||
@@ -1386,6 +1386,24 @@ print = function(str) {
|
|||||||
Object.freeze(unicode);
|
Object.freeze(unicode);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// patch con to use VTs
|
||||||
|
con.move = function(y, x) {
|
||||||
|
let activeVT = _TVDOS.ACTIVE_VT || 0 // 0 is physical terminal
|
||||||
|
let vt = _TVDOS.VT_CONTEXTS[activeVT]
|
||||||
|
|
||||||
|
vt.setCursorYX(y|0, x|0)
|
||||||
|
};
|
||||||
|
|
||||||
|
con.getyx = function() {
|
||||||
|
let activeVT = _TVDOS.ACTIVE_VT || 0 // 0 is physical terminal
|
||||||
|
let vt = _TVDOS.VT_CONTEXTS[activeVT]
|
||||||
|
|
||||||
|
return vt.getCursorYX()
|
||||||
|
};
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
let checkTerm = `if (sys.peek(-49)&1) throw new InterruptedException();`
|
let checkTerm = `if (sys.peek(-49)&1) throw new InterruptedException();`
|
||||||
let injectIntChk = (s, n) => {
|
let injectIntChk = (s, n) => {
|
||||||
// primitive way of injecting a code; will replace a JS string that matches the regex...
|
// primitive way of injecting a code; will replace a JS string that matches the regex...
|
||||||
|
|||||||
@@ -456,11 +456,7 @@ con.move = function(y, x) {
|
|||||||
//print("\x1B["+(y|0)+";"+(x|0)+"H");
|
//print("\x1B["+(y|0)+";"+(x|0)+"H");
|
||||||
// NOT using ANSI escape sequence as it conflicts with some multilingual drive which redefines PRINT function
|
// 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
|
// 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) {
|
con.addch = function(c) {
|
||||||
graphics.putSymbol(c|0);
|
graphics.putSymbol(c|0);
|
||||||
@@ -478,10 +474,7 @@ con.getmaxyx = function() {
|
|||||||
return graphics.getTermDimension(); // [rows, cols]
|
return graphics.getTermDimension(); // [rows, cols]
|
||||||
};
|
};
|
||||||
con.getyx = function() {
|
con.getyx = function() {
|
||||||
let activeVT = _TVDOS.ACTIVE_VT || 0 // 0 is physical terminal
|
return graphics.getCursorYX();
|
||||||
let vt = _TVDOS.VT_CONTEXTS[activeVT]
|
|
||||||
|
|
||||||
return vt.getCursorYX()
|
|
||||||
};
|
};
|
||||||
con.curs_up = function() {
|
con.curs_up = function() {
|
||||||
let [y,x] = con.getyx();
|
let [y,x] = con.getyx();
|
||||||
@@ -551,7 +544,6 @@ con.poll_keys = function() {
|
|||||||
sys.poke(-40, 1);
|
sys.poke(-40, 1);
|
||||||
return [-41,-42,-43,-44,-45,-46,-47,-48].map(it => sys.peek(it));
|
return [-41,-42,-43,-44,-45,-46,-47,-48].map(it => sys.peek(it));
|
||||||
};
|
};
|
||||||
Object.freeze(con);
|
|
||||||
// some utilities functions
|
// some utilities functions
|
||||||
|
|
||||||
// TypedArray re-implementation
|
// TypedArray re-implementation
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ package net.torvald.tsvm
|
|||||||
import net.torvald.UnsafeHelper
|
import net.torvald.UnsafeHelper
|
||||||
import net.torvald.UnsafePtr
|
import net.torvald.UnsafePtr
|
||||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.toHex
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.toHex
|
||||||
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.toUint
|
||||||
import net.torvald.tsvm.peripheral.*
|
import net.torvald.tsvm.peripheral.*
|
||||||
import org.graalvm.polyglot.Context
|
import org.graalvm.polyglot.Context
|
||||||
|
import org.graalvm.polyglot.Value
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
@@ -83,8 +85,9 @@ class VM(
|
|||||||
|
|
||||||
// VT tracking of the VM
|
// VT tracking of the VM
|
||||||
private var currentVTIndex = 0 // default to physical terminal
|
private var currentVTIndex = 0 // default to physical terminal
|
||||||
private val vtOutputStream = mutableMapOf<Int, OutputStream>()
|
private val vtOutputStreams = mutableMapOf<Int, OutputStream>()
|
||||||
private val vtInputStream = mutableMapOf<Int, InputStream>()
|
private val vtInputStreams = mutableMapOf<Int, InputStream>()
|
||||||
|
private val vtTerminals = mutableMapOf<Int, VTTerminalAdapter>()
|
||||||
|
|
||||||
fun getCurrentVT(): Int {
|
fun getCurrentVT(): Int {
|
||||||
// try to read from JS context
|
// try to read from JS context
|
||||||
@@ -110,6 +113,196 @@ class VM(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getVTTerminal(vtIndex: Int, buffer: Value): VTTerminalAdapter {
|
||||||
|
return vtTerminals.getOrPut(vtIndex) {
|
||||||
|
VTTerminalAdapter(vtIndex, buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getVTOutputStream(vtIndex: Int): OutputStream {
|
||||||
|
return vtOutputStreams.getOrPut(vtIndex) {
|
||||||
|
if (vtIndex == 0) {
|
||||||
|
// VT0 is physical terminal - use existing terminal
|
||||||
|
getPrintStream()
|
||||||
|
} else {
|
||||||
|
// Create virtual terminal output stream
|
||||||
|
createVTOutputStream(vtIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createVTOutputStream(vtIndex: Int): OutputStream {
|
||||||
|
return object : OutputStream() {
|
||||||
|
override fun write(b: Int) {
|
||||||
|
// Write to virtual terminal buffer
|
||||||
|
writeToVTBuffer(vtIndex, byteArrayOf(b.toByte()))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun write(b: ByteArray, off: Int, len: Int) {
|
||||||
|
// Write to virtual terminal buffer
|
||||||
|
writeToVTBuffer(vtIndex, b.sliceArray(off until off + len))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private val rawCursorPosLo = 252030L
|
||||||
|
private val rawCursorPosHi = rawCursorPosLo + 1
|
||||||
|
private val ptrTxtFore = rawCursorPosHi + 1
|
||||||
|
private val ptrTxtBack = ptrTxtFore + 2560
|
||||||
|
private val ptrTxt = ptrTxtBack + 2560
|
||||||
|
|
||||||
|
private fun writeToVTBuffer(vtIndex: Int, textToWrite: ByteArray) {
|
||||||
|
try {
|
||||||
|
// Access the JavaScript VT device driver
|
||||||
|
val context = getCurrentJSContext()
|
||||||
|
|
||||||
|
val VMEM: Value = context.eval("js", "return _TVDOS.VT_CONTEXTS[$vtIndex].buffer")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
val rawCursorPos = VMEM.getArrayElement(rawCursorPosLo).asByte().toUint() or
|
||||||
|
VMEM.getArrayElement(rawCursorPosHi).asByte().toUint().shl(8) // Cursor position in: (y*80 + x)
|
||||||
|
val printOff = rawCursorPos
|
||||||
|
|
||||||
|
// mimic the behaviour of the GraphicsAdapter.getPrintStream.write(ByteArray)
|
||||||
|
this.isIdle.set(true)
|
||||||
|
Objects.checkFromIndexSize(printOff, textToWrite.size, textToWrite.size)
|
||||||
|
|
||||||
|
for (i in 0 until textToWrite.size) {
|
||||||
|
vtWriteOut(VMEM, textToWrite[i])
|
||||||
|
}
|
||||||
|
this.isIdle.set(false)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
System.err.println("Failed to write to VT$vtIndex: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun vtWriteOut(VMEM: Value, char: Byte) {
|
||||||
|
val terminal = getVTTerminal(getCurrentVT(), VMEM)
|
||||||
|
terminal.writeOut(char) // calls GlassTty.writeOut() which handles everything
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class VTTerminalAdapter(private val vtIndex: Int, private val VMEM: Value) : StandardTty(32, 80) {
|
||||||
|
|
||||||
|
private fun toTtyTextOffset(x: Int, y: Int): Int {
|
||||||
|
return TEXT_COLS * y + x
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun putChar(x: Int, y: Int, text: Byte, foreColour: Byte, backColour: Byte) {
|
||||||
|
val textOff = toTtyTextOffset(x, y)
|
||||||
|
VMEM.setArrayElement(ptrTxtFore + textOff, foreColour)
|
||||||
|
VMEM.setArrayElement(ptrTxtBack + textOff, backColour)
|
||||||
|
VMEM.setArrayElement(ptrTxt + textOff, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun eraseInDisp(arg: Int) {
|
||||||
|
when (arg) {
|
||||||
|
2 -> {
|
||||||
|
val foreBits = ttyFore or ttyFore.shl(8) or ttyFore.shl(16) or ttyFore.shl(24)
|
||||||
|
val backBits = ttyBack or ttyBack.shl(8) or ttyBack.shl(16) or ttyBack.shl(24)
|
||||||
|
for (i in 0 until TEXT_COLS * TEXT_ROWS step 4) {
|
||||||
|
VMEM.setArrayElement(ptrTxtFore + 1, foreBits)
|
||||||
|
VMEM.setArrayElement(ptrTxtBack + 1, backBits)
|
||||||
|
VMEM.setArrayElement(ptrTxt + 1, 0)
|
||||||
|
}
|
||||||
|
VMEM.setArrayElement(rawCursorPosLo, 0)
|
||||||
|
VMEM.setArrayElement(rawCursorPosHi, 0)
|
||||||
|
}
|
||||||
|
else -> TODO()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun eraseInLine(arg: Int) {
|
||||||
|
when (arg) {
|
||||||
|
else -> TODO()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun scrollUp(arg: Int) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun scrollDown(arg: Int) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPrintStream(): OutputStream {
|
||||||
|
TODO("how???")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getErrorStream(): OutputStream {
|
||||||
|
TODO("how???")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getInputStream(): InputStream {
|
||||||
|
TODO("how???")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun putKey(key: Int) {
|
||||||
|
// VT has no keyboard attached
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun takeKey(): Int {
|
||||||
|
// VT has no keyboard attached
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun peek(addr: Long): Byte? {
|
||||||
|
if (addr < 0) return null
|
||||||
|
return VMEM.getArrayElement(addr % 524288).asByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun poke(addr: Long, byte: Byte) {
|
||||||
|
if (addr < 0) return
|
||||||
|
VMEM.setArrayElement(addr % 524288, byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mmio_read(addr: Long): Byte? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mmio_write(addr: Long, byte: Byte) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getVM(): VM {
|
||||||
|
return this@VM
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getCursorPos(): Pair<Int, Int> {
|
||||||
|
val rawPos = VMEM.getArrayElement(rawCursorPosLo).asByte().toUint() or
|
||||||
|
VMEM.getArrayElement(rawCursorPosHi).asByte().toUint().shl(8)
|
||||||
|
return (rawPos % 80) to (rawPos / 80)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setCursorPos(x: Int, y: Int) {
|
||||||
|
val rawPos = (y * 80 + x).coerceIn(0, 2559)
|
||||||
|
VMEM.setArrayElement(rawCursorPosLo, (rawPos and 0xFF).toByte())
|
||||||
|
VMEM.setArrayElement(rawCursorPosHi, (rawPos shr 8).toByte())
|
||||||
|
}
|
||||||
|
|
||||||
|
override var rawCursorPos: Int
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
|
set(value) {}
|
||||||
|
override var blinkCursor: Boolean
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
|
set(value) {}
|
||||||
|
override var ttyFore: Int
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
|
set(value) {}
|
||||||
|
override var ttyBack: Int
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
|
set(value) {}
|
||||||
|
override var ttyRawMode: Boolean
|
||||||
|
get() = TODO("Not yet implemented")
|
||||||
|
set(value) {}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class ReferenceLikeLCD(assetsRoot: String, vm: VM) : GraphicsAdapter(assetsRoot,
|
|||||||
* NOTE: if TTY size is greater than 80*32, SEGFAULT will occur because text buffer is fixed in size
|
* NOTE: if TTY size is greater than 80*32, SEGFAULT will occur because text buffer is fixed in size
|
||||||
*/
|
*/
|
||||||
open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val config: AdapterConfig, val sgr: SuperGraphicsAddonConfig = SuperGraphicsAddonConfig()) :
|
open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val config: AdapterConfig, val sgr: SuperGraphicsAddonConfig = SuperGraphicsAddonConfig()) :
|
||||||
GlassTty(config.textRows, config.textCols) {
|
StandardTty(config.textRows, config.textCols) {
|
||||||
|
|
||||||
override val typestring = VM.PERITYPE_GPU_AND_TERM
|
override val typestring = VM.PERITYPE_GPU_AND_TERM
|
||||||
|
|
||||||
@@ -690,6 +690,11 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun resetTtyStatus() {
|
||||||
|
ttyFore = TTY_FORE_DEFAULT
|
||||||
|
ttyBack = TTY_BACK_DEFAULT
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mode 0-Low, 1-High
|
* @param mode 0-Low, 1-High
|
||||||
*/
|
*/
|
||||||
@@ -705,86 +710,6 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun resetTtyStatus() {
|
|
||||||
ttyFore = TTY_FORE_DEFAULT
|
|
||||||
ttyBack = TTY_BACK_DEFAULT
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun putChar(x: Int, y: Int, text: Byte, foreColour: Byte, backColour: Byte) {
|
|
||||||
val textOff = toTtyTextOffset(x, y)
|
|
||||||
textArea[memTextForeOffset + textOff] = foreColour
|
|
||||||
textArea[memTextBackOffset + textOff] = backColour
|
|
||||||
textArea[memTextOffset + textOff] = text
|
|
||||||
applyDelay()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun emitChar(code: Int) {
|
|
||||||
val (x, y) = getCursorPos()
|
|
||||||
putChar(x, y, code.toByte())
|
|
||||||
setCursorPos(x + 1, y)
|
|
||||||
}
|
|
||||||
override fun cursorUp(arg: Int) {
|
|
||||||
val (x, y) = getCursorPos()
|
|
||||||
setCursorPos(x, y - arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun cursorDown(arg: Int) {
|
|
||||||
val (x, y) = getCursorPos()
|
|
||||||
val newy = y + arg
|
|
||||||
setCursorPos(x, if (newy >= TEXT_ROWS) TEXT_ROWS - 1 else newy)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun cursorFwd(arg: Int) {
|
|
||||||
val (x, y) = getCursorPos()
|
|
||||||
setCursorPos(x + arg, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun cursorBack(arg: Int) {
|
|
||||||
val (x, y) = getCursorPos()
|
|
||||||
setCursorPos(x - arg, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun cursorNextLine(arg: Int) {
|
|
||||||
val (_, y) = getCursorPos()
|
|
||||||
val newy = y + arg
|
|
||||||
setCursorPos(0, if (newy >= TEXT_ROWS) TEXT_ROWS - 1 else newy)
|
|
||||||
if (newy >= TEXT_ROWS) {
|
|
||||||
scrollUp(newy - TEXT_ROWS + 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun cursorPrevLine(arg: Int) {
|
|
||||||
val (_, y) = getCursorPos()
|
|
||||||
setCursorPos(0, y - arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun cursorX(arg: Int) {
|
|
||||||
val (_, y) = getCursorPos()
|
|
||||||
setCursorPos(arg, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun eraseInDisp(arg: Int) {
|
|
||||||
when (arg) {
|
|
||||||
2 -> {
|
|
||||||
val foreBits = ttyFore or ttyFore.shl(8) or ttyFore.shl(16) or ttyFore.shl(24)
|
|
||||||
val backBits = ttyBack or ttyBack.shl(8) or ttyBack.shl(16) or ttyBack.shl(24)
|
|
||||||
for (i in 0 until TEXT_COLS * TEXT_ROWS step 4) {
|
|
||||||
textArea.setIntFree(memTextForeOffset + i, foreBits)
|
|
||||||
textArea.setIntFree(memTextBackOffset + i, backBits)
|
|
||||||
textArea.setIntFree(memTextOffset + i, 0)
|
|
||||||
}
|
|
||||||
textArea.setShortFree(memTextCursorPosOffset, 0)
|
|
||||||
}
|
|
||||||
else -> TODO()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun eraseInLine(arg: Int) {
|
|
||||||
when (arg) {
|
|
||||||
else -> TODO()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** New lines are added at the bottom */
|
/** New lines are added at the bottom */
|
||||||
override fun scrollUp(arg: Int) {
|
override fun scrollUp(arg: Int) {
|
||||||
val displacement = arg.toLong() * TEXT_COLS
|
val displacement = arg.toLong() * TEXT_COLS
|
||||||
@@ -835,92 +760,34 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
override fun eraseInDisp(arg: Int) {
|
||||||
Color table for default palette
|
|
||||||
|
|
||||||
Black 240
|
|
||||||
Red 211
|
|
||||||
Green 61
|
|
||||||
Yellow 230
|
|
||||||
Blue 49
|
|
||||||
Magenta 219
|
|
||||||
Cyan 114
|
|
||||||
White 254
|
|
||||||
*/
|
|
||||||
private val sgrDefault8ColPal = intArrayOf(240,211,61,230,49,219,114,254)
|
|
||||||
|
|
||||||
override fun sgrOneArg(arg: Int) {
|
|
||||||
|
|
||||||
if (arg in 30..37) {
|
|
||||||
ttyFore = sgrDefault8ColPal[arg - 30]
|
|
||||||
}
|
|
||||||
else if (arg in 40..47) {
|
|
||||||
ttyBack = sgrDefault8ColPal[arg - 40]
|
|
||||||
}
|
|
||||||
else if (arg == 7) {
|
|
||||||
val t = ttyFore
|
|
||||||
ttyFore = ttyBack
|
|
||||||
ttyBack = t
|
|
||||||
}
|
|
||||||
else if (arg == 0) {
|
|
||||||
ttyFore = TTY_FORE_DEFAULT
|
|
||||||
ttyBack = TTY_BACK_DEFAULT
|
|
||||||
blinkCursor = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun sgrTwoArg(arg1: Int, arg2: Int) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun sgrThreeArg(arg1: Int, arg2: Int, arg3: Int) {
|
|
||||||
if (arg1 == 38 && arg2 == 5) {
|
|
||||||
ttyFore = arg3
|
|
||||||
}
|
|
||||||
else if (arg1 == 48 && arg2 == 5) {
|
|
||||||
ttyBack = arg3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun privateSeqH(arg: Int) {
|
|
||||||
when (arg) {
|
when (arg) {
|
||||||
25 -> blinkCursor = true
|
2 -> {
|
||||||
|
val foreBits = ttyFore or ttyFore.shl(8) or ttyFore.shl(16) or ttyFore.shl(24)
|
||||||
|
val backBits = ttyBack or ttyBack.shl(8) or ttyBack.shl(16) or ttyBack.shl(24)
|
||||||
|
for (i in 0 until TEXT_COLS * TEXT_ROWS step 4) {
|
||||||
|
textArea.setIntFree(memTextForeOffset + i, foreBits)
|
||||||
|
textArea.setIntFree(memTextBackOffset + i, backBits)
|
||||||
|
textArea.setIntFree(memTextOffset + i, 0)
|
||||||
|
}
|
||||||
|
textArea.setShortFree(memTextCursorPosOffset, 0)
|
||||||
|
}
|
||||||
|
else -> TODO()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun privateSeqL(arg: Int) {
|
override fun eraseInLine(arg: Int) {
|
||||||
when (arg) {
|
when (arg) {
|
||||||
25 -> blinkCursor = false
|
else -> TODO()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The values are one-based
|
override fun putChar(x: Int, y: Int, text: Byte, foreColour: Byte, backColour: Byte) {
|
||||||
* @param arg1 y-position (row)
|
val textOff = toTtyTextOffset(x, y)
|
||||||
* @param arg2 x-position (column) */
|
textArea[memTextForeOffset + textOff] = foreColour
|
||||||
override fun cursorXY(arg1: Int, arg2: Int) {
|
textArea[memTextBackOffset + textOff] = backColour
|
||||||
setCursorPos(arg2 - 1, arg1 - 1)
|
textArea[memTextOffset + textOff] = text
|
||||||
}
|
applyDelay()
|
||||||
|
|
||||||
override fun ringBell() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun insertTab() {
|
|
||||||
val (x, y) = getCursorPos()
|
|
||||||
setCursorPos((x / TAB_SIZE + 1) * TAB_SIZE, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun crlf() {
|
|
||||||
val (_, y) = getCursorPos()
|
|
||||||
val newy = y + 1 //+ halfrowMode.toInt()
|
|
||||||
setCursorPos(0, if (newy >= TEXT_ROWS) TEXT_ROWS - 1 else newy)
|
|
||||||
if (newy >= TEXT_ROWS) scrollUp(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun backspace() {
|
|
||||||
val (x, y) = getCursorPos()
|
|
||||||
setCursorPos(x - 1, y)
|
|
||||||
putChar(x - 1, y, 0x20.toByte())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2341,3 +2208,143 @@ internal fun SpriteBatch.inUse(action: () -> Unit) {
|
|||||||
action()
|
action()
|
||||||
this.end()
|
this.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class StandardTty(rows: Int, cols: Int) : GlassTty(rows, cols) {
|
||||||
|
|
||||||
|
override fun resetTtyStatus() {
|
||||||
|
ttyFore = 253
|
||||||
|
ttyBack = 255
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun emitChar(code: Int) {
|
||||||
|
val (x, y) = getCursorPos()
|
||||||
|
putChar(x, y, code.toByte())
|
||||||
|
setCursorPos(x + 1, y)
|
||||||
|
}
|
||||||
|
override fun cursorUp(arg: Int) {
|
||||||
|
val (x, y) = getCursorPos()
|
||||||
|
setCursorPos(x, y - arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cursorDown(arg: Int) {
|
||||||
|
val (x, y) = getCursorPos()
|
||||||
|
val newy = y + arg
|
||||||
|
setCursorPos(x, if (newy >= TEXT_ROWS) TEXT_ROWS - 1 else newy)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cursorFwd(arg: Int) {
|
||||||
|
val (x, y) = getCursorPos()
|
||||||
|
setCursorPos(x + arg, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cursorBack(arg: Int) {
|
||||||
|
val (x, y) = getCursorPos()
|
||||||
|
setCursorPos(x - arg, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cursorNextLine(arg: Int) {
|
||||||
|
val (_, y) = getCursorPos()
|
||||||
|
val newy = y + arg
|
||||||
|
setCursorPos(0, if (newy >= TEXT_ROWS) TEXT_ROWS - 1 else newy)
|
||||||
|
if (newy >= TEXT_ROWS) {
|
||||||
|
scrollUp(newy - TEXT_ROWS + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cursorPrevLine(arg: Int) {
|
||||||
|
val (_, y) = getCursorPos()
|
||||||
|
setCursorPos(0, y - arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cursorX(arg: Int) {
|
||||||
|
val (_, y) = getCursorPos()
|
||||||
|
setCursorPos(arg, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Color table for default palette
|
||||||
|
|
||||||
|
Black 240
|
||||||
|
Red 211
|
||||||
|
Green 61
|
||||||
|
Yellow 230
|
||||||
|
Blue 49
|
||||||
|
Magenta 219
|
||||||
|
Cyan 114
|
||||||
|
White 254
|
||||||
|
*/
|
||||||
|
private val sgrDefault8ColPal = intArrayOf(240,211,61,230,49,219,114,254)
|
||||||
|
|
||||||
|
override fun sgrOneArg(arg: Int) {
|
||||||
|
if (arg in 30..37) {
|
||||||
|
ttyFore = sgrDefault8ColPal[arg - 30]
|
||||||
|
}
|
||||||
|
else if (arg in 40..47) {
|
||||||
|
ttyBack = sgrDefault8ColPal[arg - 40]
|
||||||
|
}
|
||||||
|
else if (arg == 7) {
|
||||||
|
val t = ttyFore
|
||||||
|
ttyFore = ttyBack
|
||||||
|
ttyBack = t
|
||||||
|
}
|
||||||
|
else if (arg == 0) {
|
||||||
|
ttyFore = 253
|
||||||
|
ttyBack = 255
|
||||||
|
blinkCursor = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun sgrTwoArg(arg1: Int, arg2: Int) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun sgrThreeArg(arg1: Int, arg2: Int, arg3: Int) {
|
||||||
|
if (arg1 == 38 && arg2 == 5) {
|
||||||
|
ttyFore = arg3
|
||||||
|
}
|
||||||
|
else if (arg1 == 48 && arg2 == 5) {
|
||||||
|
ttyBack = arg3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun privateSeqH(arg: Int) {
|
||||||
|
when (arg) {
|
||||||
|
25 -> blinkCursor = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun privateSeqL(arg: Int) {
|
||||||
|
when (arg) {
|
||||||
|
25 -> blinkCursor = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The values are one-based
|
||||||
|
* @param arg1 y-position (row)
|
||||||
|
* @param arg2 x-position (column) */
|
||||||
|
override fun cursorXY(arg1: Int, arg2: Int) {
|
||||||
|
setCursorPos(arg2 - 1, arg1 - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ringBell() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun insertTab() {
|
||||||
|
val (x, y) = getCursorPos()
|
||||||
|
setCursorPos((x / 8 + 1) * 8, y) // tab size is 8
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun crlf() {
|
||||||
|
val (_, y) = getCursorPos()
|
||||||
|
val newy = y + 1 //+ halfrowMode.toInt()
|
||||||
|
setCursorPos(0, if (newy >= TEXT_ROWS) TEXT_ROWS - 1 else newy)
|
||||||
|
if (newy >= TEXT_ROWS) scrollUp(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun backspace() {
|
||||||
|
val (x, y) = getCursorPos()
|
||||||
|
setCursorPos(x - 1, y)
|
||||||
|
putChar(x - 1, y, 0x20.toByte())
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user