From 8de550f702b67888b06432c99a553c8d5f690d49 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <slouken@libsdl.org>
Date: Sun, 10 Mar 2002 03:33:59 +0000
Subject: [PATCH] Atari port cleanups from Patrice

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40306
---
 README.MiNT                                   | 11 +--
 src/joystick/mint/SDL_sysjoystick.c           | 72 +++++++++++--------
 src/video/ataricommon/Makefile.am             |  8 +--
 src/video/ataricommon/SDL_biosevents.c        |  8 +--
 src/video/ataricommon/SDL_gemdosevents.c      |  8 +--
 src/video/ataricommon/SDL_ikbdinterrupt.S     |  7 ++
 src/video/ataricommon/SDL_ikbdinterrupt_s.h   | 18 ++++-
 ...L_xbiosmouseevents.c => SDL_xbiosevents.c} | 37 ++++++----
 ...iosmouseevents_c.h => SDL_xbiosevents_c.h} | 19 +++--
 ...smouseinterrupt.S => SDL_xbiosinterrupt.S} | 59 +++++++++++----
 ...seinterrupt_s.h => SDL_xbiosinterrupt_s.h} | 12 ++--
 src/video/gem/SDL_gemvideo.c                  |  6 ++
 12 files changed, 180 insertions(+), 85 deletions(-)
 rename src/video/ataricommon/{SDL_xbiosmouseevents.c => SDL_xbiosevents.c} (78%)
 rename src/video/ataricommon/{SDL_xbiosmouseevents_c.h => SDL_xbiosevents_c.h} (72%)
 rename src/video/ataricommon/{SDL_xbiosmouseinterrupt.S => SDL_xbiosinterrupt.S} (63%)
 rename src/video/ataricommon/{SDL_xbiosmouseinterrupt_s.h => SDL_xbiosinterrupt_s.h} (77%)

diff --git a/README.MiNT b/README.MiNT
index 2d97559c..31f665a5 100644
--- a/README.MiNT
+++ b/README.MiNT
@@ -59,9 +59,9 @@ Threads support (TOS)
 - Driver combinations:
 Video	Kbd	Mouse	Timer	Jstick	Joypads
 xbios	ikbd	ikbd	vbl	ikbd	hardware
-xbios	gemdos	xbios	vbl	-	hardware
-xbios	bios	xbios	vbl	-	hardware
-gem	gem	gem	vbl	-	hardware
+xbios	gemdos	xbios	vbl	xbios	hardware
+xbios	bios	xbios	vbl	xbios	hardware
+gem	gem	gem	vbl	xbios	hardware
 
 ==============================================================================
 V.  Environment variables:
@@ -79,7 +79,8 @@ SDL_JOYSTICK_ATARI:
 	Use any of these strings in the environment variable to enable or
 	disable a joystick:
 
-	'ikbd-joy1-[on|off]' for IKBD joystick on port 1
+	'ikbd-joy1-[on|off]' for IKBD joystick on port 1 (hardware access)
+	'xbios-joy1-[on|off]' for IKBD joystick on port 1 (xbios access)
 	'porta-pad-[on|off]' for joypad on port A
 	'porta-joy0-[on|off]' for joystick 0 on port A
 	'porta-joy1-[on|off]' for joystick 1 on port A
@@ -92,6 +93,7 @@ SDL_JOYSTICK_ATARI:
 
 	Default configuration is:
 		'ikbd-joy1-on' (if IKBD events driver enabled)
+		'xbios-joy1-on' (if gemdos/bios/gem events driver enabled)
 		'porta-pad-on portb-pad-on' (if available on the machine)
 
 	port[a|b]-[pad|joy?|lp|anpad]-* strings are mutually exclusives.
@@ -99,7 +101,6 @@ SDL_JOYSTICK_ATARI:
 	a lightpen OR an analog paddle. You must disable joypad before
 	setting another controller.
 
-	IKBD joystick only available when the IKBD events driver is enabled.
 	The second joystick port on IKBD is used by the mouse, so not usable.
 
 	Joypads are multibuttons controller (Atari Jaguar console-like).
