keyboard input to use properly open/closed input stream

This commit is contained in:
minjaesong
2020-05-15 17:13:56 +09:00
parent e486d8dce4
commit 772354d2d1
7 changed files with 65 additions and 38 deletions

View File

@@ -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(

View File

@@ -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")

View File

@@ -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()
}
}

View File

@@ -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)
}
}
}

View File

@@ -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

View File

@@ -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()
}

View File

@@ -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!
--------------------------------------------------------------------------------