[Fixed] The emulator only handles one key event at a time, and it interferes with mouse/joystick input
Posted: Thu Mar 23, 2023 7:58 pm
The quickest way to observe this is:
So, how did I find this?
I noticed the kernal had a limitation where kbd_scan only reads one scancode at a time, so for games, you need to repeatedly call kbd_scan in a loop or else all keyboard input will be buffered as one-change-per-frame. I think this is fine in many cases, it's just that game developers will need to be aware of this and how to work around it.
I used the codex to write a simple test (attached): a scancode handler which INC's a memory address (i.e., how many times the scancode handler runs per kbd_scan call), and a custom IRQ handler which repeatedly calls kbd_scan until it detects that the scancode handler ran 0 times (i.e., when the i2c keyboard buffer is empty).
To use this test, extract the contents of the attached ZIP file somewhere the X16 can access it, then open the codex and load "KBDTEST.ASM". Exit back to BASIC, then type SYS $4000 to install the hooks (a side effect is, you lose the flashing cursor, but you can still type like usual). Now, mash the keyboard, then type PRINT PEEK($3003). This value represents the maximum amount of scancodes that were received in one IRQ. In the emulator, this is always "1", but on hardware, I imagine this number will get larger.
...and that's why I looked at the emulator source and found what I found.
- At the ready prompt, type MOUSE 1
- Try waggling the mouse while repeatedly mashing keys on the keyboard.
- Observe that the mouse movement becomes very choppy.
So, how did I find this?
I noticed the kernal had a limitation where kbd_scan only reads one scancode at a time, so for games, you need to repeatedly call kbd_scan in a loop or else all keyboard input will be buffered as one-change-per-frame. I think this is fine in many cases, it's just that game developers will need to be aware of this and how to work around it.
I used the codex to write a simple test (attached): a scancode handler which INC's a memory address (i.e., how many times the scancode handler runs per kbd_scan call), and a custom IRQ handler which repeatedly calls kbd_scan until it detects that the scancode handler ran 0 times (i.e., when the i2c keyboard buffer is empty).
To use this test, extract the contents of the attached ZIP file somewhere the X16 can access it, then open the codex and load "KBDTEST.ASM". Exit back to BASIC, then type SYS $4000 to install the hooks (a side effect is, you lose the flashing cursor, but you can still type like usual). Now, mash the keyboard, then type PRINT PEEK($3003). This value represents the maximum amount of scancodes that were received in one IRQ. In the emulator, this is always "1", but on hardware, I imagine this number will get larger.
...and that's why I looked at the emulator source and found what I found.