diff --git a/src/joystick/mint/SDL_sysjoystick.c b/src/joystick/mint/SDL_sysjoystick.c
index 4d20f7b0..867611d0 100644
--- a/src/joystick/mint/SDL_sysjoystick.c
+++ b/src/joystick/mint/SDL_sysjoystick.c
@@ -31,6 +31,7 @@ static char rcsid =
  *	Patrice Mandin
  */
 
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -43,12 +44,15 @@ static char rcsid =
 #include "SDL_sysjoystick.h"
 #include "SDL_joystick_c.h"
 
-#include "../video/ataricommon/SDL_ikbdinterrupt_s.h"
+#include "SDL_ikbdinterrupt_s.h"
+#include "SDL_xbiosevents_c.h"
+#include "SDL_xbiosinterrupt_s.h"
 
 /*--- Const ---*/
 
 /* We can have:
-	1 joystick on IKBD port 1 (port 0 is used by mouse)
+	1 joystick on IKBD port 1, read via hardware I/O
+      or same joystick on IKBD port 1, read via xbios
 	2 joypads on ports A,B
 	  or 4 joysticks on joypads ports A,B
 	  or 1 lightpen on joypad port A
@@ -58,6 +62,7 @@ static char rcsid =
 
 enum {
 	IKBD_JOY1=0,
+	XBIOS_JOY1,
 	PORTA_PAD,
 	PORTB_PAD,
 	PORTA_JOY0,
@@ -116,6 +121,7 @@ typedef struct {
 
 static atarijoy_t atarijoysticks[MAX_JOYSTICKS]={
 	{SDL_FALSE,"IKBD joystick port 1",0},
+	{SDL_FALSE,"Xbios joystick port 1",0},
 	{SDL_FALSE,"Joypad port A",0},
 	{SDL_FALSE,"Joypad port B",0},
 	{SDL_FALSE,"Joystick 0 port A",0},
@@ -132,11 +138,11 @@ static atarijoy_t atarijoysticks[MAX_JOYSTICKS]={
 };
 
 static const int jp_buttons[JP_NUM_BUTTONS]={
-	JP_KPMULT,	JP_KP7,		JP_KP4,		JP_KP1,
-	JP_KP0,		JP_KP8,		JP_KP5,		JP_KP2,
-	JP_KPNUM,	JP_KP9,		JP_KP6,		JP_KP3,
-	JP_PAUSE,	JP_FIRE0,	JP_FIRE1,	JP_FIRE2,
-	JP_OPTION
+	JP_FIRE0,	JP_FIRE1,	JP_FIRE2,	JP_PAUSE,
+	JP_OPTION,	JP_KPMULT,	JP_KPNUM,	JP_KP0,
+	JP_KP1,		JP_KP2,		JP_KP3,		JP_KP4,
+	JP_KP5,		JP_KP6,		JP_KP7,		JP_KP8,
+	JP_KP9
 };
 
 static SDL_bool joypad_ports_enabled=SDL_FALSE;
@@ -160,8 +166,6 @@ int SDL_SYS_JoystickInit(void)
 	int i;
 	unsigned long cookie_mch;
 	const char *envr=getenv("SDL_JOYSTICK_ATARI");
-	const char *env_evt=getenv("SDL_ATARI_EVENTSDRIVER");
-	SDL_bool ikbd_enabled=SDL_FALSE;
 	
 #define TEST_JOY_ENABLED(env,idstring,num) \
 	if (strstr(env,idstring"-off")) { \
@@ -179,28 +183,23 @@ int SDL_SYS_JoystickInit(void)
 	/* Enable some default joysticks */
 	if ((cookie_mch == MCH_ST<<16) || ((cookie_mch>>16) == MCH_STE) ||
 		(cookie_mch == MCH_TT<<16) || (cookie_mch == MCH_F30<<16)) {
-		ikbd_enabled=SDL_TRUE;
-		if (env_evt) {
-			if (!strcmp(env_evt,"ikbd")) {
-				ikbd_enabled=SDL_FALSE;
-			}
-		}
-		atarijoysticks[IKBD_JOY1].enabled=ikbd_enabled;
+		atarijoysticks[IKBD_JOY1].enabled=(SDL_AtariIkbd_enabled!=0);
 	}
 	if ((cookie_mch == MCH_STE<<16) || (cookie_mch == MCH_F30<<16)) {
 		atarijoysticks[PORTA_PAD].enabled=SDL_TRUE;
 		atarijoysticks[PORTB_PAD].enabled=SDL_TRUE;
 	}
