tty state machine wip

This commit is contained in:
minjaesong
2020-05-10 19:13:35 +09:00
parent cbcd1ac7af
commit c1f5944643
3 changed files with 205 additions and 49 deletions

View File

@@ -33,17 +33,43 @@ class GraphicsJSR223Delegate(val vm: VM) {
}
}
private fun GraphicsAdapter._loadbulk(fromAddr: Int, toAddr: Int, length: Int) {
if (toAddr < 250880) {
UnsafeHelper.memcpy(
vm.usermem.ptr + fromAddr,
(this.framebuffer.pixels as DirectBuffer).address() + toAddr,
length.toLong()
)
}
else if (toAddr < 250972) {
fun storeBulk(fromAddr: Int, toAddr: Int, length: Int) {
getFirstGPU()?.let {
it._storebulk(fromAddr, toAddr, length)
}
}
private fun GraphicsAdapter._loadbulk(fromAddr: Int, toAddr: Int, length: Int) {
UnsafeHelper.memcpy(
vm.usermem.ptr + fromAddr,
(this.framebuffer.pixels as DirectBuffer).address() + toAddr,
length.toLong()
)
}
private fun GraphicsAdapter._storebulk(fromAddr: Int, toAddr: Int, length: Int) {
UnsafeHelper.memcpy(
(this.framebuffer.pixels as DirectBuffer).address() + fromAddr,
vm.usermem.ptr + toAddr,
length.toLong()
)
}
private fun GraphicsAdapter._loadSprite(spriteNum: Int, ptr: Int) {
UnsafeHelper.memcpy(
vm.usermem.ptr + ptr,
(this.spriteAndTextArea).ptr + (260 * spriteNum) + 4,
256
)
}
private fun GraphicsAdapter._storeSprite(spriteNum: Int, ptr: Int) {
UnsafeHelper.memcpy(
(this.spriteAndTextArea).ptr + (260 * spriteNum) + 4,
vm.usermem.ptr + ptr,
256
)
}
}

View File

@@ -1,6 +1,6 @@
package net.torvald.tsvm.peripheral
import com.badlogic.gdx.utils.Queue
import java.util.*
/**
* Implements standard TTY that can interpret some of the ANSI escape sequences
@@ -19,8 +19,8 @@ abstract class GlassTty(val TEXT_ROWS: Int, val TEXT_COLS: Int) {
abstract fun putChar(x: Int, y: Int, text: Byte, foreColour: Byte = ttyFore.toByte(), backColour: Byte = ttyBack.toByte())
private var ttyMode = Queue<Byte>() // stores escape sequences like: <ESC> [
private var ttyEscState = TTY_ESC_STATE.INITIAL
private val ttyEscArguments = Stack<Int>()
/**
* ONLY accepts a character to either process the escape sequence, or say the input character is allowed to print.
* This function will alter the internal state of the TTY intepreter (aka this very class)
@@ -31,40 +31,164 @@ abstract class GlassTty(val TEXT_ROWS: Int, val TEXT_COLS: Int) {
* @return true if character should be printed as-is
*/
private fun acceptChar(char: Byte): Boolean {
TODO()
if (ESC == char) {
// beginning of the escape sequence
if (ttyMode.isEmpty) {
ttyMode.addLast(char)
}
else {
return true
}
fun reject(): Boolean {
ttyEscState = TTY_ESC_STATE.INITIAL
ttyEscArguments.clear()
return true
}
// Any escape sequences
else if (ttyMode.size >= 1) {
// make a state machine; if the machine should move into accepting state: accept a char, and return false;
// for a rejecting state (sequence not in the transition table): clear the ttyMode, and return false;
// for a terminating state (escape sequence is terminated successfully): run interpretCSI(), and return false.
fun accept(execute: () -> Unit): Boolean {
ttyEscState = TTY_ESC_STATE.INITIAL
execute.invoke()
ttyEscArguments.clear()
return false
}
fun registerNewNumberArg(newnum: Byte, newState: TTY_ESC_STATE) {
ttyEscArguments.push(char.toInt() - 0x30)
ttyEscState = newState
}
fun appendToExistingNumber(newnum: Byte) {
ttyEscArguments.push(ttyEscArguments.pop() * 10 + (newnum.toInt() - 0x30))
}
//TODO()
when (ttyEscState) {
TTY_ESC_STATE.INITIAL -> {
if (char == ESC) {
ttyEscState = TTY_ESC_STATE.ESC
}
else {
return true
}
}
TTY_ESC_STATE.ESC -> {
when (char.toChar()) {
'c' -> return accept { resetTtyStatus() }
'[' -> ttyEscState = TTY_ESC_STATE.CSI
else -> return reject()
}
}
TTY_ESC_STATE.CSI -> {
when (char.toChar()) {
'A' -> return accept { cursorUp() }
'B' -> return accept { cursorDown() }
'C' -> return accept { cursorFwd() }
'D' -> return accept { cursorBack() }
'E' -> return accept { cursorNextLine() }
'F' -> return accept { cursorPrevLine() }
'G' -> return accept { cursorX() }
'J' -> return accept { eraseInDisp() }
'K' -> return accept { eraseInLine() }
'S' -> return accept { scrollUp() }
'T' -> return accept { scrollDown() }
'm' -> return accept { sgrOneArg() }
';' -> {
ttyEscArguments.push(0)
ttyEscState = TTY_ESC_STATE.SEP1
}
in '0'..'9' -> registerNewNumberArg(char, TTY_ESC_STATE.NUM1)
else -> return reject()
}
}
TTY_ESC_STATE.NUM1 -> {
when (char.toChar()) {
'A' -> return accept { cursorUp(ttyEscArguments.pop()) }
'B' -> return accept { cursorDown(ttyEscArguments.pop()) }
'C' -> return accept { cursorFwd(ttyEscArguments.pop()) }
'D' -> return accept { cursorBack(ttyEscArguments.pop()) }
'E' -> return accept { cursorNextLine(ttyEscArguments.pop()) }
'F' -> return accept { cursorPrevLine(ttyEscArguments.pop()) }
'G' -> return accept { cursorX(ttyEscArguments.pop()) }
'J' -> return accept { eraseInDisp(ttyEscArguments.pop()) }
'K' -> return accept { eraseInLine(ttyEscArguments.pop()) }
'S' -> return accept { scrollUp(ttyEscArguments.pop()) }
'T' -> return accept { scrollDown(ttyEscArguments.pop()) }
'm' -> return accept { sgrOneArg(ttyEscArguments.pop()) }
';' -> ttyEscState = TTY_ESC_STATE.SEP1
in '0'..'9' -> appendToExistingNumber(char)
else -> return reject()
}
}
TTY_ESC_STATE.NUM2 -> {
when (char.toChar()) {
in '0'..'9' -> appendToExistingNumber(char)
'H' -> return accept {
val arg2 = ttyEscArguments.pop()
val arg1 = ttyEscArguments.pop()
cursorXY(arg1, arg2)
}
';' -> ttyEscState = TTY_ESC_STATE.SEP2
else -> return reject()
}
}
TTY_ESC_STATE.NUM3 -> {
when (char.toChar()) {
in '0'..'9' -> appendToExistingNumber(char)
'm' -> return accept {
val arg3 = ttyEscArguments.pop()
val arg2 = ttyEscArguments.pop()
val arg1 = ttyEscArguments.pop()
sgrThreeArg(arg1, arg2, arg3)
}
else -> return reject()
}
}
TTY_ESC_STATE.SEP1 -> {
when (char.toChar()) {
in '0'..'9' -> registerNewNumberArg(char, TTY_ESC_STATE.NUM2)
'H' -> return accept {
val arg1 = ttyEscArguments.pop()
cursorXY(arg1, 0)
}
';' -> {
ttyEscArguments.push(0)
ttyEscState = TTY_ESC_STATE.SEP2
}
else -> return reject()
}
}
TTY_ESC_STATE.SEP2 -> {
when (char.toChar()) {
'm' -> return accept {
val arg2 = ttyEscArguments.pop()
val arg1 = ttyEscArguments.pop()
sgrThreeArg(arg1, arg2, 0)
}
in '0'..'9' -> registerNewNumberArg(char, TTY_ESC_STATE.NUM3)
else -> return reject()
}
}
}
return false
}
private fun interpretEscapeSequence() {
TODO()
}
abstract fun resetTtyStatus()
abstract fun cursorUp(arg: Int = 1)
abstract fun cursorDown(arg: Int = 1)
abstract fun cursorFwd(arg: Int = 1)
abstract fun cursorBack(arg: Int = 1)
abstract fun cursorNextLine(arg: Int = 1)
abstract fun cursorPrevLine(arg: Int = 1)
abstract fun cursorX(arg: Int = 1) // aka Cursor Horizintal Absolute
abstract fun eraseInDisp(arg: Int = 0)
abstract fun eraseInLine(arg: Int = 0)
abstract fun scrollUp(arg: Int = 1)
abstract fun scrollDown(arg: Int = 1)
abstract fun sgrOneArg(arg: Int = 0)
abstract fun sgrThreeArg(arg1: Int, arg2: Int, arg3: Int)
abstract fun cursorXY(arg1: Int, arg2: Int)
private val ESC = 0x1B.toByte()
private val LBRACKET = 0x5B.toByte()
private val FORE_DEFAULT = 254
private val BACK_DEFAULT = 255
private enum class TTY_ESC_STATE {
INITIAL, ESC, CSI, NUM1, SEP1, NUM2, SEP2, NUM3
}
}
/*
@@ -82,11 +206,13 @@ digraph G {
CSI -> CursorBack [label="D"]
CSI -> CursorNextLine [label="E"]
CSI -> CursorPrevLine [label="F"]
CSI -> CursorY [label="G"]
CSI -> EraseDisp [label="J"]
CSI -> EraseLine [label="K"]
CSI -> CursorX [label="G"]
CSI -> EraseInDisp [label="J"]
CSI -> EraseInLine [label="K"]
CSI -> ScrollUp [label="S"]
CSI -> ScrollDown [label="T"]
CSI -> SGR [label="m"]
CSI -> separator1 [label="; (zero)"]
numeral -> numeral [label="0..9"]
numeral -> CursorUp [label="A"]
@@ -95,25 +221,29 @@ digraph G {
numeral -> CursorBack [label="D"]
numeral -> CursorNextLine [label="E"]
numeral -> CursorPrevLine [label="F"]
numeral -> CursorY [label="G"]
numeral -> EraseDisp [label="J"]
numeral -> EraseLine [label="K"]
numeral -> CursorX [label="G"]
numeral -> EraseInDisp [label="J"]
numeral -> EraseInLine [label="K"]
numeral -> ScrollUp [label="S"]
numeral -> ScrollDown [label="T"]
numeral -> SGR [label="(any unacceptable char)"]
numeral -> SGR [label="m"]
numeral -> separator1 [label=";"]
separator1 -> numeral2 [label="0..9"]
separator1 -> separator2 [label="; (zero)"]
separator1 -> CursorPos [label="H (zero)"]
numeral2 -> numeral2 [label="0..9"]
numeral2 -> CursorPos [label="H"]
numeral2 -> separator2 [label=";"]
separator2 -> numeral3 [label="0..9"]
numeral3 -> numeral3 [label="0..9"]
numeral3 -> "SGR-Colour" [label="(any unacceptable char)"]
separator2 -> "SGR-Colour" [label="m (zero)"]
numeral3 -> "SGR-Colour" [label="m"]
ESC [shape=Mdiamond]
Reset -> end
@@ -123,9 +253,9 @@ digraph G {
CursorBack -> end
CursorNextLine -> end
CursorPrevLine -> end
CursorY -> end
EraseDisp -> end
EraseLine -> end
CursorX -> end
EraseInDisp -> end
EraseInLine -> end
ScrollUp -> end
ScrollDown -> end
CursorPos -> end

View File

@@ -23,7 +23,7 @@ class GraphicsAdapter(val lcdMode: Boolean = false) : GlassTty(Companion.TEXT_RO
private val chrrom0 = Texture("./FontROM7x14.png")
private val faketex: Texture
private val spriteAndTextArea = UnsafeHelper.allocate(10660L)
internal val spriteAndTextArea = UnsafeHelper.allocate(10660L)
private val unusedArea = ByteArray(92)
private val paletteShader = AppLoader.loadShaderInline(DRAW_SHADER_VERT, if (lcdMode) DRAW_SHADER_FRAG_LCD else DRAW_SHADER_FRAG)