video: Add support for SDL joysticks and game controllers.
This commit is contained in:
parent
05e4babe24
commit
72b89054da
2 changed files with 187 additions and 0 deletions
184
sim_video.c
184
sim_video.c
|
@ -37,6 +37,10 @@ t_bool vid_mouse_b1 = FALSE;
|
||||||
t_bool vid_mouse_b2 = FALSE;
|
t_bool vid_mouse_b2 = FALSE;
|
||||||
t_bool vid_mouse_b3 = FALSE;
|
t_bool vid_mouse_b3 = FALSE;
|
||||||
static VID_QUIT_CALLBACK vid_quit_callback = NULL;
|
static VID_QUIT_CALLBACK vid_quit_callback = NULL;
|
||||||
|
static VID_GAMEPAD_CALLBACK motion_callback[10];
|
||||||
|
static VID_GAMEPAD_CALLBACK button_callback[10];
|
||||||
|
static int vid_gamepad_inited = 0;
|
||||||
|
static int vid_gamepad_ok = 0; /* Or else just joysticks. */
|
||||||
|
|
||||||
t_stat vid_register_quit_callback (VID_QUIT_CALLBACK callback)
|
t_stat vid_register_quit_callback (VID_QUIT_CALLBACK callback)
|
||||||
{
|
{
|
||||||
|
@ -44,6 +48,41 @@ vid_quit_callback = callback;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static t_stat register_callback (void **array, int n, void *callback)
|
||||||
|
{
|
||||||
|
int i, j = -1;
|
||||||
|
|
||||||
|
if (!vid_gamepad_inited) {
|
||||||
|
return SCPE_NOATT;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (array[i] == callback)
|
||||||
|
return SCPE_ALATT;
|
||||||
|
if (array[i] == NULL)
|
||||||
|
j = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j != -1) {
|
||||||
|
array[j] = callback;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SCPE_NXM;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat vid_register_gamepad_motion_callback (VID_GAMEPAD_CALLBACK callback)
|
||||||
|
{
|
||||||
|
int n = sizeof (motion_callback) / sizeof (callback);
|
||||||
|
return register_callback ((void **)motion_callback, n, (void *)callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat vid_register_gamepad_button_callback (VID_GAMEPAD_CALLBACK callback)
|
||||||
|
{
|
||||||
|
int n = sizeof (button_callback) / sizeof (callback);
|
||||||
|
return register_callback ((void **)button_callback, n, (void *)callback);
|
||||||
|
}
|
||||||
|
|
||||||
t_stat vid_show (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char* desc)
|
t_stat vid_show (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char* desc)
|
||||||
{
|
{
|
||||||
return vid_show_video (st, uptr, val, desc);
|
return vid_show_video (st, uptr, val, desc);
|
||||||
|
@ -510,6 +549,64 @@ return SCPE_OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static t_stat vid_init_controllers (void)
|
||||||
|
{
|
||||||
|
SDL_Joystick *y;
|
||||||
|
SDL_version ver;
|
||||||
|
int i, n;
|
||||||
|
|
||||||
|
if (vid_gamepad_inited)
|
||||||
|
return SCPE_OK;
|
||||||
|
|
||||||
|
/* Chech that the SDL_GameControllerFromInstanceID function is
|
||||||
|
available at run time. */
|
||||||
|
SDL_GetVersion(&ver);
|
||||||
|
vid_gamepad_ok = (ver.major > 2 ||
|
||||||
|
(ver.major == 2 && (ver.minor > 0 || ver.patch >= 4)));
|
||||||
|
|
||||||
|
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
|
||||||
|
if (vid_gamepad_ok)
|
||||||
|
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||||
|
|
||||||
|
if (SDL_JoystickEventState (SDL_ENABLE) < 0) {
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||||
|
return SCPE_IOERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vid_gamepad_ok && SDL_GameControllerEventState (SDL_ENABLE) < 0) {
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||||
|
return SCPE_IOERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = SDL_NumJoysticks();
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (vid_gamepad_ok && SDL_IsGameController (i)) {
|
||||||
|
SDL_GameController *x = SDL_GameControllerOpen (i);
|
||||||
|
if (x != NULL) {
|
||||||
|
sim_debug (SIM_VID_DBG_VIDEO, vid_dev,
|
||||||
|
"Game controller: %s\n", SDL_GameControllerNameForIndex(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
y = SDL_JoystickOpen (i);
|
||||||
|
if (y != NULL) {
|
||||||
|
sim_debug (SIM_VID_DBG_VIDEO, vid_dev,
|
||||||
|
"Joystick: %s\n", SDL_JoystickNameForIndex(i));
|
||||||
|
sim_debug (SIM_VID_DBG_VIDEO, vid_dev,
|
||||||
|
"Number of axes: %d, buttons: %d\n",
|
||||||
|
SDL_JoystickNumAxes(y),
|
||||||
|
SDL_JoystickNumButtons(y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vid_gamepad_inited = 1;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
t_stat vid_open (DEVICE *dptr, const char *title, uint32 width, uint32 height, int flags)
|
t_stat vid_open (DEVICE *dptr, const char *title, uint32 width, uint32 height, int flags)
|
||||||
{
|
{
|
||||||
if (!vid_active) {
|
if (!vid_active) {
|
||||||
|
@ -538,10 +635,18 @@ if (!vid_active) {
|
||||||
|
|
||||||
vid_dev = dptr;
|
vid_dev = dptr;
|
||||||
|
|
||||||
|
memset (motion_callback, 0, sizeof motion_callback);
|
||||||
|
memset (button_callback, 0, sizeof button_callback);
|
||||||
|
|
||||||
stat = vid_create_window ();
|
stat = vid_create_window ();
|
||||||
if (stat != SCPE_OK)
|
if (stat != SCPE_OK)
|
||||||
return stat;
|
return stat;
|
||||||
|
|
||||||
|
if (vid_init_controllers () != SCPE_OK) {
|
||||||
|
sim_debug (SIM_VID_DBG_VIDEO, vid_dev,
|
||||||
|
"vid_open() - Failed initializing game controllers\n");
|
||||||
|
}
|
||||||
|
|
||||||
sim_debug (SIM_VID_DBG_VIDEO|SIM_VID_DBG_KEY|SIM_VID_DBG_MOUSE, vid_dev, "vid_open() - Success\n");
|
sim_debug (SIM_VID_DBG_VIDEO|SIM_VID_DBG_KEY|SIM_VID_DBG_MOUSE, vid_dev, "vid_open() - Success\n");
|
||||||
}
|
}
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -553,6 +658,12 @@ if (vid_active) {
|
||||||
SDL_Event user_event;
|
SDL_Event user_event;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
|
vid_gamepad_inited = 0;
|
||||||
|
memset (motion_callback, 0, sizeof motion_callback);
|
||||||
|
memset (button_callback, 0, sizeof button_callback);
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||||
|
|
||||||
vid_active = FALSE;
|
vid_active = FALSE;
|
||||||
if (vid_ready) {
|
if (vid_ready) {
|
||||||
sim_debug (SIM_VID_DBG_VIDEO|SIM_VID_DBG_KEY|SIM_VID_DBG_MOUSE, vid_dev, "vid_close()\n");
|
sim_debug (SIM_VID_DBG_VIDEO|SIM_VID_DBG_KEY|SIM_VID_DBG_MOUSE, vid_dev, "vid_close()\n");
|
||||||
|
@ -1149,6 +1260,60 @@ switch (key) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vid_joy_motion (SDL_JoyAxisEvent *event)
|
||||||
|
{
|
||||||
|
int n = sizeof motion_callback / sizeof (VID_GAMEPAD_CALLBACK);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (motion_callback[i]) {
|
||||||
|
motion_callback[i](event->which, event->axis, event->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vid_joy_button (SDL_JoyButtonEvent *event)
|
||||||
|
{
|
||||||
|
int n = sizeof button_callback / sizeof (VID_GAMEPAD_CALLBACK);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (button_callback[i]) {
|
||||||
|
button_callback[i](event->which, event->button, event->state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void vid_controller_motion (SDL_ControllerAxisEvent *event)
|
||||||
|
{
|
||||||
|
SDL_JoyAxisEvent e;
|
||||||
|
e.which = event->which;
|
||||||
|
e.axis = event->axis;
|
||||||
|
e.value = event->value;
|
||||||
|
vid_joy_motion (&e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vid_controller_button (SDL_ControllerButtonEvent *event)
|
||||||
|
{
|
||||||
|
/* SDL_GameControllerFromInstanceID is only available from SDL
|
||||||
|
version 2.0.4, so check the version at compile time. The
|
||||||
|
version is also checked at run time. */
|
||||||
|
#if (SDL_MAJOR_VERSION > 2) || (SDL_MAJOR_VERSION == 2 && \
|
||||||
|
(SDL_MINOR_VERSION > 0) || (SDL_PATCHLEVEL >= 4))
|
||||||
|
|
||||||
|
SDL_JoyButtonEvent e;
|
||||||
|
SDL_GameControllerButtonBind b;
|
||||||
|
SDL_GameController *c;
|
||||||
|
|
||||||
|
c = SDL_GameControllerFromInstanceID (event->which);
|
||||||
|
b = SDL_GameControllerGetBindForButton (c, event->button);
|
||||||
|
e.which = event->which;
|
||||||
|
e.button = b.value.button;
|
||||||
|
e.state = event->state;
|
||||||
|
vid_joy_button (&e);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void vid_key (SDL_KeyboardEvent *event)
|
void vid_key (SDL_KeyboardEvent *event)
|
||||||
{
|
{
|
||||||
SIM_KEY_EVENT ev;
|
SIM_KEY_EVENT ev;
|
||||||
|
@ -1702,6 +1867,25 @@ while (vid_active) {
|
||||||
case SDL_MOUSEMOTION:
|
case SDL_MOUSEMOTION:
|
||||||
vid_mouse_move (&event.motion);
|
vid_mouse_move (&event.motion);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SDL_JOYAXISMOTION:
|
||||||
|
vid_joy_motion (&event.jaxis);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_JOYBUTTONUP:
|
||||||
|
case SDL_JOYBUTTONDOWN:
|
||||||
|
vid_joy_button (&event.jbutton);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_CONTROLLERAXISMOTION:
|
||||||
|
vid_controller_motion (&event.caxis);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SDL_CONTROLLERBUTTONUP:
|
||||||
|
case SDL_CONTROLLERBUTTONDOWN:
|
||||||
|
vid_controller_button (&event.cbutton);
|
||||||
|
break;
|
||||||
|
|
||||||
#if SDL_MAJOR_VERSION != 1
|
#if SDL_MAJOR_VERSION != 1
|
||||||
case SDL_WINDOWEVENT:
|
case SDL_WINDOWEVENT:
|
||||||
if (event.window.windowID == vid_windowID) {
|
if (event.window.windowID == vid_windowID) {
|
||||||
|
|
|
@ -180,6 +180,9 @@ t_stat vid_open (DEVICE *dptr, const char *title, uint32 width, uint32 height, i
|
||||||
/* code responsible for cursor display in video) */
|
/* code responsible for cursor display in video) */
|
||||||
typedef void (*VID_QUIT_CALLBACK)(void);
|
typedef void (*VID_QUIT_CALLBACK)(void);
|
||||||
t_stat vid_register_quit_callback (VID_QUIT_CALLBACK callback);
|
t_stat vid_register_quit_callback (VID_QUIT_CALLBACK callback);
|
||||||
|
typedef void (*VID_GAMEPAD_CALLBACK)(int, int, int);
|
||||||
|
t_stat vid_register_gamepad_motion_callback (VID_GAMEPAD_CALLBACK);
|
||||||
|
t_stat vid_register_gamepad_button_callback (VID_GAMEPAD_CALLBACK);
|
||||||
t_stat vid_close (void);
|
t_stat vid_close (void);
|
||||||
t_stat vid_poll_kb (SIM_KEY_EVENT *ev);
|
t_stat vid_poll_kb (SIM_KEY_EVENT *ev);
|
||||||
t_stat vid_poll_mouse (SIM_MOUSE_EVENT *ev);
|
t_stat vid_poll_mouse (SIM_MOUSE_EVENT *ev);
|
||||||
|
|
Loading…
Add table
Reference in a new issue