Fix sticky keys in doom. host-sdl only reported the last key pressed, now uses a circular buffer.

This commit is contained in:
Toby Jaffey 2025-12-14 22:39:24 +00:00
parent 49a94ca174
commit e524ea4815

View file

@ -19,13 +19,36 @@
#define WIDTH 320 #define WIDTH 320
#define HEIGHT 200 #define HEIGHT 200
#define WINDOW_WIDTH WIDTH*2 #define WINDOW_WIDTH WIDTH*3
#define WINDOW_HEIGHT HEIGHT*2 #define WINDOW_HEIGHT HEIGHT*3
// TBD replace with queue of keypresses // circular buffer of keypresses, so vm code can read them as it's ready
uint16_t last_keyscancode; typedef struct {
bool last_keyvalid = false; bool down;
bool last_keypressed = false; uint16_t scancode;
} keyevent_t;
#define KEYBUFFER_LEN 8
static keyevent_t keyBuffer[KEYBUFFER_LEN];
static int keyBufferWr = 0;
static int keyBufferRd = 0;
void key_enq(uint16_t scancode, bool down) {
keyBuffer[keyBufferWr].scancode = scancode;
keyBuffer[keyBufferWr].down = down;
keyBufferWr = (keyBufferWr + 1) % KEYBUFFER_LEN;
}
bool key_deq(keyevent_t *ke) {
if (keyBufferWr != keyBufferRd) {
*ke = keyBuffer[keyBufferRd];
keyBufferRd = (keyBufferRd + 1) % KEYBUFFER_LEN;
return true;
} else {
return false;
}
}
static uint8_t *read_file(const char* filename, int *len) { static uint8_t *read_file(const char* filename, int *len) {
FILE* f = fopen(filename, "rb"); FILE* f = fopen(filename, "rb");
@ -185,16 +208,12 @@ int main(int argc, char *argv[]) {
break; break;
case SDL_EVENT_KEY_DOWN: case SDL_EVENT_KEY_DOWN:
if (!event.key.repeat) { if (!event.key.repeat) {
last_keyscancode = event.key.scancode; key_enq(event.key.scancode, true);
last_keypressed = true;
last_keyvalid = true;
} }
break; break;
case SDL_EVENT_KEY_UP: case SDL_EVENT_KEY_UP:
if (!event.key.repeat) { if (!event.key.repeat) {
last_keyscancode = event.key.scancode; key_enq(event.key.scancode, false);
last_keypressed = false;
last_keyvalid = true;
} }
break; break;
} }
@ -281,15 +300,15 @@ int main(int argc, char *argv[]) {
SDL_RenderTexture(renderer, render_target, &src_rect, &dst_rect); SDL_RenderTexture(renderer, render_target, &src_rect, &dst_rect);
SDL_RenderPresent(renderer); SDL_RenderPresent(renderer);
} break; } break;
case UVM32_SYSCALL_GETKEY: case UVM32_SYSCALL_GETKEY: {
if (last_keyvalid) { keyevent_t ke;
uint32_t code = (last_keypressed ? 0x80000000 : 0) | last_keyscancode; if (key_deq(&ke)) {
uint32_t code = (ke.down ? 0x80000000 : 0) | ke.scancode;
uvm32_arg_setval(vmst, &evt, RET, code); uvm32_arg_setval(vmst, &evt, RET, code);
} else { } else {
uvm32_arg_setval(vmst, &evt, RET, 0xFFFFFFFF); uvm32_arg_setval(vmst, &evt, RET, 0xFFFFFFFF);
} }
last_keyvalid = false; } break;
break;
default: default:
printf("Unhandled syscall 0x%08x\n", evt.data.syscall.code); printf("Unhandled syscall 0x%08x\n", evt.data.syscall.code);
break; break;