Linux/GTK: add support for gamepad touchpad -> touch screen input

translation
This commit is contained in:
thesource 2025-04-19 18:53:43 +03:00 committed by rofl0r
parent 6f1a63fe89
commit 07c444eb0c
5 changed files with 381 additions and 206 deletions

View File

@ -493,7 +493,7 @@ int main(int argc, char ** argv) {
fprintf(stderr, "Warning: X11 not thread-safe\n"); fprintf(stderr, "Warning: X11 not thread-safe\n");
} }
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) == -1) if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK| SDL_INIT_GAMECONTROLLER) == -1)
{ {
fprintf(stderr, "Error trying to initialize SDL: %s\n", fprintf(stderr, "Error trying to initialize SDL: %s\n",
SDL_GetError()); SDL_GetError());

View File

@ -2086,48 +2086,11 @@ static gboolean JoyKeyAcceptTimerFunc(gpointer data)
{ {
if(!in_joy_config_mode) if(!in_joy_config_mode)
return FALSE; return FALSE;
SDL_Event event; struct modify_key_ctx *ctx = (struct modify_key_ctx*)data;
u16 key; bool modified = FALSE;
bool done = FALSE; u16 key=get_joy_key(ctx->key_id, &modified);
while(SDL_PollEvent(&event) && !done) if(modified) {
{
switch(event.type)
{
case SDL_JOYBUTTONDOWN:
key = ((get_joystick_number_by_id(event.jbutton.which) & 15) << 12) | JOY_BUTTON << 8 | (event.jbutton.button & 255);
done = TRUE;
break;
case SDL_JOYAXISMOTION:
if( ((u32)abs(event.jaxis.value) >> 14) != 0 )
{
key = ((get_joystick_number_by_id(event.jaxis.which) & 15) << 12) | JOY_AXIS << 8 | ((event.jaxis.axis & 127) << 1);
if (event.jaxis.value > 0)
key |= 1;
done = TRUE;
}
break;
case SDL_JOYHATMOTION:
if (event.jhat.value != SDL_HAT_CENTERED) {
key = ((get_joystick_number_by_id(event.jhat.which) & 15) << 12) | JOY_HAT << 8 | ((event.jhat.hat & 63) << 2);
if ((event.jhat.value & SDL_HAT_UP) != 0)
key |= JOY_HAT_UP;
else if ((event.jhat.value & SDL_HAT_RIGHT) != 0)
key |= JOY_HAT_RIGHT;
else if ((event.jhat.value & SDL_HAT_DOWN) != 0)
key |= JOY_HAT_DOWN;
else if ((event.jhat.value & SDL_HAT_LEFT) != 0)
key |= JOY_HAT_LEFT;
done = TRUE;
}
break;
default:
do_process_joystick_device_events(&event);
break;
}
}
if(done) {
struct modify_key_ctx *ctx = (struct modify_key_ctx*)data;
ctx->mk_key_chosen = key; ctx->mk_key_chosen = key;
gchar* YouPressed = g_strdup_printf("You pressed : %d\nClick OK to keep this key.", ctx->mk_key_chosen); gchar* YouPressed = g_strdup_printf("You pressed : %d\nClick OK to keep this key.", ctx->mk_key_chosen);
gtk_label_set_text(GTK_LABEL(ctx->label), YouPressed); gtk_label_set_text(GTK_LABEL(ctx->label), YouPressed);
@ -2926,6 +2889,16 @@ gboolean EmuLoop(gpointer data)
process_joystick_events(&keys_latch); process_joystick_events(&keys_latch);
/* Update! */ /* Update! */
update_keypad(keys_latch); update_keypad(keys_latch);
/* Update mouse position and click (source - game controller touchpad)*/
if(touchpad.down) {
NDS_setTouchPos(touchpad.x * 256, touchpad.y * 192);
touchpad.down = 2;
}
if(touchpad.click)
{
NDS_releaseTouch();
touchpad.click = 0;
}
desmume_cycle(); /* Emule ! */ desmume_cycle(); /* Emule ! */
@ -3415,7 +3388,7 @@ common_gtk_main(GApplication *app, gpointer user_data)
/* FIXME: SDL_INIT_VIDEO is needed for joystick support to work!? /* FIXME: SDL_INIT_VIDEO is needed for joystick support to work!?
* Perhaps it needs a "window" to catch events...? */ * Perhaps it needs a "window" to catch events...? */
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,"1"); SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,"1");
if(SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO) == -1) { if(SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO|SDL_INIT_JOYSTICK|SDL_INIT_GAMECONTROLLER) == -1) {
g_printerr("Error trying to initialize SDL: %s\n", g_printerr("Error trying to initialize SDL: %s\n",
SDL_GetError()); SDL_GetError());
// TODO: return a non-zero exit status. // TODO: return a non-zero exit status.

View File

@ -2269,48 +2269,11 @@ static gboolean JoyKeyAcceptTimerFunc(gpointer data)
{ {
if(!in_joy_config_mode) if(!in_joy_config_mode)
return FALSE; return FALSE;
SDL_Event event; struct modify_key_ctx *ctx = (struct modify_key_ctx*)data;
u16 key; bool modified = FALSE;
bool done = FALSE; u16 key=get_joy_key(ctx->key_id, &modified);
while(SDL_PollEvent(&event) && !done) if(modified) {
{
switch(event.type)
{
case SDL_JOYBUTTONDOWN:
key = ((get_joystick_number_by_id(event.jbutton.which) & 15) << 12) | JOY_BUTTON << 8 | (event.jbutton.button & 255);
done = TRUE;
break;
case SDL_JOYAXISMOTION:
if( ((u32)abs(event.jaxis.value) >> 14) != 0 )
{
key = ((get_joystick_number_by_id(event.jaxis.which) & 15) << 12) | JOY_AXIS << 8 | ((event.jaxis.axis & 127) << 1);
if (event.jaxis.value > 0)
key |= 1;
done = TRUE;
}
break;
case SDL_JOYHATMOTION:
if (event.jhat.value != SDL_HAT_CENTERED) {
key = ((get_joystick_number_by_id(event.jhat.which) & 15) << 12) | JOY_HAT << 8 | ((event.jhat.hat & 63) << 2);
if ((event.jhat.value & SDL_HAT_UP) != 0)
key |= JOY_HAT_UP;
else if ((event.jhat.value & SDL_HAT_RIGHT) != 0)
key |= JOY_HAT_RIGHT;
else if ((event.jhat.value & SDL_HAT_DOWN) != 0)
key |= JOY_HAT_DOWN;
else if ((event.jhat.value & SDL_HAT_LEFT) != 0)
key |= JOY_HAT_LEFT;
done = TRUE;
}
break;
default:
do_process_joystick_device_events(&event);
break;
}
}
if(done) {
struct modify_key_ctx *ctx = (struct modify_key_ctx*)data;
ctx->mk_key_chosen = key; ctx->mk_key_chosen = key;
gchar* YouPressed = g_strdup_printf("You pressed : %d\nClick OK to keep this key.", ctx->mk_key_chosen); gchar* YouPressed = g_strdup_printf("You pressed : %d\nClick OK to keep this key.", ctx->mk_key_chosen);
gtk_label_set_text(GTK_LABEL(ctx->label), YouPressed); gtk_label_set_text(GTK_LABEL(ctx->label), YouPressed);
@ -3107,6 +3070,16 @@ gboolean EmuLoop(gpointer data)
process_joystick_events(&keys_latch); process_joystick_events(&keys_latch);
/* Update! */ /* Update! */
update_keypad(keys_latch); update_keypad(keys_latch);
/* Update mouse position and click (source - game controller touchpad)*/
if(touchpad.down) {
NDS_setTouchPos(touchpad.x * 256, touchpad.y * 192);
touchpad.down = 2;
}
if(touchpad.click)
{
NDS_releaseTouch();
touchpad.click = 0;
}
desmume_cycle(); /* Emule ! */ desmume_cycle(); /* Emule ! */
@ -3538,7 +3511,7 @@ common_gtk_main( class configured_features *my_config)
/* FIXME: SDL_INIT_VIDEO is needed for joystick support to work!? /* FIXME: SDL_INIT_VIDEO is needed for joystick support to work!?
* Perhaps it needs a "window" to catch events...? */ * Perhaps it needs a "window" to catch events...? */
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,"1"); SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,"1");
if(SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO) == -1) { if(SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO|SDL_INIT_JOYSTICK|SDL_INIT_GAMECONTROLLER) == -1) {
g_printerr("Error trying to initialize SDL: %s\n", g_printerr("Error trying to initialize SDL: %s\n",
SDL_GetError()); SDL_GetError());
return 1; return 1;

View File

@ -36,10 +36,20 @@ u32 joypad_cfg[NB_KEYS];
static_assert(sizeof(keyboard_cfg) == sizeof(joypad_cfg), ""); static_assert(sizeof(keyboard_cfg) == sizeof(joypad_cfg), "");
mouse_status mouse; mouse_status mouse;
touchpad_status touchpad = {0.0, 0.0, 0, 0};
static int fullscreen; static int fullscreen;
//List of currently connected joysticks (key - instance id, value - SDL_Joystick structure, joystick number) struct JoystickInfo
static std::pair<SDL_Joystick *, SDL_JoystickID> open_joysticks[MAX_JOYSTICKS]; {
bool isController;
union {
SDL_Joystick* joy;
SDL_GameController* gcont;
} handle;
SDL_JoystickID id;
};
static JoystickInfo open_joysticks[MAX_JOYSTICKS];
/* Keypad key names */ /* Keypad key names */
const char *key_names[NB_KEYS] = const char *key_names[NB_KEYS] =
@ -117,26 +127,44 @@ BOOL init_joy( void) {
} }
for(i=0; i<MAX_JOYSTICKS; ++i) for(i=0; i<MAX_JOYSTICKS; ++i)
open_joysticks[i]=std::make_pair((SDL_Joystick*)NULL, 0); open_joysticks[i]={FALSE, {NULL}, -1};
int nbr_joy = std::min(SDL_NumJoysticks(), MAX_JOYSTICKS); int nbr_joy = std::min(SDL_NumJoysticks(), MAX_JOYSTICKS);
if ( nbr_joy > 0) { if ( nbr_joy > 0) {
printf("Found %d joysticks\n", nbr_joy); printf("Found %d joysticks\n", nbr_joy);
for (i = 0; i < nbr_joy; i++) { for (i = 0; i < nbr_joy; i++) {
SDL_Joystick * joy = SDL_JoystickOpen(i); if(SDL_IsGameController(i)) {
if(joy) { SDL_GameController * gcont = SDL_GameControllerOpen(i);
printf("Joystick %d %s\n", i, SDL_JoystickNameForIndex(i)); if(gcont) {
printf("Axes: %d\n", SDL_JoystickNumAxes(joy)); printf("Game controller %d %s\n", i, SDL_GameControllerNameForIndex(i));
printf("Buttons: %d\n", SDL_JoystickNumButtons(joy)); printf("Axes: %d\n", SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(gcont)));
printf("Trackballs: %d\n", SDL_JoystickNumBalls(joy)); printf("Buttons: %d\n", SDL_JoystickNumButtons(SDL_GameControllerGetJoystick(gcont)));
printf("Hats: %d\n\n", SDL_JoystickNumHats(joy)); printf("Touchpads: %d\n", SDL_GameControllerGetNumTouchpads(gcont));
open_joysticks[i]=std::make_pair(joy, SDL_JoystickInstanceID(joy)); printf("%s\n", SDL_GameControllerHasSensor(gcont, SDL_SENSOR_ACCEL) ? "Accelerometer present" : "Accelerometer not present");
printf("%s\n", SDL_GameControllerHasSensor(gcont, SDL_SENSOR_GYRO) ? "Gyroscope present" : "Gyroscope not present");
open_joysticks[i]={TRUE, {.gcont=gcont}, SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gcont))};
}
else {
fprintf(stderr, "Failed to open game controller %d: %s\n", i, SDL_GetError());
joy_init_good = FALSE;
}
} }
else { else {
fprintf(stderr, "Failed to open joystick %d: %s\n", i, SDL_GetError()); SDL_Joystick * joy = SDL_JoystickOpen(i);
joy_init_good = FALSE; if(joy) {
printf("Joystick %d %s\n", i, SDL_JoystickNameForIndex(i));
printf("Axes: %d\n", SDL_JoystickNumAxes(joy));
printf("Buttons: %d\n", SDL_JoystickNumButtons(joy));
printf("Trackballs: %d\n", SDL_JoystickNumBalls(joy));
printf("Hats: %d\n\n", SDL_JoystickNumHats(joy));
open_joysticks[i]={FALSE, {joy}, SDL_JoystickInstanceID(joy)};
}
else {
fprintf(stderr, "Failed to open joystick %d: %s\n", i, SDL_GetError());
joy_init_good = FALSE;
}
} }
} }
} }
@ -149,10 +177,15 @@ void uninit_joy( void)
{ {
int i; int i;
for (i=0; i<MAX_JOYSTICKS; ++i) { for (i=0; i<MAX_JOYSTICKS; ++i) {
if(open_joysticks[i].first) { if(open_joysticks[i].isController) {
SDL_JoystickClose(open_joysticks[i].first); if(open_joysticks[i].handle.gcont)
open_joysticks[i]=std::make_pair((SDL_Joystick*)NULL, 0); SDL_GameControllerClose(open_joysticks[i].handle.gcont);
} }
else {
if(open_joysticks[i].handle.joy)
SDL_JoystickClose(open_joysticks[i].handle.joy);
}
open_joysticks[i]={FALSE, {NULL}, -1};
} }
SDL_QuitSubSystem(SDL_INIT_JOYSTICK); SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
@ -187,70 +220,105 @@ u32 lookup_key (u32 keyval) {
} }
/* Get pressed joystick key */ /* Get pressed joystick key */
u16 get_joy_key(int index) { u16 get_joy_key(int index, bool *modified) {
BOOL done = FALSE; SDL_Event event;
SDL_Event event; u16 key=joypad_cfg[index];
u16 key = joypad_cfg[index]; bool done = FALSE;
int etype=-1, jn;
/* Enable joystick events if needed */ Uint8 bnum, bval;
if( SDL_JoystickEventState(SDL_QUERY) == SDL_IGNORE ) Sint16 aval;
SDL_JoystickEventState(SDL_ENABLE);
if(SDL_JoystickEventState(SDL_QUERY) == SDL_IGNORE)
while(SDL_WaitEvent(&event) && !done) SDL_JoystickEventState(SDL_ENABLE);
if(SDL_GameControllerEventState(SDL_QUERY) == SDL_IGNORE)
SDL_GameControllerEventState(SDL_ENABLE);
while(!done && SDL_PollEvent(&event))
{ {
switch(event.type) switch(event.type)
{ {
case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONDOWN:
printf( "Device: %d; Button: %d\n", event.jbutton.which, event.jbutton.button ); jn=get_joystick_number_by_id(event.jbutton.which);
key = ((get_joystick_number_by_id(event.jbutton.which) & 15) << 12) | JOY_BUTTON << 8 | (event.jbutton.button & 255); if(!open_joysticks[jn].isController)
done = TRUE;
break;
case SDL_JOYAXISMOTION:
/* Dead zone of 50% */
if( ((u32)abs(event.jaxis.value) >> 14) != 0 )
{ {
key = ((get_joystick_number_by_id(event.jaxis.which) & 15) << 12) | JOY_AXIS << 8 | ((event.jaxis.axis & 127) << 1); etype=0;
if (event.jaxis.value > 0) { bnum=event.jbutton.button;
printf( "Device: %d; Axis: %d (+)\n", event.jaxis.which, event.jaxis.axis );
key |= 1;
}
else
printf( "Device: %d; Axis: %d (-)\n", event.jaxis.which, event.jaxis.axis );
done = TRUE;
} }
break; break;
case SDL_CONTROLLERBUTTONDOWN:
jn=get_joystick_number_by_id(event.cbutton.which);
if(open_joysticks[jn].isController)
{
etype=0;
bnum=event.cbutton.button;
}
break;
case SDL_JOYAXISMOTION:
jn=get_joystick_number_by_id(event.jaxis.which);
if(!open_joysticks[jn].isController)
{
etype=1;
bnum=event.jaxis.axis;
aval=event.jaxis.value;
}
break;
case SDL_CONTROLLERAXISMOTION:
jn=get_joystick_number_by_id(event.caxis.which);
if(open_joysticks[jn].isController)
{
etype=1;
bnum=event.caxis.axis;
aval=event.caxis.value;
}
break;
case SDL_JOYHATMOTION: case SDL_JOYHATMOTION:
/* Diagonal positions will be treated as two separate keys being activated, rather than a single diagonal key. */ jn=get_joystick_number_by_id(event.jhat.which);
/* JOY_HAT_* are sequential integers, rather than a bitmask */ if(!open_joysticks[jn].isController)
if (event.jhat.value != SDL_HAT_CENTERED) { {
key = ((get_joystick_number_by_id(event.jhat.which) & 15) << 12) | JOY_HAT << 8 | ((event.jhat.hat & 63) << 2); etype=2;
/* Can't just use a switch here because SDL_HAT_* make up a bitmask. We only want one of these when assigning keys. */ bnum=event.jhat.hat;
if ((event.jhat.value & SDL_HAT_UP) != 0) { bval=event.jhat.value;
key |= JOY_HAT_UP;
printf( "Device: %d; Hat: %d (Up)\n", event.jhat.which, event.jhat.hat );
} }
else if ((event.jhat.value & SDL_HAT_RIGHT) != 0) { break;
key |= JOY_HAT_RIGHT; default:
printf( "Device: %d; Hat: %d (Right)\n", event.jhat.which, event.jhat.hat ); do_process_joystick_device_events(&event);
} break;
else if ((event.jhat.value & SDL_HAT_DOWN) != 0) { }
key |= JOY_HAT_DOWN;
printf( "Device: %d; Hat: %d (Down)\n", event.jhat.which, event.jhat.hat ); switch(etype)
} {
else if ((event.jhat.value & SDL_HAT_LEFT) != 0) { case 0:
key |= JOY_HAT_LEFT; key = ((jn & 15) << 12) | JOY_BUTTON << 8 | (bnum & 255);
printf( "Device: %d; Hat: %d (Left)\n", event.jhat.which, event.jhat.hat ); done = TRUE;
} break;
done = TRUE; case 1:
} if( ((u32)abs(aval) >> 14) != 0 )
break; {
key = ((jn & 15) << 12) | JOY_AXIS << 8 | ((bnum & 127) << 1);
if (aval > 0)
key |= 1;
done = TRUE;
}
break;
case 2:
if (bval != SDL_HAT_CENTERED) {
key = ((jn & 15) << 12) | JOY_HAT << 8 | ((bnum & 63) << 2);
if ((bval & SDL_HAT_UP) != 0)
key |= JOY_HAT_UP;
else if ((bval & SDL_HAT_RIGHT) != 0)
key |= JOY_HAT_RIGHT;
else if ((bval & SDL_HAT_DOWN) != 0)
key |= JOY_HAT_DOWN;
else if ((bval & SDL_HAT_LEFT) != 0)
key |= JOY_HAT_LEFT;
done = TRUE;
}
break;
} }
} }
if(modified)
if( SDL_JoystickEventState(SDL_QUERY) == SDL_ENABLE ) (*modified)=done;
SDL_JoystickEventState(SDL_IGNORE); return key;
return key;
} }
/* Get and set a new joystick key */ /* Get and set a new joystick key */
@ -372,16 +440,126 @@ do_process_joystick_events( u16 *keypad, SDL_Event *event) {
u16 key_r; u16 key_r;
u16 key_d; u16 key_d;
u16 key_l; u16 key_l;
int jn, etype=-1;
Sint16 aval;
Uint8 bnum, bval;
switch ( event->type) switch ( event->type)
{ {
/* Joystick axis motion
Note: button constants have a 1bit offset. */
case SDL_JOYAXISMOTION: case SDL_JOYAXISMOTION:
key_code = ((get_joystick_number_by_id(event->jaxis.which) & 15) << 12) | JOY_AXIS << 8 | ((event->jaxis.axis & 127) << 1); jn=get_joystick_number_by_id(event->jaxis.which);
if( ((u32)abs(event->jaxis.value) >> 14) != 0 ) if(!open_joysticks[jn].isController)
{
etype=0;
bnum=event->jaxis.axis;
aval=event->jaxis.value;
}
break;
case SDL_JOYHATMOTION:
jn=get_joystick_number_by_id(event->jhat.which);
if(!open_joysticks[jn].isController)
{
etype=1;
bnum=event->jhat.hat;
bval=event->jhat.value;
}
break;
case SDL_JOYBUTTONDOWN:
jn=get_joystick_number_by_id(event->jbutton.which);
if(!open_joysticks[jn].isController)
{
etype=2;
bnum=event->jbutton.button;
}
break;
case SDL_JOYBUTTONUP:
jn=get_joystick_number_by_id(event->jbutton.which);
if(!open_joysticks[jn].isController)
{
etype=3;
bnum=event->jbutton.button;
}
break;
case SDL_CONTROLLERAXISMOTION:
jn=get_joystick_number_by_id(event->caxis.which);
if(open_joysticks[jn].isController)
{
etype=0;
bnum=event->caxis.axis;
aval=event->caxis.value;
}
break;
case SDL_CONTROLLERBUTTONDOWN:
jn=get_joystick_number_by_id(event->cbutton.which);
if(open_joysticks[jn].isController)
{
etype=2;
bnum=event->cbutton.button;
}
break;
case SDL_CONTROLLERBUTTONUP:
jn=get_joystick_number_by_id(event->cbutton.which);
if(open_joysticks[jn].isController)
{
etype=3;
bnum=event->cbutton.button;
}
break;
case SDL_CONTROLLERTOUCHPADDOWN:
jn=get_joystick_number_by_id(event->ctouchpad.which);
if(open_joysticks[jn].isController)
{
if(event->ctouchpad.finger==0)
if(!touchpad.down)
touchpad.down=1;
}
break;
case SDL_CONTROLLERTOUCHPADMOTION:
jn=get_joystick_number_by_id(event->ctouchpad.which);
if(open_joysticks[jn].isController)
if(event->ctouchpad.finger==0)
{ {
if (event->jaxis.value > 0) touchpad.x=event->ctouchpad.x;
touchpad.y=event->ctouchpad.y;
}
break;
case SDL_CONTROLLERTOUCHPADUP:
jn=get_joystick_number_by_id(event->ctouchpad.which);
if(open_joysticks[jn].isController)
{
if(event->ctouchpad.finger==0)
if(touchpad.down)
{
touchpad.click = 1;
if(touchpad.down > 1) touchpad.down = 0;
}
}
break;
default:
processed = 0;
break;
}
switch(etype)
{
/* Joystick axis motion
Note: button constants have a 1bit offset. */
case 0:
key_code = ((jn & 15) << 12) | JOY_AXIS << 8 | ((bnum & 127) << 1);
if( ((u32)abs(aval) >> 14) != 0 )
{
if (aval > 0)
key_code |= 1; key_code |= 1;
key = lookup_joy_key( key_code ); key = lookup_joy_key( key_code );
key_o = lookup_joy_key( key_code ^ 1 ); key_o = lookup_joy_key( key_code ^ 1 );
@ -401,53 +579,49 @@ do_process_joystick_events( u16 *keypad, SDL_Event *event) {
RM_KEY( *keypad, key_o ); RM_KEY( *keypad, key_o );
} }
break; break;
case SDL_JOYHATMOTION: /* Diagonal positions will be treated as two separate keys being activated, rather than a single diagonal key. */
/* Diagonal positions will be treated as two separate keys being activated, rather than a single diagonal key. */ /* JOY_HAT_* are sequential integers, rather than a bitmask */
/* JOY_HAT_* are sequential integers, rather than a bitmask */ case 1:
key_code = ((get_joystick_number_by_id(event->jhat.which) & 15) << 12) | JOY_HAT << 8 | ((event->jhat.hat & 63) << 2); key_code = ((jn & 15) << 12) | JOY_HAT << 8 | ((bnum & 63) << 2);
key_u = lookup_joy_key( key_code | JOY_HAT_UP ); key_u = lookup_joy_key( key_code | JOY_HAT_UP );
key_r = lookup_joy_key( key_code | JOY_HAT_RIGHT ); key_r = lookup_joy_key( key_code | JOY_HAT_RIGHT );
key_d = lookup_joy_key( key_code | JOY_HAT_DOWN ); key_d = lookup_joy_key( key_code | JOY_HAT_DOWN );
key_l = lookup_joy_key( key_code | JOY_HAT_LEFT ); key_l = lookup_joy_key( key_code | JOY_HAT_LEFT );
if ((key_u != 0) && ((event->jhat.value & SDL_HAT_UP) != 0)) if ((key_u != 0) && ((bval & SDL_HAT_UP) != 0))
ADD_KEY( *keypad, key_u ); ADD_KEY( *keypad, key_u );
else if (key_u != 0) else if (key_u != 0)
RM_KEY( *keypad, key_u ); RM_KEY( *keypad, key_u );
if ((key_r != 0) && ((event->jhat.value & SDL_HAT_RIGHT) != 0)) if ((key_r != 0) && ((bval & SDL_HAT_RIGHT) != 0))
ADD_KEY( *keypad, key_r ); ADD_KEY( *keypad, key_r );
else if (key_r != 0) else if (key_r != 0)
RM_KEY( *keypad, key_r ); RM_KEY( *keypad, key_r );
if ((key_d != 0) && ((event->jhat.value & SDL_HAT_DOWN) != 0)) if ((key_d != 0) && ((bval & SDL_HAT_DOWN) != 0))
ADD_KEY( *keypad, key_d ); ADD_KEY( *keypad, key_d );
else if (key_d != 0) else if (key_d != 0)
RM_KEY( *keypad, key_d ); RM_KEY( *keypad, key_d );
if ((key_l != 0) && ((event->jhat.value & SDL_HAT_LEFT) != 0)) if ((key_l != 0) && ((bval & SDL_HAT_LEFT) != 0))
ADD_KEY( *keypad, key_l ); ADD_KEY( *keypad, key_l );
else if (key_l != 0) else if (key_l != 0)
RM_KEY( *keypad, key_l ); RM_KEY( *keypad, key_l );
break; break;
/* Joystick button pressed */ /* Joystick button pressed */
case SDL_JOYBUTTONDOWN: case 2:
key_code = ((get_joystick_number_by_id(event->jbutton.which) & 15) << 12) | JOY_BUTTON << 8 | (event->jbutton.button & 255); key_code = ((jn & 15) << 12) | JOY_BUTTON << 8 | (bnum & 255);
key = lookup_joy_key( key_code ); key = lookup_joy_key( key_code );
if (key != 0) if (key != 0)
ADD_KEY( *keypad, key ); ADD_KEY( *keypad, key );
break; break;
/* Joystick button released */ /* Joystick button released */
case SDL_JOYBUTTONUP: case 3:
key_code = ((get_joystick_number_by_id(event->jbutton.which) & 15) << 12) | JOY_BUTTON << 8 | (event->jbutton.button & 255); key_code = ((jn & 15) << 12) | JOY_BUTTON << 8 | (bnum & 255);
key = lookup_joy_key( key_code ); key = lookup_joy_key( key_code );
if (key != 0) if (key != 0)
RM_KEY( *keypad, key ); RM_KEY( *keypad, key );
break; break;
}
default:
processed = 0;
break;
}
return processed; return processed;
} }
@ -464,28 +638,32 @@ do_process_joystick_device_events(SDL_Event* event) {
case SDL_JOYDEVICEREMOVED: case SDL_JOYDEVICEREMOVED:
n=get_joystick_number_by_id(event->jdevice.which); n=get_joystick_number_by_id(event->jdevice.which);
if(n != -1) { if(n != -1) {
printf("Joystick %d disconnected\n", n); if(!open_joysticks[n].isController) {
SDL_JoystickClose(open_joysticks[n].first); printf("Joystick %d disconnected\n", n);
open_joysticks[n]=std::make_pair((SDL_Joystick*)NULL, 0); SDL_JoystickClose(open_joysticks[n].handle.joy);
open_joysticks[n]={FALSE, {NULL}, -1};
}
} }
break; break;
/* Joystick connected */ /* Joystick connected */
case SDL_JOYDEVICEADDED: case SDL_JOYDEVICEADDED:
if(event->jdevice.which<MAX_JOYSTICKS) { if(event->jdevice.which<MAX_JOYSTICKS) {
//Filter connect events for joysticks already initialized in init_joy if(!SDL_IsGameController(event->jdevice.which)) {
if(!open_joysticks[event->jdevice.which].first) { //Filter connect events for joysticks already initialized in init_joy
SDL_Joystick* joy = SDL_JoystickOpen(event->jdevice.which); if(!open_joysticks[event->jdevice.which].handle.joy) {
if(joy) { SDL_Joystick* joy = SDL_JoystickOpen(event->jdevice.which);
printf("Joystick %d %s\n", event->jdevice.which, SDL_JoystickNameForIndex(event->jdevice.which)); if(joy) {
printf("Axes: %d\n", SDL_JoystickNumAxes(joy)); printf("Joystick %d %s\n", event->jdevice.which, SDL_JoystickNameForIndex(event->jdevice.which));
printf("Buttons: %d\n", SDL_JoystickNumButtons(joy)); printf("Axes: %d\n", SDL_JoystickNumAxes(joy));
printf("Trackballs: %d\n", SDL_JoystickNumBalls(joy)); printf("Buttons: %d\n", SDL_JoystickNumButtons(joy));
printf("Hats: %d\n\n", SDL_JoystickNumHats(joy)); printf("Trackballs: %d\n", SDL_JoystickNumBalls(joy));
open_joysticks[event->jdevice.which]=std::make_pair(joy, SDL_JoystickInstanceID(joy)); printf("Hats: %d\n\n", SDL_JoystickNumHats(joy));
open_joysticks[event->jdevice.which]={FALSE, {joy}, SDL_JoystickInstanceID(joy)};
}
else
fprintf(stderr, "Failed to open joystick %d: %s\n", event->jdevice.which, SDL_GetError());
} }
else
fprintf(stderr, "Failed to open joystick %d: %s\n", event->jdevice.which, SDL_GetError());
} }
} }
else else
@ -493,6 +671,44 @@ do_process_joystick_device_events(SDL_Event* event) {
event->jdevice.which, MAX_JOYSTICKS-1); event->jdevice.which, MAX_JOYSTICKS-1);
break; break;
/* Game controller disconnected */
case SDL_CONTROLLERDEVICEREMOVED:
n=get_joystick_number_by_id(event->cdevice.which);
if(n != -1) {
if(open_joysticks[n].isController) {
printf("Game controller %d disconnected\n", n);
SDL_GameControllerClose(open_joysticks[n].handle.gcont);
open_joysticks[n]={FALSE, {NULL}, -1};
}
}
break;
/* Game controller connected */
case SDL_CONTROLLERDEVICEADDED:
if(event->cdevice.which<MAX_JOYSTICKS) {
if(SDL_IsGameController(event->cdevice.which)) {
//Filter connect events for joysticks already initialized in init_joy
if(!open_joysticks[event->cdevice.which].handle.gcont) {
SDL_GameController* gcont = SDL_GameControllerOpen(event->cdevice.which);
if(gcont) {
printf("Game controller %d %s\n", event->cdevice.which, SDL_GameControllerNameForIndex(event->cdevice.which));
printf("Axes: %d\n", SDL_JoystickNumAxes(SDL_GameControllerGetJoystick(gcont)));
printf("Buttons: %d\n", SDL_JoystickNumButtons(SDL_GameControllerGetJoystick(gcont)));
printf("Touchpads: %d\n", SDL_GameControllerGetNumTouchpads(gcont));
printf("%s\n", SDL_GameControllerHasSensor(gcont, SDL_SENSOR_ACCEL) ? "Accelerometer present" : "Accelerometer not present");
printf("%s\n", SDL_GameControllerHasSensor(gcont, SDL_SENSOR_GYRO) ? "Gyroscope present" : "Gyroscope not present");
open_joysticks[event->cdevice.which]={TRUE, {.gcont=gcont}, SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(gcont))};
}
else
fprintf(stderr, "Failed to open game controller %d: %s\n", event->cdevice.which, SDL_GetError());
}
}
}
else
printf("Game controller %d connected to the system, but maximum supported joystick index is %d, ignoring\n",
event->cdevice.which, MAX_JOYSTICKS-1);
break;
default: default:
processed = 0; processed = 0;
break; break;
@ -510,7 +726,9 @@ process_joystick_events( u16 *keypad) {
/* IMPORTANT: Reenable joystick events if needed. */ /* IMPORTANT: Reenable joystick events if needed. */
if(SDL_JoystickEventState(SDL_QUERY) == SDL_IGNORE) if(SDL_JoystickEventState(SDL_QUERY) == SDL_IGNORE)
SDL_JoystickEventState(SDL_ENABLE); SDL_JoystickEventState(SDL_ENABLE);
if(SDL_GameControllerEventState(SDL_QUERY) == SDL_IGNORE)
SDL_GameControllerEventState(SDL_ENABLE);
/* There's an event waiting to be processed? */ /* There's an event waiting to be processed? */
while (SDL_PollEvent(&event)) while (SDL_PollEvent(&event))
{ {
@ -528,6 +746,8 @@ void process_joystick_device_events() {
/* IMPORTANT: Reenable joystick events if needed. */ /* IMPORTANT: Reenable joystick events if needed. */
if(SDL_JoystickEventState(SDL_QUERY) == SDL_IGNORE) if(SDL_JoystickEventState(SDL_QUERY) == SDL_IGNORE)
SDL_JoystickEventState(SDL_ENABLE); SDL_JoystickEventState(SDL_ENABLE);
if(SDL_GameControllerEventState(SDL_QUERY) == SDL_IGNORE)
SDL_GameControllerEventState(SDL_ENABLE);
/* There's an event waiting to be processed? */ /* There's an event waiting to be processed? */
while (SDL_PollEvent(&event)) while (SDL_PollEvent(&event))
@ -538,8 +758,7 @@ int get_joystick_number_by_id(SDL_JoystickID id)
{ {
int i; int i;
for(i=0; i<MAX_JOYSTICKS; ++i) for(i=0; i<MAX_JOYSTICKS; ++i)
if(open_joysticks[i].first) if(open_joysticks[i].id==id)
if(open_joysticks[i].second==id)
return i; return i;
return -1; return -1;
} }
@ -548,7 +767,7 @@ int get_number_of_joysticks()
{ {
int i, n=0; int i, n=0;
for(i=0; i<MAX_JOYSTICKS; ++i) for(i=0; i<MAX_JOYSTICKS; ++i)
if(open_joysticks[i].first) if(open_joysticks[i].id>=0)
++n; ++n;
return n; return n;
} }

View File

@ -82,6 +82,16 @@ struct mouse_status
extern mouse_status mouse; extern mouse_status mouse;
#endif // !GTK_UI #endif // !GTK_UI
struct touchpad_status
{
float x;
float y;
int down;
int click;
};
extern touchpad_status touchpad;
struct ctrls_event_config { struct ctrls_event_config {
unsigned short keypad; unsigned short keypad;
float nds_screen_size_ratio; float nds_screen_size_ratio;
@ -98,7 +108,7 @@ struct ctrls_event_config {
void load_default_config(const u32 kbCfg[]); void load_default_config(const u32 kbCfg[]);
BOOL init_joy( void); BOOL init_joy( void);
void uninit_joy( void); void uninit_joy( void);
u16 get_joy_key(int index); u16 get_joy_key(int index, bool* modified=NULL);
u16 get_set_joy_key(int index); u16 get_set_joy_key(int index);
void update_keypad(u16 keys); void update_keypad(u16 keys);
u16 get_keypad( void); u16 get_keypad( void);