From 20b97558e4c8ad70165c731dd4a56f3f85a636cf Mon Sep 17 00:00:00 2001
From: Anders Granlund <[EMAIL REDACTED]>
Date: Thu, 27 Jun 2024 22:57:48 +0200
Subject: [PATCH] atari:events:xbios: add keyboard handler
Add support for hooking the keyboard vector on TOS >= 2.x
---
src/video/ataricommon/SDL_atarievents.c | 8 ++
src/video/ataricommon/SDL_xbiosevents.c | 97 ++++++++++++++++++++
src/video/ataricommon/SDL_xbiosevents_c.h | 8 ++
src/video/ataricommon/SDL_xbiosinterrupt.S | 86 +++++++++++++++++
src/video/ataricommon/SDL_xbiosinterrupt_s.h | 3 +
5 files changed, 202 insertions(+)
diff --git a/src/video/ataricommon/SDL_atarievents.c b/src/video/ataricommon/SDL_atarievents.c
index a5172de3..d913f0bc 100644
--- a/src/video/ataricommon/SDL_atarievents.c
+++ b/src/video/ataricommon/SDL_atarievents.c
@@ -39,6 +39,7 @@
#include "SDL_atarikeys.h"
#include "SDL_atarievents_c.h"
#include "SDL_biosevents_c.h"
+#include "SDL_xbiosevents_c.h"
#include "SDL_gemdosevents_c.h"
#include "SDL_ikbdevents_c.h"
@@ -117,6 +118,13 @@ static void Atari_InitializeEvents(_THIS)
this->PumpEvents=AtariBios_PumpEvents;
Atari_ShutdownEvents=AtariBios_ShutdownEvents;
}
+
+ if (SDL_strcmp(envr, "xbios") == 0) {
+ this->InitOSKeymap=AtariXbios_InitOSKeymap;
+ this->PumpEvents=AtariXbios_PumpEvents;
+ Atari_ShutdownEvents=AtariXbios_ShutdownEvents;
+ }
+
}
void Atari_InitOSKeymap(_THIS)
diff --git a/src/video/ataricommon/SDL_xbiosevents.c b/src/video/ataricommon/SDL_xbiosevents.c
index 3dd26a8f..0708cf76 100644
--- a/src/video/ataricommon/SDL_xbiosevents.c
+++ b/src/video/ataricommon/SDL_xbiosevents.c
@@ -29,11 +29,19 @@
#include <mint/osbind.h>
+#include "../../events/SDL_sysevents.h"
#include "../../events/SDL_events_c.h"
+
#include "SDL_atarisuper.h"
+#include "SDL_atarikeys.h"
+#include "SDL_atarievents_c.h"
#include "SDL_xbiosevents_c.h"
#include "SDL_xbiosinterrupt_s.h"
+#define KEY_PRESSED 0xff
+#define KEY_UNDEFINED 0x80
+#define KEY_RELEASED 0x00
+
/* Variables */
SDL_bool SDL_AtariXbios_enabled=SDL_FALSE;
@@ -44,6 +52,44 @@ static Uint16 atari_prevmouseb; /* buttons */
/* Functions */
+SDL_bool SDL_AtariXbios_IsKeyboardVectorSupported_Super()
+{
+ /* TODO: FreeMiNT (MagiC, Geneva?) */
+ uint16_t* oshdr = *((uint16_t**)(0x4f2));
+ return (oshdr[1] >= 0x0200) ? SDL_TRUE : SDL_FALSE;
+}
+
+SDL_bool SDL_AtariXbios_IsKeyboardVectorSupported()
+{
+ return Supexec(SDL_AtariXbios_IsKeyboardVectorSupported_Super);
+}
+
+void AtariXbios_InitOSKeymap(_THIS)
+{
+ int vectors_mask;
+ vectors_mask = ATARI_XBIOS_JOYSTICKEVENTS; /* XBIOS joystick events */
+ vectors_mask |= ATARI_XBIOS_MOUSEEVENTS; /* XBIOS mouse events */
+ if (SDL_AtariXbios_IsKeyboardVectorSupported()) {
+ vectors_mask |= ATARI_XBIOS_KEYBOARDEVENTS; /* XBIOS keyboard events */
+ } else {
+ SDL_SetError("Xbios keyboard vector is not supported on TOS 1.x");
+ return;
+ }
+
+ SDL_AtariXbios_InstallVectors(vectors_mask);
+}
+
+void AtariXbios_PumpEvents(_THIS)
+{
+ SDL_AtariXbios_PostKeyboardEvents(this);
+ SDL_AtariXbios_PostMouseEvents(this, SDL_TRUE);
+}
+
+void AtariXbios_ShutdownEvents(void)
+{
+ SDL_AtariXbios_RestoreVectors();
+}
+
void SDL_AtariXbios_InstallVectors(int vectors_mask)
{
/* Clear variables */
@@ -54,6 +100,8 @@ void SDL_AtariXbios_InstallVectors(int vectors_mask)
SDL_AtariXbios_joystick =
atari_prevmouseb = 0;
+ SDL_memset((void*)SDL_AtariXbios_keyboard, KEY_UNDEFINED, 128);
+
if (vectors_mask==0) {
SDL_AtariXbios_enabled=SDL_FALSE;
return;
@@ -62,6 +110,8 @@ void SDL_AtariXbios_InstallVectors(int vectors_mask)
/* Install our vectors */
SDL_AtariXbios_installmousevector = (vectors_mask & ATARI_XBIOS_MOUSEEVENTS) != 0;
SDL_AtariXbios_installjoystickvector = (vectors_mask & ATARI_XBIOS_JOYSTICKEVENTS) != 0;
+ SDL_AtariXbios_installkeyboardvector = (vectors_mask & ATARI_XBIOS_KEYBOARDEVENTS) != 0;
+
Supexec(SDL_AtariXbios_Install);
/* SDL_AtariXbios_Restore() doesn't need SDL_AtariXbios_enabled */
Setexc(VEC_PROCTERM, SDL_AtariXbios_Restore);
@@ -130,3 +180,50 @@ void SDL_AtariXbios_LockMousePosition(SDL_bool lockPosition)
{
SDL_AtariXbios_mouselock = lockPosition;
}
+
+void SDL_AtariXbios_PostKeyboardEvents(_THIS)
+{
+ short i, kstate;
+ SDL_keysym keysym;
+
+ if (!SDL_AtariXbios_enabled) {
+ return;
+ }
+
+ kstate = (SDL_AtariXbios_keyboard[SCANCODE_LEFTSHIFT] == KEY_PRESSED) ? K_LSHIFT : 0;
+ kstate |= (SDL_AtariXbios_keyboard[SCANCODE_RIGHTSHIFT] == KEY_PRESSED) ? K_RSHIFT : 0;
+ kstate |= (SDL_AtariXbios_keyboard[SCANCODE_LEFTCONTROL] == KEY_PRESSED) ? K_CTRL : 0;
+ kstate |= (SDL_AtariXbios_keyboard[SCANCODE_LEFTALT] == KEY_PRESSED) ? K_ALT : 0;
+ kstate |= (SDL_AtariXbios_keyboard[SCANCODE_CAPSLOCK] == KEY_PRESSED) ? K_CAPSLOCK : 0;
+ kstate |= (SDL_AtariXbios_keyboard[SCANCODE_ALTGR] == KEY_PRESSED) ? 0x80 : 0;
+
+ for (i=0; i<sizeof(SDL_AtariXbios_keyboard); i++) {
+ /* Key pressed ? */
+ if (SDL_AtariXbios_keyboard[i]==KEY_PRESSED) {
+ SDL_PrivateKeyboard(SDL_PRESSED,
+ SDL_Atari_TranslateKey(i, &keysym, SDL_TRUE, kstate));
+ if (i == SCANCODE_CAPSLOCK) {
+ /* Pressed capslock: generate a release event, too because this
+ * is what SDL expects; it handles locking by itself.
+ */
+ SDL_PrivateKeyboard(SDL_RELEASED,
+ SDL_Atari_TranslateKey(i, &keysym, SDL_FALSE, kstate & ~K_CAPSLOCK));
+ }
+ SDL_AtariXbios_keyboard[i]=KEY_UNDEFINED;
+ }
+
+ /* Key released ? */
+ if (SDL_AtariXbios_keyboard[i]==KEY_RELEASED) {
+ if (i == SCANCODE_CAPSLOCK) {
+ /* Released capslock: generate a pressed event, too because this
+ * is what SDL expects; it handles locking by itself.
+ */
+ SDL_PrivateKeyboard(SDL_PRESSED,
+ SDL_Atari_TranslateKey(i, &keysym, SDL_TRUE, kstate | K_CAPSLOCK));
+ }
+ SDL_PrivateKeyboard(SDL_RELEASED,
+ SDL_Atari_TranslateKey(i, &keysym, SDL_FALSE, kstate));
+ SDL_AtariXbios_keyboard[i]=KEY_UNDEFINED;
+ }
+ }
+}
diff --git a/src/video/ataricommon/SDL_xbiosevents_c.h b/src/video/ataricommon/SDL_xbiosevents_c.h
index 40a43308..55482d33 100644
--- a/src/video/ataricommon/SDL_xbiosevents_c.h
+++ b/src/video/ataricommon/SDL_xbiosevents_c.h
@@ -37,12 +37,20 @@
#define ATARI_XBIOS_MOUSEEVENTS (1<<0)
#define ATARI_XBIOS_JOYSTICKEVENTS (1<<1)
+#define ATARI_XBIOS_KEYBOARDEVENTS (1<<2)
extern SDL_bool SDL_AtariXbios_enabled;
+extern void AtariXbios_InitOSKeymap(_THIS);
+extern void AtariXbios_PumpEvents(_THIS);
+extern void AtariXbios_ShutdownEvents(void);
+
extern void SDL_AtariXbios_InstallVectors(int vectors_mask);
extern void SDL_AtariXbios_RestoreVectors(void);
extern void SDL_AtariXbios_PostMouseEvents(_THIS, SDL_bool buttonEvents);
extern void SDL_AtariXbios_LockMousePosition(SDL_bool lockPosition);
+extern void SDL_AtariXbios_PostKeyboardEvents(_THIS);
+
+extern SDL_bool SDL_AtariXbios_IsKeyboardVectorSupported();
#endif /* _SDL_XBIOSEVENTS_H_ */
diff --git a/src/video/ataricommon/SDL_xbiosinterrupt.S b/src/video/ataricommon/SDL_xbiosinterrupt.S
index d000194f..d03073ea 100644
--- a/src/video/ataricommon/SDL_xbiosinterrupt.S
+++ b/src/video/ataricommon/SDL_xbiosinterrupt.S
@@ -40,6 +40,8 @@
.globl SYM(SDL_AtariXbios_mousey)
.globl SYM(SDL_AtariXbios_installjoystickvector)
.globl SYM(SDL_AtariXbios_joystick)
+ .globl SYM(SDL_AtariXbios_installkeyboardvector)
+ .globl SYM(SDL_AtariXbios_keyboard)
.globl SYM(Atari_UnhookXbra)
@@ -99,6 +101,21 @@ no_new_mouse_vector:
#endif
no_new_joystick_vector:
+ /* Save old keyboard vector, set our routine */
+
+ tstw SYM(SDL_AtariXbios_installkeyboardvector)
+ beqs no_new_keyboard_vector
+#if defined(__mcoldfire__)
+ movel a0@(-4),a1
+ movel a1,oldkeyboardvector
+ lea newkeyboardvector(pc),a1
+ movel a1,a0@(-4)
+#else
+ movel a0@(-4),oldkeyboardvector
+ movel #newkeyboardvector,a0@(-4)
+#endif
+no_new_keyboard_vector:
+
/* Restart interrupts */
movew d1,sr
@@ -176,6 +193,24 @@ no_restore_mouse:
no_restore_joystick:
+ /* Restore keyboard vector */
+
+ tstl oldkeyboardvector
+ beqs no_restore_keyboard
+
+ movew d1,sp@-
+
+ pea newkeyboardvector(pc)
+ movel #0x4c53444c,sp@- /* "LSDL" */
+ pea a0@(-4)
+ jsr SYM(Atari_UnhookXbra)
+ lea sp@(12),sp
+ clrl oldkeyboardvector
+
+ movew sp@+,d1
+
+no_restore_keyboard:
+
/* Restart interrupts */
movew d1,sr
@@ -294,3 +329,54 @@ SYM(SDL_AtariXbios_installjoystickvector):
.dc.w 0
SYM(SDL_AtariXbios_joystick):
.dc.w 0
+
+
+/*--- Our keyboard vector ---*/
+
+ .text
+
+ .even
+ .ascii "XBRA"
+ .ascii "LSDL"
+oldkeyboardvector:
+ .dc.l 0
+newkeyboardvector:
+
+#if defined(__mcoldfire__)
+ lea sp@(-12),sp
+ moveml d0-d1/a0,sp@
+#else
+ moveml d0-d1/a0,sp@-
+#endif
+
+ moveb d0,d1
+ lea SYM(SDL_AtariXbios_keyboard),a0
+#if defined(__mcoldfire__)
+ andl #0x7f,d1
+ btst #7,d0
+ seq d0
+ moveb d0,a0@(0,d1:l)
+#else
+ andw #0x7f,d1
+ btst #7,d0
+ seq a0@(0,d1:w)
+#endif
+
+ /* Jump through old vector */
+#if defined(__mcoldfire__)
+ moveml sp@,d0-d1/a0
+ lea sp@(12),sp
+#else
+ moveml sp@+,d0-d1/a0
+#endif
+
+ movel oldkeyboardvector,sp@-
+ rts
+
+ .data
+
+ .even
+SYM(SDL_AtariXbios_installkeyboardvector):
+ .dc.w 0
+SYM(SDL_AtariXbios_keyboard):
+ .ds.b 128
diff --git a/src/video/ataricommon/SDL_xbiosinterrupt_s.h b/src/video/ataricommon/SDL_xbiosinterrupt_s.h
index efaf85b2..f669498d 100644
--- a/src/video/ataricommon/SDL_xbiosinterrupt_s.h
+++ b/src/video/ataricommon/SDL_xbiosinterrupt_s.h
@@ -41,6 +41,8 @@ extern volatile Sint16 SDL_AtariXbios_mousex; /* X relative motion */
extern volatile Sint16 SDL_AtariXbios_mousey; /* Y relative motion */
extern Uint16 SDL_AtariXbios_installjoystickvector; /* flag for SDL_AtariXbios_Install() */
extern volatile Uint16 SDL_AtariXbios_joystick; /* Joystick */
+extern Uint16 SDL_AtariXbios_installkeyboardvector; /* flag for SDL_AtariXbios_Install() */
+extern volatile Uint8 SDL_AtariXbios_keyboard[128]; /* Keyboard table */
/* Functions */
@@ -48,5 +50,6 @@ extern void SDL_AtariXbios_Install(void);
extern void SDL_AtariXbios_Restore(void);
extern void SDL_AtariXbios_MouseVector(void *buf);
extern void SDL_AtariXbios_JoystickVector(void *buf);
+extern void SDL_AtariXbios_KeyboardVector(void *buf);
#endif /* _SDL_XBIOSINTERRUPT_S_H_ */