+	if (!atarijoysticks[IKBD_JOY1].enabled) {
+		atarijoysticks[XBIOS_JOY1].enabled=(SDL_AtariXbios_enabled!=0);
+	}
 
 	/* Read environment for joysticks to enable */
 	if (envr) {
 		/* IKBD on any Atari, maybe clones */
 		if ((cookie_mch == MCH_ST<<16) || ((cookie_mch>>16) == MCH_STE) ||
 			(cookie_mch == MCH_TT<<16) || (cookie_mch == MCH_F30<<16)) {
-			if (env_evt) {
-				if (strcmp(env_evt,"ikbd")) {
-					TEST_JOY_ENABLED(envr, "ikbd-joy1", IKBD_JOY1);
-				}
+			if (SDL_AtariIkbd_enabled!=0) {
+				TEST_JOY_ENABLED(envr, "ikbd-joy1", IKBD_JOY1);
 			}
 		}
 		/* Joypads ports only on STE and Falcon */
@@ -226,6 +225,12 @@ int SDL_SYS_JoystickInit(void)
 				}
 			}
 		}
+
+		if (!atarijoysticks[IKBD_JOY1].enabled) {
+			if (SDL_AtariXbios_enabled!=0) {
+				TEST_JOY_ENABLED(envr, "xbios-joy1", XBIOS_JOY1);
+			}
+		}
 #if 0
 		/* Parallel port on any Atari, maybe clones */
 		if ((cookie_mch == MCH_ST<<16) || ((cookie_mch>>16) == MCH_STE) ||
@@ -262,13 +267,15 @@ static int GetEnabledAtariJoystick(int index)
 	/* Return the nth'index' enabled atari joystick */
 	j=0;
 	for (i=0;i<MAX_JOYSTICKS;i++) {
-		if (atarijoysticks[i].enabled) {
-			if (j==index) {
-				break;
-			} else {
-				j++;
-			}
+		if (!atarijoysticks[i].enabled) {
+			continue;
 		}
+
+		if (j==index) {
+			break;
+		}
+
+		++j;
 	}
 	if (i==MAX_JOYSTICKS)
 		return -1;
@@ -328,8 +335,17 @@ void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
 
 	switch (numjoystick) {
 		case IKBD_JOY1:
+		case XBIOS_JOY1:
 			{
-				curstate = SDL_AtariIkbd_joystick & 0xff;
+				curstate = 0;
+
+				if (numjoystick==IKBD_JOY1) {
+					curstate = SDL_AtariIkbd_joystick & 0xff;
+				}
+				if (numjoystick==XBIOS_JOY1) {
+					curstate = SDL_AtariXbios_joystick & 0xff;
+				}
+
 				if (curstate != prevstate) {
 					/* X axis */
 					if ((curstate & (IKBD_JOY_LEFT|IKBD_JOY_RIGHT)) != (prevstate & (IKBD_JOY_LEFT|IKBD_JOY_RIGHT))) {
@@ -359,7 +375,7 @@ void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick)
 						SDL_PrivateJoystickButton(joystick,0,SDL_RELEASED);
 					}
 				}
-				atarijoysticks[IKBD_JOY1].prevstate = curstate;
+				atarijoysticks[numjoystick].prevstate = curstate;
 			}
 			break;
 		case PORTA_PAD:
diff --git a/src/video/ataricommon/Makefile.am b/src/video/ataricommon/Makefile.am
index ea98d58c..1be48b45 100644
--- a/src/video/ataricommon/Makefile.am
+++ b/src/video/ataricommon/Makefile.am
@@ -25,7 +25,7 @@ ATARICOMMON_SRCS = 	\
 	SDL_ikbdevents_c.h \
 	SDL_ikbdinterrupt.S	\
 	SDL_ikbdinterrupt_s.h \
-	SDL_xbiosmouseevents.c \
-	SDL_xbiosmouseevents_c.h \
-	SDL_xbiosmouseinterrupt.S \
-	SDL_xbiosmouseinterrupt_s.h
+	SDL_xbiosevents.c \
+	SDL_xbiosevents_c.h \
+	SDL_xbiosinterrupt.S \
+	SDL_xbiosinterrupt_s.h
diff --git a/src/video/ataricommon/SDL_biosevents.c b/src/video/ataricommon/SDL_biosevents.c
index 85b6e543..2b229da7 100644
--- a/src/video/ataricommon/SDL_biosevents.c
+++ b/src/video/ataricommon/SDL_biosevents.c
@@ -41,7 +41,7 @@ static char rcsid =
 #include "SDL_events_c.h"
 
 #include "SDL_atarikeys.h"
-#include "SDL_xbiosmouseevents_c.h"
+#include "SDL_xbiosevents_c.h"
 
 /* To save state of keyboard */
 #define ATARIBIOS_MAXKEYS 128
@@ -104,7 +104,7 @@ void AtariBios_InitOSKeymap(_THIS)
 	keymap[SCANCODE_LEFTALT] = SDLK_LALT;
 	keymap[SCANCODE_CAPSLOCK] = SDLK_CAPSLOCK;
 
-	AtariXbios_InstallMouseVector();
+	SDL_AtariXbios_InstallVectors(ATARI_XBIOS_MOUSEEVENTS|ATARI_XBIOS_JOYSTICKEVENTS);
 }
 
 void AtariBios_PumpEvents(_THIS)
@@ -142,7 +142,7 @@ void AtariBios_PumpEvents(_THIS)
 			SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey(i, bios_currentascii[i], &keysym));
 	}
 
