mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 19:51:51 +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)
|
||||
}
|
||||
}
|
||||
VDEV.bwrite = (fd, bytes) {
|
||||
VDEV.bwrite = (fd, bytes) => {
|
||||
if (bytes.length == VMEM.length && bytes instanceof Int8Array) {
|
||||
VMEM = bytes.slice()
|
||||
}
|
||||
@@ -837,7 +837,7 @@ _TVDOS.DRV.FS.DEVPT.pwrite = (fd, ptr, count, offset) => {
|
||||
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()
|
||||
for (let i = 0; i < bytes.length; i++) {
|
||||
sys.poke(mem - i, bytes[i])
|
||||
@@ -1386,6 +1386,24 @@ print = function(str) {
|
||||
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 injectIntChk = (s, n) => {
|
||||
// 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");
|
||||
// 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
|
||||
|
||||
let activeVT = _TVDOS.ACTIVE_VT || 0 // 0 is physical terminal
|
||||
let vt = _TVDOS.VT_CONTEXTS[activeVT]
|
||||
|
||||
vt.setCursorYX(y|0, x|0)
|
||||
graphics.setCursorYX(y|0, x|0);
|
||||
};
|
||||
con.addch = function(c) {
|
||||
graphics.putSymbol(c|0);
|
||||
@@ -478,10 +474,7 @@ con.getmaxyx = function() {
|
||||
return graphics.getTermDimension(); // [rows, cols]
|
||||
};
|
||||
con.getyx = function() {
|
||||
let activeVT = _TVDOS.ACTIVE_VT || 0 // 0 is physical terminal
|
||||
let vt = _TVDOS.VT_CONTEXTS[activeVT]
|
||||
|
||||
return vt.getCursorYX()
|
||||
return graphics.getCursorYX();
|
||||
};
|
||||
con.curs_up = function() {
|
||||
let [y,x] = con.getyx();
|
||||
@@ -551,7 +544,6 @@ con.poll_keys = function() {
|
||||
sys.poke(-40, 1);
|
||||
return [-41,-42,-43,-44,-45,-46,-47,-48].map(it => sys.peek(it));
|
||||
};
|
||||
Object.freeze(con);
|
||||
// some utilities functions
|
||||
|
||||
// TypedArray re-implementation
|
||||
|
||||
@@ -3,8 +3,10 @@ package net.torvald.tsvm
|
||||
import net.torvald.UnsafeHelper
|
||||
import net.torvald.UnsafePtr
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.toHex
|
||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.toUint
|
||||
import net.torvald.tsvm.peripheral.*
|
||||
import org.graalvm.polyglot.Context
|
||||
import org.graalvm.polyglot.Value
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.nio.charset.Charset
|
||||
@@ -83,8 +85,9 @@ class VM(
|
||||
|
||||
// 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>()
|
||||
private val vtOutputStreams = mutableMapOf<Int, OutputStream>()
|
||||
private val vtInputStreams = mutableMapOf<Int, InputStream>()
|
||||
private val vtTerminals = mutableMapOf<Int, VTTerminalAdapter>()
|
||||
|
||||
fun getCurrentVT(): Int {
|
||||
// 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
|
||||
*/
|
||||
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
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
@@ -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 */
|
||||
override fun scrollUp(arg: Int) {
|
||||
val displacement = arg.toLong() * TEXT_COLS
|
||||
@@ -835,92 +760,34 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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) {
|
||||
override fun eraseInDisp(arg: Int) {
|
||||
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) {
|
||||
25 -> blinkCursor = false
|
||||
else -> TODO()
|
||||
}
|
||||
}
|
||||
|
||||
/** 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 / 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())
|
||||
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()
|
||||
}
|
||||
|
||||
|
||||
@@ -2341,3 +2208,143 @@ internal fun SpriteBatch.inUse(action: () -> Unit) {
|
||||
action()
|
||||
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