more input reading|js console app

This commit is contained in:
minjaesong
2020-05-19 11:14:27 +09:00
parent 9321dbceb1
commit 619257ecf2
10 changed files with 240 additions and 41 deletions

44
assets/jscon.js Normal file
View File

@@ -0,0 +1,44 @@
function readConsoleInput() {
var cmdbuf = "";
var key = -1;
while (key != 10 && key != 13) {
key = vm.readKey();
// printable chars
if (key >= 32 && key <= 126) {
var s = String.fromCharCode(key);
cmdbuf += s;
print(s);
}
// backspace
else if (key == 8 && cmdbuf.length > 0) {
cmdbuf = cmdbuf.substring(0, cmdbuf.length - 1);
print(String.fromCharCode(key));
}
// up down key
else if (key >= 19 && key <= 20) {
return key;
}
// left right key
else if (key >= 19 && key <= 20) {
//
}
}
return cmdbuf;
}
println("JS Console");
while (true) {
print("JS> ");
var cmdbuf = readConsoleInput();
if (typeof cmdbuf == "string") {
println();
try {
println(eval(cmdbuf));
}
catch (e) {
println(e);
}
}
}

View File

@@ -22,16 +22,9 @@ println("Starting TVDOS...");
greet();
/*while (true) {
while (true) {
print(get_prompt_text());
var s = read();
println();
println("String read: " + s + "@");
}*/
println(vm.peek(-4093)); // expecting an odd number
vm.poke(-4093, 6);
for (i = 0; i < 4096; i++) {
print(String.fromCharCode(vm.peek(-4097 - i)));
}
println();
}

View File

@@ -51,7 +51,8 @@ class VMGUI(val appConfig: LwjglApplicationConfiguration) : ApplicationAdapter()
vm.getInputStream = { gpu.getInputStream() }
// TEST PRG
val fr = FileReader("./assets/tvdos/command.js")
//val fr = FileReader("./assets/tvdos/command.js")
val fr = FileReader("./assets/jscon.js")
val prg = fr.readText()
fr.close()

View File