-	AtariXbios_PostMouseEvents(this);
+	SDL_AtariXbios_PostMouseEvents(this);
 
 	/* Will be previous table */
 	memcpy(bios_previouskeyboard, bios_currentkeyboard, ATARIBIOS_MAXKEYS);
@@ -183,5 +183,5 @@ static SDL_keysym *TranslateKey(int scancode, int asciicode, SDL_keysym *keysym)
 
 void AtariBios_ShutdownEvents(void)
 {
-	AtariXbios_RestoreMouseVector();
+	SDL_AtariXbios_RestoreVectors();
 }
diff --git a/src/video/ataricommon/SDL_gemdosevents.c b/src/video/ataricommon/SDL_gemdosevents.c
index c402e927..95fda1bd 100644
--- a/src/video/ataricommon/SDL_gemdosevents.c
+++ b/src/video/ataricommon/SDL_gemdosevents.c
@@ -41,7 +41,7 @@ static char rcsid =
 #include "SDL_events_c.h"
 
 #include "SDL_atarikeys.h"
-#include "SDL_xbiosmouseevents_c.h"
+#include "SDL_xbiosevents_c.h"
 
 /* To save state of keyboard */
 #define ATARIBIOS_MAXKEYS 128
@@ -109,7 +109,7 @@ void AtariGemdos_InitOSKeymap(_THIS)
 	keymap[SCANCODE_LEFTALT] = SDLK_LALT;
 	keymap[SCANCODE_CAPSLOCK] = SDLK_CAPSLOCK;
 
-	AtariXbios_InstallMouseVector();
+	SDL_AtariXbios_InstallVectors(ATARI_XBIOS_MOUSEEVENTS|ATARI_XBIOS_JOYSTICKEVENTS);
 }
 
 void AtariGemdos_PumpEvents(_THIS)
@@ -147,7 +147,7 @@ void AtariGemdos_PumpEvents(_THIS)
 			SDL_PrivateKeyboard(SDL_RELEASED, TranslateKey(i, gemdos_currentascii[i], &keysym));
 	}
 
-	AtariXbios_PostMouseEvents(this);
+	SDL_AtariXbios_PostMouseEvents(this);
 
 	/* Will be previous table */
 	memcpy(gemdos_previouskeyboard, gemdos_currentkeyboard, ATARIBIOS_MAXKEYS);
