mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 19:51:51 +09:00
keyboard input to use properly open/closed input stream
This commit is contained in:
@@ -9,6 +9,7 @@ import net.torvald.tsvm.peripheral.PeriBase
|
||||
import org.luaj.vm2.LuaValue
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.io.PrintStream
|
||||
import java.util.*
|
||||
import kotlin.math.ceil
|
||||
import kotlin.random.Random
|
||||
@@ -68,9 +69,14 @@ class VM(
|
||||
|
||||
internal fun getIO(): IOSpace = peripheralTable[0].peripheral as IOSpace
|
||||
|
||||
lateinit var printStream: OutputStream
|
||||
lateinit var errorStream: OutputStream
|
||||
lateinit var inputStream: InputStream
|
||||
//lateinit var printStream: OutputStream
|
||||
//lateinit var errorStream: OutputStream
|
||||
//lateinit var inputStream: InputStream // InputStream should not be a singleton, as it HAS TO open and close the stream.
|
||||
// Printstreams don't need that so they're singleton.
|
||||
|
||||
var getPrintStream: () -> OutputStream = { TODO() }
|
||||
var getErrorStream: () -> OutputStream = { TODO() }
|
||||
var getInputStream: () -> InputStream = { TODO() }
|
||||
|
||||
init {
|
||||
peripheralTable[0] = PeripheralEntry(
|
||||
|
||||
@@ -44,9 +44,9 @@ class VMGUI(val appConfig: LwjglApplicationConfiguration) : ApplicationAdapter()
|
||||
batch.projectionMatrix = camera.combined
|
||||
Gdx.gl20.glViewport(0, 0, appConfig.width, appConfig.height)
|
||||
|
||||
vm.printStream = gpu.getPrintStream()
|
||||
vm.errorStream = gpu.getErrorStream()
|
||||
vm.inputStream = gpu.getInputStream()
|
||||
vm.getPrintStream = { gpu.getPrintStream() }
|
||||
vm.getErrorStream = { gpu.getErrorStream() }
|
||||
vm.getInputStream = { gpu.getInputStream() }
|
||||
|
||||
// TEST PRG
|
||||
vmRunner = VMRunnerFactory(vm, "js")
|
||||
|
||||
@@ -15,24 +15,25 @@ class VMJSR223Delegate(val vm: VM) {
|
||||
|
||||
fun print(s: String) {
|
||||
//print("[Nashorn] $s")
|
||||
vm.printStream.write(s.toByteArray())
|
||||
vm.getPrintStream().write(s.toByteArray())
|
||||
}
|
||||
fun println(s: String) {
|
||||
//println("[Nashorn] $s")
|
||||
vm.printStream.write((s + '\n').toByteArray())
|
||||
vm.getPrintStream().write((s + '\n').toByteArray())
|
||||
}
|
||||
fun println() = print('\n')
|
||||
|
||||
fun readKey() = vm.inputStream.read()
|
||||
//fun readKey() = vm.inputStream.read()
|
||||
|
||||
/**
|
||||
* Read series of key inputs until Enter/Return key is pressed
|
||||
*/
|
||||
fun read(): String {
|
||||
val inputStream = vm.getInputStream()
|
||||
val sb = StringBuilder()
|
||||
var key: Int
|
||||
do {
|
||||
key = readKey()
|
||||
key = inputStream.read()
|
||||
|
||||
if ((key == 8 && sb.isNotEmpty()) || key in 0x20..0x7E) {
|
||||
this.print("${key.toChar()}")
|
||||
@@ -45,6 +46,7 @@ class VMJSR223Delegate(val vm: VM) {
|
||||
} while (key != 13 && key != 10)
|
||||
this.println()
|
||||
|
||||
inputStream.close()
|
||||
return sb.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,7 +368,7 @@ class GraphicsAdapter(val vm: VM, val lcdMode: Boolean = false) : GlassTty(Compa
|
||||
|
||||
private lateinit var PRINTSTREAM_INSTANCE: OutputStream
|
||||
private lateinit var ERRORSTREAM_INSTANCE: OutputStream
|
||||
private lateinit var INPUTSTREAM_INSTANCE: InputStream
|
||||
//private lateinit var INPUTSTREAM_INSTANCE: InputStream
|
||||
|
||||
override fun getPrintStream(): OutputStream {
|
||||
try {
|
||||
@@ -412,12 +412,16 @@ class GraphicsAdapter(val vm: VM, val lcdMode: Boolean = false) : GlassTty(Compa
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* As getting the keyboard input now requires proper open and closing, the inputstream cannot be a singleton, unlike
|
||||
* the printstream.
|
||||
*/
|
||||
override fun getInputStream(): InputStream {
|
||||
try {
|
||||
return INPUTSTREAM_INSTANCE
|
||||
return object : InputStream() {
|
||||
|
||||
init {
|
||||
vm.getIO().mmio_write(38L, 1)
|
||||
}
|
||||
catch (e: UninitializedPropertyAccessException) {
|
||||
INPUTSTREAM_INSTANCE = object : InputStream() {
|
||||
|
||||
override fun read(): Int {
|
||||
var key: Byte
|
||||
@@ -430,9 +434,10 @@ class GraphicsAdapter(val vm: VM, val lcdMode: Boolean = false) : GlassTty(Compa
|
||||
//println("[stdin] key = $key")
|
||||
return key.toInt().and(255)
|
||||
}
|
||||
}
|
||||
|
||||
return INPUTSTREAM_INSTANCE
|
||||
override fun close() {
|
||||
vm.getIO().mmio_write(38L, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor {
|
||||
private var mouseY: Short = 0
|
||||
private var mouseDown = false
|
||||
|
||||
private var keyboardInputRequested = false
|
||||
|
||||
override fun peek(addr: Long): Byte? {
|
||||
return mmio_read(addr)
|
||||
}
|
||||
@@ -37,7 +39,8 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor {
|
||||
in 32..33 -> (mouseX.toInt() shr (adi - 32).times(8)).toByte()
|
||||
in 34..35 -> (mouseY.toInt() shr (adi - 34).times(8)).toByte()
|
||||
36L -> if (mouseDown) 1 else 0
|
||||
37L -> keyboardBuffer.removeHead() ?: -1
|
||||
37L -> keyboardBuffer.removeTail() ?: -1
|
||||
38L -> if (keyboardInputRequested) 1 else 0
|
||||
else -> -1
|
||||
}
|
||||
}
|
||||
@@ -46,6 +49,11 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor {
|
||||
val adi = addr.toInt()
|
||||
val bi = byte.toInt().and(255)
|
||||
when (addr) {
|
||||
37L -> keyboardBuffer.appendHead(byte)
|
||||
38L -> {
|
||||
keyboardInputRequested = (byte != 0.toByte())
|
||||
if (keyboardInputRequested) keyboardBuffer.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,12 +75,14 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor {
|
||||
}
|
||||
|
||||
override fun keyTyped(p0: Char): Boolean {
|
||||
try {
|
||||
keyboardBuffer.appendTail(p0.toByte())
|
||||
}
|
||||
catch (e: StackOverflowError) { /* if stack overflow, simply stop reading more keys */ }
|
||||
if (keyboardInputRequested) {
|
||||
keyboardBuffer.appendHead(p0.toByte())
|
||||
return true
|
||||
}
|
||||
else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
override fun scrolled(p0: Int): Boolean {
|
||||
return false
|
||||
|
||||
@@ -84,6 +84,7 @@ class CircularArray<T>(val size: Int, val overwriteOnOverflow: Boolean): Iterabl
|
||||
// even if overflowing is enabled, appending at tail causes head element to be altered, therefore such action
|
||||
// must be blocked by throwing overflow error
|
||||
|
||||
// if you think this behaviour is wrong, you're confusing appendHead() with appendTail(). Use appendHead() and removeTail()
|
||||
if (overflow) {
|
||||
throw StackOverflowError()
|
||||
}
|
||||
|
||||
@@ -43,13 +43,16 @@ Endianness: little
|
||||
|
||||
MMIO
|
||||
|
||||
0..31: Raw Keyboard Buffer read. Won't shift the key buffer
|
||||
32..33: Mouse X pos
|
||||
34..35: Mouse Y pos
|
||||
36: Mouse down? (1 for TRUE, 0 for FALSE)
|
||||
37: Read/Write single key input. Key buffer will be shifted. Manual writing is
|
||||
0..31 RO: Raw Keyboard Buffer read. Won't shift the key buffer
|
||||
32..33 RO: Mouse X pos
|
||||
34..35 RO: Mouse Y pos
|
||||
36 RO: Mouse down? (1 for TRUE, 0 for FALSE)
|
||||
37 RW: Read/Write single key input. Key buffer will be shifted. Manual writing is
|
||||
usually unnecessary as such action must be automatically managed via LibGDX
|
||||
input processing.
|
||||
38 RW: Request keyboard input be read. Write nonzero value to enable, write zero to
|
||||
close it. Keyboard buffer will be cleared whenever request is received, so
|
||||
MAKE SURE YOU REQUEST THE KEY INPUT ONLY ONCE!
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user