@@ -23,10 +23,16 @@ class VMJSR223Delegate(val vm: VM) {
}
fun println() = print('\n')
//fun readKey() = vm.inputStream.read()
fun readKey(): Int {
val inputStream = vm.getInputStream()
var key: Int = inputStream.read()
inputStream.close()
return key
}
/**
* Read series of key inputs until Enter/Return key is pressed
* Read series of key inputs until Enter/Return key is pressed. Backspace will work but any other non-printable
* characters (e.g. arrow keys) won't work.
*/
fun read(): String {
val inputStream = vm.getInputStream()

View File

@@ -8,6 +8,7 @@ abstract class BlockTransferInterface(val isMaster: Boolean, val isSlave: Boolea
open var busy = false
protected var sendmode = false; private set
open var blockSize = 0
open fun attachDevice(device: BlockTransferInterface?) {
recipient = device
@@ -39,10 +40,14 @@ abstract class BlockTransferInterface(val isMaster: Boolean, val isSlave: Boolea
open fun writeout(inputData: ByteArray, writeoutfun: (() -> Unit)? = null) {
busy = true
ready = false
blockSize = minOf(inputData.size, BLOCK_SIZE)
writeoutfun?.invoke()
busy = false
ready = true
}
abstract fun hasNext(): Boolean
open fun doYouHaveNext(): Boolean = recipient?.hasNext() ?: false
open fun yourBlockSize(): Int = recipient?.blockSize ?: 0
/** @param sendmode TRUE for send, FALSE for receive */
open fun setMode(sendmode: Boolean) {
@@ -52,4 +57,8 @@ abstract class BlockTransferInterface(val isMaster: Boolean, val isSlave: Boolea
open fun getMode(): Boolean = sendmode
open fun cableConnected(): Boolean = recipient?.recipient == this
companion object {
const val BLOCK_SIZE = 4096
}
}

View File

@@ -8,19 +8,22 @@ import net.torvald.tsvm.VM
*/
internal class BlockTransferPort(val vm: VM, val portno: Int) : BlockTransferInterface(true, false) {
internal var hasNext = false
override fun startSend(sendfun: ((BlockTransferInterface) -> Unit)?) {
super.startSend { recipient ->
val ba = ByteArray(4096) { vm.getIO().blockTransforBlock[portno][it.toLong()] }
val ba = ByteArray(BLOCK_SIZE) { vm.getIO().blockTransferRx[portno][it.toLong()] }
recipient.writeout(ba)
}
}
override fun hasNext(): Boolean = hasNext
override fun writeout(inputData: ByteArray, writeoutfun: (() -> Unit)?) {
super.writeout(inputData) {
val copySize = minOf(4096, inputData.size).toLong()
val copySize = minOf(BLOCK_SIZE, inputData.size).toLong()
val arrayOffset = UnsafeHelper.getArrayOffset(inputData).toLong()
UnsafeHelper.memcpyRaw(inputData, arrayOffset, null, vm.getIO().blockTransforBlock[portno].ptr, copySize)
UnsafeHelper.memcpyRaw(inputData, arrayOffset, null, vm.getIO().blockTransferRx[portno].ptr, copySize)
}
}

View File

@@ -18,14 +18,16 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor {
/** Absolute y-position of the computer GUI */
var guiPosY = 0
/** Accepts a keycode */
private val keyboardBuffer = CircularArray<Byte>(32, true)
private var mouseX: Short = 0
private var mouseY: Short = 0
private var mouseDown = false
private var keyboardInputRequested = false
internal val blockTransforBlock = arrayOf(
internal val blockTransferRx = arrayOf(
UnsafeHelper.allocate(4096),
UnsafeHelper.allocate(4096),
UnsafeHelper.allocate(4096),
UnsafeHelper.allocate(4096)
)
internal val blockTransferTx = arrayOf(
UnsafeHelper.allocate(4096),
UnsafeHelper.allocate(4096),
UnsafeHelper.allocate(4096),
@@ -33,6 +35,8 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor {
)
private val blockTransferPorts = Array(4) { BlockTransferPort(vm, it) }
private val keyEventBuffers = ByteArray(8)
init {
blockTransferPorts[0].attachDevice(TestFunctionGenerator())
}
@@ -71,17 +75,33 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor {
in 0..31 -> keyboardBuffer[(addr.toInt())] ?: -1
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
36L -> mouseDown.toInt().toByte()
37L -> keyboardBuffer.removeTail() ?: -1
38L -> if (keyboardInputRequested) 1 else 0
38L -> keyboardInputRequested.toInt().toByte()
39L -> rawInputFunctionLatched.toInt().toByte()
in 40..47 -> keyEventBuffers[adi - 40]
in 64..67 -> vm.memsize.shr((adi - 64) * 8).toByte()
68L -> (uptimeCounterLatched.toInt() or RTClatched.toInt().shl(1)).toByte()
in 72..79 -> systemUptime.ushr((adi - 72) * 8).and(255).toByte()
in 80..87 -> rtc.ushr((adi - 80) * 8).and(255).toByte()
4084L -> (blockTransferPorts[0].yourBlockSize().toByte())
4085L -> (blockTransferPorts[0].doYouHaveNext().toInt().shl(7) or blockTransferPorts[0].yourBlockSize().ushr(8).and(15)).toByte()
4086L -> (blockTransferPorts[1].yourBlockSize().toByte())
4087L -> (blockTransferPorts[1].doYouHaveNext().toInt().shl(7) or blockTransferPorts[1].yourBlockSize().ushr(8).and(15)).toByte()
4088L -> (blockTransferPorts[2].yourBlockSize().toByte())
4089L -> (blockTransferPorts[2].doYouHaveNext().toInt().shl(7) or blockTransferPorts[2].yourBlockSize().ushr(8).and(15)).toByte()
4090L -> (blockTransferPorts[3].yourBlockSize().toByte())
4091L -> (blockTransferPorts[4].doYouHaveNext().toInt().shl(7) or blockTransferPorts[3].yourBlockSize().ushr(8).and(15)).toByte()
in 4092..4095 -> composeBlockTransferStatus(adi - 4092).toByte()
in 4096..8191 -> blockTransforBlock[0][addr - 4096]
in 8192..12287 -> blockTransforBlock[1][addr - 8192]
in 12288..16383 -> blockTransforBlock[2][addr - 12288]
in 16384..20479 -> blockTransforBlock[3][addr - 16384]
in 4096..8191 -> blockTransferRx[0][addr - 4096]
in 8192..12287 -> blockTransferRx[1][addr - 8192]
in 12288..16383 -> blockTransferRx[2][addr - 12288]
in 16384..20479 -> blockTransferRx[3][addr - 16384]
in 131072..262143 -> vm.peripheralTable[1].peripheral?.mmio_read(addr - 131072)
in 262144..393215 -> vm.peripheralTable[2].peripheral?.mmio_read(addr - 262144)
@@ -101,15 +121,43 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor {
when (addr) {
37L -> keyboardBuffer.appendHead(byte)
38L -> {
keyboardInputRequested = (byte != 0.toByte())
keyboardInputRequested = (byte.isNonZero())
if (keyboardInputRequested) keyboardBuffer.clear()
}
39L -> rawInputFunctionLatched = (byte.isNonZero())
in 40..47 -> keyEventBuffers[adi - 40] = byte
68L -> {
uptimeCounterLatched = byte.and(0b01).isNonZero()
RTClatched = byte.and(0b10).isNonZero()
}
4084L -> blockTransferPorts[0].blockSize = blockTransferPorts[0].blockSize.and(0xFF00) or byte.toInt().and(255)
4085L -> {
blockTransferPorts[0].hasNext = (byte < 0)
blockTransferPorts[0].blockSize = blockTransferPorts[0].blockSize.and(0x00FF) or byte.toInt().and(15)
}
4086L -> blockTransferPorts[1].blockSize = blockTransferPorts[1].blockSize.and(0xFF00) or byte.toInt().and(255)
4087L -> {
blockTransferPorts[1].hasNext = (byte < 0)
blockTransferPorts[1].blockSize = blockTransferPorts[1].blockSize.and(0x00FF) or byte.toInt().and(15)
}
4088L -> blockTransferPorts[2].blockSize = blockTransferPorts[2].blockSize.and(0xFF00) or byte.toInt().and(255)
4089L -> {
blockTransferPorts[2].hasNext = (byte < 0)
blockTransferPorts[2].blockSize = blockTransferPorts[2].blockSize.and(0x00FF) or byte.toInt().and(15)
}
4090L -> blockTransferPorts[3].blockSize = blockTransferPorts[3].blockSize.and(0xFF00) or byte.toInt().and(255)
4091L -> {
blockTransferPorts[3].hasNext = (byte < 0)
blockTransferPorts[3].blockSize = blockTransferPorts[3].blockSize.and(0x00FF) or byte.toInt().and(15)
}
in 4092..4095 -> setBlockTransferPortStatus(adi - 4092, byte)
in 4096..8191 -> blockTransforBlock[0][addr - 4096] = byte
in 8192..12287 -> blockTransforBlock[1][addr - 8192] = byte
in 12288..16383 -> blockTransforBlock[2][addr - 12288] = byte
in 16384..20479 -> blockTransforBlock[3][addr - 16384] = byte
in 4096..8191 -> blockTransferTx[0][addr - 4096] = byte
in 8192..12287 -> blockTransferTx[1][addr - 8192] = byte
in 12288..16383 -> blockTransferTx[2][addr - 12288] = byte
in 16384..20479 -> blockTransferTx[3][addr - 16384] = byte
in 131072..262143 -> vm.peripheralTable[1].peripheral?.mmio_write(addr - 131072, byte)
in 262144..393215 -> vm.peripheralTable[2].peripheral?.mmio_write(addr - 262144, byte)
@@ -122,13 +170,47 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor {
}
override fun dispose() {
blockTransforBlock.forEach { it.destroy() }
blockTransferRx.forEach { it.destroy() }
blockTransferTx.forEach { it.destroy() }
}
private var mouseX: Short = 0
private var mouseY: Short = 0
private var mouseDown = false
private var systemUptime = 0L
private var rtc = 0L
fun update(delta: Float) {
mouseX = (Gdx.input.x + guiPosX).toShort()
mouseY = (Gdx.input.y + guiPosY).toShort()
mouseDown = Gdx.input.isTouched
if (rawInputFunctionLatched) {
rawInputFunctionLatched = false
// store mouse info
mouseX = (Gdx.input.x + guiPosX).toShort()
mouseY = (Gdx.input.y + guiPosY).toShort()
mouseDown = Gdx.input.isTouched
// strobe keys to fill the key read buffer
var keysPushed = 0
keyEventBuffers.fill(0)
for (k in 1..254) {
if (Gdx.input.isKeyPressed(k)) {
keyEventBuffers[keysPushed] = k.toByte()
keysPushed += 1
}
if (keysPushed >= 8) break
}
}
if (uptimeCounterLatched) {
uptimeCounterLatched = false
systemUptime = vm.getUptime()
}
if (RTClatched) {
RTClatched = false
rtc = System.currentTimeMillis()
}
}
override fun touchUp(p0: Int, p1: Int, p2: Int, p3: Int): Boolean {
@@ -140,7 +222,8 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor {
}
override fun keyTyped(p0: Char): Boolean {
if (keyboardInputRequested) {
if (keyboardInputRequested && !ttySpecialKeyLatched && p0.toInt() > 0) {
println("[IO] Key typed: ${p0.toInt()}")
keyboardBuffer.appendHead(p0.toByte())
return true
}
@@ -154,15 +237,28 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor {
}
override fun keyUp(p0: Int): Boolean {
return false
ttySpecialKeyLatched = false
return true
}
override fun touchDragged(p0: Int, p1: Int, p2: Int): Boolean {
return false
}
private var keyboardInputRequested = false
private var uptimeCounterLatched = false
private var RTClatched = false
private var rawInputFunctionLatched = false
private var ttySpecialKeyLatched = false
// UP DN LE RI
private var specialKey = listOf(19,20,21,22).toSortedSet()
override fun keyDown(p0: Int): Boolean {
return false
if (keyboardInputRequested && !ttySpecialKeyLatched && p0 in specialKey) {
println("[IO] Key down: $p0")
keyboardBuffer.appendHead(p0.toByte())
}
return true
}
override fun touchDown(p0: Int, p1: Int, p2: Int, p3: Int): Boolean {
@@ -170,4 +266,5 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor {
}
private fun Boolean.toInt() = if (this) 1 else 0
}
private fun Byte.isNonZero() = this != 0.toByte()
}

View File

@@ -0,0 +1,14 @@
package net.torvald.tsvm.peripheral
import java.util.*
class SerialDiskDrive : BlockTransferInterface(false, true) {
override fun hasNext(): Boolean {
TODO("Not yet implemented")
}
val diskID: UUID = UUID(0, 0)
}

View File

@@ -18,6 +18,8 @@ Nunc mollis nibh vitae sapien consequat, ut vestibulum sem pharetra. Aliquam iac
super.startSend { it.writeout(msg) }
}
override fun hasNext(): Boolean = false
override fun writeout(inputData: ByteArray, writeoutfun: (() -> Unit)?) {
}

View File

@@ -42,6 +42,10 @@ IO Device
Endianness: little
Note: Always takes up the peripheral slot of zero
Latching: latching is used to "lock" the fluctuating values when you attempt to read them so you would get
reliable values when you try to read them, especially the multibyte values where another byte would
change after you read one byte, e.g. System uptime in nanoseconds
MMIO
0..31 RO: Raw Keyboard Buffer read. Won't shift the key buffer
@@ -51,11 +55,37 @@ MMIO
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
Stores ASCII code representing the character, plus:
19: Up arrow
20: Down arrow
21: Left arrow
22: Right arrow
38 RW: Request keyboard input be read (TTY Function). 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!
39 WO: Latch Key/Mouse Input (Raw Input function). Write nonzero value to latch.
Stores LibGDX Key code
40..47 RO: Key Press buffer
stores keys that are held down. Can accomodate 8-key rollover (in keyboard geeks' terms)
64..67 RO: User area memory size in bytes
68 WO: Counter latch
0b 0000 00ba
a: System uptime
b: RTC
72..79 RO: System uptime in nanoseconds
80..87 RO: RTC in microseconds
4084..4091 RO: Block transfer status
0b nnnnnnnn a000 mmmm
n-read: size of the block from the other device, LSB (4096-full block size is zero)
m-read: size of the block from the other device, MSB (4096-full block size is zero)
a-read: if the other device hasNext (doYouHaveNext), false if device not present
n-write: size of the block I'm sending, LSB (4096-full block size is zero)
m-write: size of the block I'm sending, MSB (4096-full block size is zero)
a-write: if there's more to send (hasNext)
4092..4095 RW: Block transfer control for Port 1 through 4
0b 00ms abcd