@@ -188,5 +188,5 @@ static SDL_keysym *TranslateKey(int scancode, int asciicode, SDL_keysym *keysym)
 
 void AtariGemdos_ShutdownEvents(void)
 {
-	AtariXbios_RestoreMouseVector();
+	SDL_AtariXbios_RestoreVectors();
 }
diff --git a/src/video/ataricommon/SDL_ikbdinterrupt.S b/src/video/ataricommon/SDL_ikbdinterrupt.S
index f3a7cef3..83b77654 100644
--- a/src/video/ataricommon/SDL_ikbdinterrupt.S
+++ b/src/video/ataricommon/SDL_ikbdinterrupt.S
@@ -42,6 +42,8 @@ static char rcsid =
 	.globl	_SDL_AtariIkbd_mousey
 	.globl	_SDL_AtariIkbd_joystick
 
+	.globl	_SDL_AtariIkbd_enabled
+
 /*--- Install our IKBD vector ---*/
 
 _SDL_AtariIkbdInstall:
@@ -72,6 +74,8 @@ _SDL_AtariIkbdInstall:
 
 	| Interrupts done
 
+	movew	#0xffff,_SDL_AtariIkbd_enabled
+
 	moveml	sp@+,d0-d1/a0-a1
 	rts
 
@@ -208,6 +212,9 @@ ikbd_joystick:
 	.data
 	
 	.even
+_SDL_AtariIkbd_enabled:
+	.word	0
+	.even
 	.comm	_SDL_AtariIkbd_keyboard,128
 	.even
 	.comm	_SDL_AtariIkbd_mousex,2*1
diff --git a/src/video/ataricommon/SDL_ikbdinterrupt_s.h b/src/video/ataricommon/SDL_ikbdinterrupt_s.h
index 150df13c..2c7c6938 100644
--- a/src/video/ataricommon/SDL_ikbdinterrupt_s.h
+++ b/src/video/ataricommon/SDL_ikbdinterrupt_s.h
@@ -38,13 +38,25 @@ static char rcsid =
 
 #include "SDL_types.h"
 
+/* Const */
+
+#define IKBD_JOY_UP		(1<<0)
+#define IKBD_JOY_DOWN	(1<<1)
+#define IKBD_JOY_LEFT	(1<<2)
+#define IKBD_JOY_RIGHT	(1<<3)
+#define IKBD_JOY_FIRE	(1<<7)
+
 /* Variables */
 
 extern Uint8  SDL_AtariIkbd_keyboard[128];	/* Keyboard table */
-extern Uint16 SDL_AtariIkbd_mouseb;	/* buttons */
-extern Sint16 SDL_AtariIkbd_mousex;	/* X relative motion */
-extern Sint16 SDL_AtariIkbd_mousey;	/* Y relative motion */
+extern Uint16 SDL_AtariIkbd_mouseb;	/* Mouse on port 0, buttons */
+extern Sint16 SDL_AtariIkbd_mousex;	/* Mouse X relative motion */
+extern Sint16 SDL_AtariIkbd_mousey;	/* Mouse Y relative motion */
+extern Uint16 SDL_AtariIkbd_joystick;	/* Joystick on port 1 */
 
+extern Uint16 SDL_AtariIkbd_enabled;	/* For joystick driver to know
+											if this is usable */
+										
 /* Functions */ 
 
 extern void SDL_AtariIkbdInstall(void);
diff --git a/src/video/ataricommon/SDL_xbiosmouseevents.c b/src/video/ataricommon/SDL_xbiosevents.c
similarity index 78%
rename from src/video/ataricommon/SDL_xbiosmouseevents.c
rename to src/video/ataricommon/SDL_xbiosevents.c
index af80be69..62c2af83 100644
--- a/src/video/ataricommon/SDL_xbiosmouseevents.c
+++ b/src/video/ataricommon/SDL_xbiosevents.c
@@ -26,7 +26,7 @@ static char rcsid =
 #endif
 
 /*
- *	IKBD 6301 mouse vector
+ *	XBIOS mouse & joystick vectors
  *
  *	Patrice Mandin
  */
@@ -36,19 +36,28 @@ static char rcsid =
 #include <mint/osbind.h>
 
 #include "SDL_events_c.h"
