fix: mmio-based readKey() having delayed event because of race condition

This commit is contained in:
minjaesong
2025-12-20 11:17:50 +09:00
parent 64026be133
commit 5d5576c077
2 changed files with 16 additions and 18 deletions

View File

@@ -208,25 +208,19 @@ class VMJSR223Delegate(private val vm: VM) {
* ^A-^Z: 1 through 26 * ^A-^Z: 1 through 26
*/ */
fun readKey(): Int { fun readKey(): Int {
val inputStream = vm.getInputStream() // MMIO-based implementation that can be replicated by JS via MMIO read/writes
var key: Int = inputStream.read() vm.getIO().let {
inputStream.close() it.mmio_write(38, 1) // Set keyboardInputRequested = true (also clears buffer)
return key
// impl that doesn't rely on InputStream
// fixme it's causing event-wise delay
/*vm.getIO().let {
it.mmio_write(38, 1)
vm.isIdle.set(true) vm.isIdle.set(true)
while (it.mmio_read(49L) == 0.toByte()) { while (it.mmio_read(49L) == 0.toByte()) { // Wait for keyPushed flag
Thread.sleep(6L) Thread.sleep(6L)
} }
vm.isIdle.set(false) vm.isIdle.set(false)
it.mmio_write(38, 0) it.mmio_write(38, 0) // Clear keyboardInputRequested
return it.mmio_read(37L)!!.toUint() return it.mmio_read(37L)!!.toUint() // Read and remove key from buffer
}*/ }
} }
/** /**

View File

@@ -99,7 +99,11 @@ class IOSpace(val vm: VM) : PeriBase("io"), InputProcessor {
in 32..33 -> (mouseX.toInt() shr (adi - 32).times(8)).toByte() in 32..33 -> (mouseX.toInt() shr (adi - 32).times(8)).toByte()
in 34..35 -> (mouseY.toInt() shr (adi - 34).times(8)).toByte() in 34..35 -> (mouseY.toInt() shr (adi - 34).times(8)).toByte()
36L -> mouseDown.toInt().toByte() 36L -> mouseDown.toInt().toByte()
37L -> keyboardBuffer.removeTail() ?: -1 37L -> {
val key = keyboardBuffer.removeTail() ?: -1
keyPushed = !keyboardBuffer.isEmpty // Clear flag when buffer becomes empty
key
}
38L -> keyboardInputRequested.toInt().toByte() 38L -> keyboardInputRequested.toInt().toByte()
39L -> rawInputFunctionLatched.toInt().toByte() 39L -> rawInputFunctionLatched.toInt().toByte()
in 40..47 -> keyEventBuffers[adi - 40] in 40..47 -> keyEventBuffers[adi - 40]
@@ -174,6 +178,7 @@ class IOSpace(val vm: VM) : PeriBase("io"), InputProcessor {
keyboardInputRequested = (byte.isNonZero()) keyboardInputRequested = (byte.isNonZero())
if (keyboardInputRequested) { if (keyboardInputRequested) {
keyboardBuffer.clear() keyboardBuffer.clear()
keyPushed = false // Reset flag when buffer is cleared
vm.isIdle.set(true) vm.isIdle.set(true)
} }
else else
@@ -344,14 +349,11 @@ class IOSpace(val vm: VM) : PeriBase("io"), InputProcessor {
override fun keyTyped(p0: Char): Boolean { override fun keyTyped(p0: Char): Boolean {
if (keyboardInputRequested && p0.toInt() > 0) { if (keyboardInputRequested && p0.toInt() > 0) {
//println("[IO] key typed = ${p0.toInt()}") //println("[IO] key typed = ${p0.toInt()}")
keyPushed = true
keyboardBuffer.appendHead(p0.toByte()) keyboardBuffer.appendHead(p0.toByte())
Thread.sleep(6L) keyPushed = true // Set after append; cleared when buffer is emptied via mmio_read(37)
keyPushed = false
return true return true
} }
else { else {
keyPushed = false
return false return false
} }
} }
@@ -389,11 +391,13 @@ class IOSpace(val vm: VM) : PeriBase("io"), InputProcessor {
if (keyboardInputRequested) { if (keyboardInputRequested) {
if (p0 in Input.Keys.A..Input.Keys.Z && (Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT) || Gdx.input.isKeyPressed(Input.Keys.CONTROL_RIGHT))) { if (p0 in Input.Keys.A..Input.Keys.Z && (Gdx.input.isKeyPressed(Input.Keys.CONTROL_LEFT) || Gdx.input.isKeyPressed(Input.Keys.CONTROL_RIGHT))) {
keyboardBuffer.appendHead((p0 - 28).toByte()) keyboardBuffer.appendHead((p0 - 28).toByte())
keyPushed = true
} }
else { else {
specialKeys[p0]?.let { specialKeys[p0]?.let {
//println("[IO] key special = ${it.toUInt()}") //println("[IO] key special = ${it.toUInt()}")
keyboardBuffer.appendHead(it) keyboardBuffer.appendHead(it)
keyPushed = true
} }
} }
return true return true