-#include "SDL_xbiosmouseinterrupt_s.h"
-
-static _KBDVECS *kbdvecs;		/* Pointer to access vectors */
-static _KBDVECS sys_kbdvecs;	/* Backup of system vectors */
+#include "SDL_xbiosevents_c.h"
+#include "SDL_xbiosinterrupt_s.h"
 
 /* Variables */
 
+int SDL_AtariXbios_enabled=0;
+
+static _KBDVECS *kbdvecs;		/* Pointer to access vectors */
+static _KBDVECS sys_kbdvecs;	/* Backup of system vectors */
 static Uint16 atari_prevmouseb;	/* buttons */
 
-void AtariXbios_InstallMouseVector(void)
+void SDL_AtariXbios_InstallVectors(int vectors_mask)
 {
 	void *oldpile;
 
+	/* Clear variables */
+	SDL_AtariXbios_mouseb =
+		SDL_AtariXbios_mousex =
+		SDL_AtariXbios_mousey =
+		SDL_AtariXbios_joystick =
+		atari_prevmouseb = 0;
+
 	/* Read IKBD vectors base */
 	kbdvecs=Kbdvbase();
 
@@ -59,17 +68,19 @@ void AtariXbios_InstallMouseVector(void)
 	memcpy(&sys_kbdvecs, kbdvecs, sizeof(_KBDVECS));
 
 	/* Install our vector */
-	SDL_AtariXbiosMouseInstall(kbdvecs,SDL_AtariXbiosMouseVector);
+	SDL_AtariXbios_Install(
+		kbdvecs,
+		(vectors_mask & ATARI_XBIOS_MOUSEEVENTS) ? SDL_AtariXbios_MouseVector : NULL,
+		(vectors_mask & ATARI_XBIOS_JOYSTICKEVENTS) ? SDL_AtariXbios_JoystickVector : NULL
+	);
 
 	/* Back to user mode */
 	Super(oldpile);
 
-	/* Clear variables */
-	SDL_AtariXbios_mouseb = SDL_AtariXbios_mousex = SDL_AtariXbios_mousey = 0;
-	atari_prevmouseb = 0;
+	SDL_AtariXbios_enabled=1;
 }
 
-void AtariXbios_RestoreMouseVector(void)
+void SDL_AtariXbios_RestoreVectors(void)
 {
 	void *oldpile;
 
@@ -77,7 +88,7 @@ void AtariXbios_RestoreMouseVector(void)
 	oldpile=(void *)Super(NULL);
 
 	/* Reinstall system vector */
-	SDL_AtariXbiosMouseInstall(kbdvecs,sys_kbdvecs.mousevec);
+	SDL_AtariXbios_Install(kbdvecs,sys_kbdvecs.mousevec,sys_kbdvecs.joyvec);
 
 	/* Back to user mode */
 	Super(oldpile);
@@ -97,7 +108,7 @@ static int atari_GetButton(int button)
 	}
 }
 
-void AtariXbios_PostMouseEvents(_THIS)
+void SDL_AtariXbios_PostMouseEvents(_THIS)
 {
 	/* Mouse motion ? */
 	if (SDL_AtariXbios_mousex || SDL_AtariXbios_mousey) {
diff --git a/src/video/ataricommon/SDL_xbiosmouseevents_c.h b/src/video/ataricommon/SDL_xbiosevents_c.h
similarity index 72%
rename from src/video/ataricommon/SDL_xbiosmouseevents_c.h
rename to src/video/ataricommon/SDL_xbiosevents_c.h
index 6b956239..c15c7c0c 100644
--- a/src/video/ataricommon/SDL_xbiosmouseevents_c.h
+++ b/src/video/ataricommon/SDL_xbiosevents_c.h
@@ -26,21 +26,26 @@ static char rcsid =
 #endif
 
 /*
- *	IKBD 6301 mouse vector
+ *	Xbios mouse & joystick vectors
  *
  *	Patrice Mandin
  */
 
-#ifndef _SDL_XBIOSMOUSEEVENTS_H_
-#define _SDL_XBIOSMOUSEEVENTS_H_
+#ifndef _SDL_ATARI_XBIOSEVENTS_H_
+#define _SDL_ATARI_XBIOSEVENTS_H_
 
 #include "SDL_sysvideo.h"
 
 /* Hidden "this" pointer for the video functions */
 #define _THIS	SDL_VideoDevice *this
 
-extern void AtariXbios_InstallMouseVector(void);
-extern void AtariXbios_RestoreMouseVector(void);
-extern void AtariXbios_PostMouseEvents(_THIS);
+#define ATARI_XBIOS_MOUSEEVENTS (1<<0)
+#define ATARI_XBIOS_JOYSTICKEVENTS (1<<1)
 
-#endif /* _SDL_XBIOSMOUSEEVENTS_H_ */
+extern int SDL_AtariXbios_enabled;
+
+extern void SDL_AtariXbios_InstallVectors(int vectors_mask);
+extern void SDL_AtariXbios_RestoreVectors(void);
+extern void SDL_AtariXbios_PostMouseEvents(_THIS);
+
+#endif /* _SDL_XBIOSEVENTS_H_ */
diff --git a/src/video/ataricommon/SDL_xbiosmouseinterrupt.S b/src/video/ataricommon/SDL_xbiosinterrupt.S
similarity index 63%
rename from src/video/ataricommon/SDL_xbiosmouseinterrupt.S
rename to src/video/ataricommon/SDL_xbiosinterrupt.S
index 3d022f38..6254ad78 100644
--- a/src/video/ataricommon/SDL_xbiosmouseinterrupt.S
+++ b/src/video/ataricommon/SDL_xbiosinterrupt.S
@@ -26,37 +26,46 @@ static char rcsid =
 #endif
 
 /*
- *	IKBD 6301 mouse vector
+ *	XBIOS mouse & joystick vectors
  *
  *	Patrice Mandin
  */
 
 	.text
 
-	.globl	_SDL_AtariXbiosMouseInstall
-	.globl	_SDL_AtariXbiosMouseVector
+	.globl	_SDL_AtariXbios_Install
+	.globl	_SDL_AtariXbios_MouseVector
+	.globl	_SDL_AtariXbios_JoystickVector
 
 	.globl	_SDL_AtariXbios_mouseb
 	.globl	_SDL_AtariXbios_mousex
 	.globl	_SDL_AtariXbios_mousey
+	.globl	_SDL_AtariXbios_joystick
 
 /*--- Vector installer ---*/
 
-_SDL_AtariXbiosMouseInstall:
+_SDL_AtariXbios_Install:
 	movel	sp@(4),a0
-	movel	sp@(8),a1
 
 	/* Stop interrupts */
 
 	movew	#0x2700,sr
 
-	/* Save old vector */
+	/* Save old mouse vector, set our routine */
 
-	movel	a0@(16),oldvector
+	movel	sp@(8),d0
+	beqs	no_new_mouse_vector
+	movel	a0@(16),oldmousevector
+	movel	d0,a0@(16)
+no_new_mouse_vector:
 
-	/* Set our routine */
+	/* Save old joystick vector, set our routine */
 
-	movel	a1,a0@(16)
+	movel	sp@(12),d0
+	beqs	no_new_joystick_vector
+	movel	a0@(24),oldjoystickvector
+	movel	d0,a0@(24)
+no_new_joystick_vector:
 
 	/* Restart interrupts */
 
@@ -70,8 +79,8 @@ _SDL_AtariXbiosMouseInstall:
 	.even
 	.ascii "XBRA"
 	.ascii "LSDL"
-	.comm	oldvector,4*1
-_SDL_AtariXbiosMouseVector:
+	.comm	oldmousevector,4*1
+_SDL_AtariXbios_MouseVector:
 	moveml	d0/a1,sp@-
 
 	/* Mouse buttons */
@@ -90,7 +99,7 @@ _SDL_AtariXbiosMouseVector:
 	addw	d0,_SDL_AtariXbios_mousey
 
 	/* Jump through old vector */
-	movel	oldvector,a1
+	movel	oldmousevector,a1
 	jsr	(a1)
 
 	moveml	sp@+,d0/a1
@@ -104,3 +113,29 @@ _SDL_AtariXbiosMouseVector:
 	.even
 	.comm	_SDL_AtariXbios_mouseb,2*1
 
+/*--- Our joystick vector ---*/
+
+	.text
+	.even
+	.ascii "XBRA"
+	.ascii "LSDL"
+	.comm	oldjoystickvector,4*1
+_SDL_AtariXbios_JoystickVector:
+	moveml	d0/a1,sp@-
+
+	/* New joystick state */
+	moveb	a0@(1),d0
+	andw	#0x8f,d0
+	movew	d0,_SDL_AtariXbios_joystick
+
+	/* Jump through old vector */
+	movel	oldjoystickvector,a1
+	jsr	(a1)
+
+	moveml	sp@+,d0/a1
+	rts
+
+	.data
+	.even
+	.comm	_SDL_AtariXbios_joystick,2*1
+
diff --git a/src/video/ataricommon/SDL_xbiosmouseinterrupt_s.h b/src/video/ataricommon/SDL_xbiosinterrupt_s.h
similarity index 77%
rename from src/video/ataricommon/SDL_xbiosmouseinterrupt_s.h
rename to src/video/ataricommon/SDL_xbiosinterrupt_s.h
index 99a1aab4..d763641d 100644
--- a/src/video/ataricommon/SDL_xbiosmouseinterrupt_s.h
+++ b/src/video/ataricommon/SDL_xbiosinterrupt_s.h
@@ -31,8 +31,8 @@ static char rcsid =
  *	Patrice Mandin
  */
 
-#ifndef _SDL_XBIOSMOUSEEVENTS_S_H_
-#define _SDL_XBIOSMOUSEEVENTS_S_H_
+#ifndef _SDL_XBIOSINTERRUPT_S_H_
+#define _SDL_XBIOSINTERRUPT_S_H_
 
 #include <mint/osbind.h>
 
@@ -43,10 +43,12 @@ static char rcsid =
 extern Uint16 SDL_AtariXbios_mouseb;	/* buttons */
 extern Sint16 SDL_AtariXbios_mousex;	/* X relative motion */
 extern Sint16 SDL_AtariXbios_mousey;	/* Y relative motion */
+extern Uint16 SDL_AtariXbios_joystick;	/* Joystick */
 
 /* Functions */ 
 
-extern void SDL_AtariXbiosMouseInstall(_KBDVECS *kbdvecs,void *newvector);
-extern void SDL_AtariXbiosMouseVector(void *buf);
+extern void SDL_AtariXbios_Install(_KBDVECS *kbdvecs,void *newmousevector,void *newjoystickvector);
+extern void SDL_AtariXbios_MouseVector(void *buf);
+extern void SDL_AtariXbios_JoystickVector(void *buf);
 
-#endif /* _SDL_XBIOSMOUSEEVENTS_S_H_ */
+#endif /* _SDL_XBIOSINTERRUPT_S_H_ */
diff --git a/src/video/gem/SDL_gemvideo.c b/src/video/gem/SDL_gemvideo.c
index f3955a07..4a0e48bc 100644
--- a/src/video/gem/SDL_gemvideo.c
+++ b/src/video/gem/SDL_gemvideo.c
@@ -60,6 +60,7 @@ static char rcsid =
 #include "SDL_gemevents_c.h"
 #include "SDL_gemmouse_c.h"
 #include "SDL_gemwm_c.h"
+#include "SDL_xbiosevents_c.h"
 
 /* Defines */
 
@@ -176,6 +177,9 @@ static SDL_VideoDevice *GEM_CreateDevice(int devindex)
 	device->WarpWMCursor = GEM_WarpWMCursor;
 	device->CheckMouseMode = GEM_CheckMouseMode;
 
+	/* Joystick */
+	SDL_AtariXbios_InstallVectors(ATARI_XBIOS_JOYSTICKEVENTS);
+
 	device->free = GEM_DeleteDevice;
 
 	return device;
@@ -937,6 +941,8 @@ static int GEM_ToggleFullScreen(_THIS, int on)
 */
 void GEM_VideoQuit(_THIS)
 {
+	SDL_AtariXbios_RestoreVectors();
+
 	GEM_FreeBuffers(this);
 
 	if (GEM_locked) {
-- 
2.18.1