From 544fec60044324b815c3d615f0646143cd59383d Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Sun, 7 Jan 2024 12:37:39 +0300 Subject: [PATCH 1/4] ogc: only deliver accelerometer events in axes if the hint is set --- src/joystick/ogc/SDL_sysjoystick.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/joystick/ogc/SDL_sysjoystick.c b/src/joystick/ogc/SDL_sysjoystick.c index e97a5c686f753..3e6b11e24f749 100644 --- a/src/joystick/ogc/SDL_sysjoystick.c +++ b/src/joystick/ogc/SDL_sysjoystick.c @@ -27,6 +27,8 @@ #include "../SDL_sysjoystick.h" #include "../usb_ids.h" #include "SDL_events.h" +#include "SDL_hints.h" +#include "../../SDL_hints_c.h" #include "SDL_joystick.h" #include @@ -186,6 +188,7 @@ static char s_gc_failed_reads = 0; static u32 s_gc_last_scanpads = 0; #ifdef __wii__ static bool s_wii_has_new_data[MAX_WII_JOYSTICKS]; +static bool s_accelerometers_as_axes = false; #endif static bool s_hardware_queried = false; @@ -294,6 +297,13 @@ static void update_rumble(SDL_Joystick *joystick) enable_rumble(joystick->hwdata->index, rumble); } +static void SDLCALL +on_hint_accel_as_joystick_cb(void *userdata, const char *name, + const char *oldValue, const char *hint) +{ + s_accelerometers_as_axes = SDL_GetStringBoolean(hint, SDL_FALSE); +} + /* Function to scan the system for joysticks. * This function should return the number of available * joysticks. Joystick 0 should be the system default joystick. @@ -308,6 +318,9 @@ static int OGC_JoystickInit(void) /* We don't call WPAD_Init() here, since it's already been called by * SDL_main for the Wii */ + SDL_AddHintCallback(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, + on_hint_accel_as_joystick_cb, NULL); + /* Initialize the needed variables */ for (int i = 0; i < MAX_JOYSTICKS; i++) { s_connected_instances[i] = -1; @@ -938,8 +951,10 @@ static void _HandleWiiJoystickUpdate(SDL_Joystick *joystick) prev_state->wiimote.exp = data->exp.type; if (update_wiimote) { - int start_index = split_joysticks ? 0 : 6; - HandleWiiMotion(joystick, prev_state, data, start_index); + if (s_accelerometers_as_axes) { + int start_index = split_joysticks ? 0 : 6; + HandleWiiMotion(joystick, prev_state, data, start_index); + } } } #endif /* __wii__ */ @@ -1043,6 +1058,8 @@ static void OGC_JoystickClose(SDL_Joystick *joystick) void OGC_JoystickQuit(void) { + SDL_DelHintCallback(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, + on_hint_accel_as_joystick_cb, NULL); } static SDL_bool OGC_JoystickGetGamepadMapping(int device_index, From fa3928618878465178b7c6688844c9e5360b38f2 Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Sun, 7 Jan 2024 17:02:17 +0300 Subject: [PATCH 2/4] ogc: use more proper define for WIIMOTE index --- src/joystick/ogc/SDL_sysjoystick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/joystick/ogc/SDL_sysjoystick.c b/src/joystick/ogc/SDL_sysjoystick.c index 3e6b11e24f749..07bb9f357d2a6 100644 --- a/src/joystick/ogc/SDL_sysjoystick.c +++ b/src/joystick/ogc/SDL_sysjoystick.c @@ -537,7 +537,7 @@ static int OGC_JoystickOpen(SDL_Joystick *joystick, int device_index) #ifdef __wii__ } else { if (split_joysticks) { - if (index < MAX_GC_JOYSTICKS + MAX_WII_JOYSTICKS) { + if (index < WII_WIIMOTES_END) { // wiimote joystick->nbuttons = SDL_WII_NUM_BUTTONS_WIIMOTE; joystick->naxes = 3; From 6c35f2676c4703ece273d01c4bc7d5e472d95150 Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Sun, 7 Jan 2024 17:03:40 +0300 Subject: [PATCH 3/4] ogc: report acceleromoter sensor data --- src/joystick/ogc/SDL_sysjoystick.c | 50 ++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/joystick/ogc/SDL_sysjoystick.c b/src/joystick/ogc/SDL_sysjoystick.c index 07bb9f357d2a6..ab84b0f375c8d 100644 --- a/src/joystick/ogc/SDL_sysjoystick.c +++ b/src/joystick/ogc/SDL_sysjoystick.c @@ -101,6 +101,7 @@ typedef struct joystick_wpaddata_t typedef struct joystick_hwdata { int index; + char sensors_disabled; /* This must be big enough for MAX_RUMBLE */ char rumble_intensity; u16 rumble_loop; @@ -542,17 +543,30 @@ static int OGC_JoystickOpen(SDL_Joystick *joystick, int device_index) joystick->nbuttons = SDL_WII_NUM_BUTTONS_WIIMOTE; joystick->naxes = 3; joystick->nhats = 1; + SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 100.0f); } else { // expansion joystick->nbuttons = SDL_max(SDL_WII_NUM_BUTTONS_NUNCHUCK, SDL_WII_NUM_BUTTONS_CLASSIC); joystick->naxes = 6; joystick->nhats = 1; + if (s_detected_devices[index] == 1 + WPAD_EXP_NUNCHUK) { + SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL_L, 100.0f); + } } } else { joystick->nbuttons = MAX_WII_BUTTONS; joystick->naxes = MAX_WII_AXES; joystick->nhats = MAX_WII_HATS; + /* Add the accelerometer only if there is no expansion connected */ + if (s_detected_devices[index] == 1) { + SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 100.0f); + } else if (s_detected_devices[index] == 1 + WPAD_EXP_NUNCHUK) { + /* Or, if the nunchuck is connected, add the wiimote, and the + * nunchuk on the left */ + SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 100.0f); + SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL_L, 100.0f); + } } #endif } @@ -625,6 +639,11 @@ static int OGC_JoystickSendEffect(SDL_Joystick *joystick, static int OGC_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled) { + int index = joystick->hwdata->index; + if (index >= WII_WIIMOTES_START && index < WII_WIIMOTES_END) { + joystick->hwdata->sensors_disabled = !enabled; + return 0; + } return SDL_Unsupported(); } @@ -778,6 +797,34 @@ static void HandleWiiMotion(SDL_Joystick *joystick, } } +static void HandleNunchuckSensors(SDL_Joystick *joystick, + const nunchuk_t *data) +{ + float values[3]; + SDL_SensorType type; + + if (joystick->hwdata->sensors_disabled) return; + + type = split_joysticks ? SDL_SENSOR_ACCEL : SDL_SENSOR_ACCEL_L; + values[0] = data->gforce.x * SDL_STANDARD_GRAVITY; + values[1] = data->gforce.z * SDL_STANDARD_GRAVITY; + values[2] = -data->gforce.y * SDL_STANDARD_GRAVITY; + SDL_PrivateJoystickSensor(joystick, type, 0, values, 3); +} + +static void HandleWiimoteSensors(SDL_Joystick *joystick, + WPADData *data) +{ + float values[3]; + + if (joystick->hwdata->sensors_disabled) return; + + values[0] = data->gforce.x * SDL_STANDARD_GRAVITY; + values[1] = data->gforce.z * SDL_STANDARD_GRAVITY; + values[2] = -data->gforce.y * SDL_STANDARD_GRAVITY; + SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, 0, values, 3); +} + static void _HandleWiiJoystickUpdate(SDL_Joystick *joystick) { u32 changed, pressed; @@ -945,6 +992,8 @@ static void _HandleWiiJoystickUpdate(SDL_Joystick *joystick) SDL_PrivateJoystickAxis(joystick, 1, axis); prev_state->wiimote.nunchuk_stickY = axis; } + + HandleNunchuckSensors(joystick, &data->exp.nunchuk); } } @@ -955,6 +1004,7 @@ static void _HandleWiiJoystickUpdate(SDL_Joystick *joystick) int start_index = split_joysticks ? 0 : 6; HandleWiiMotion(joystick, prev_state, data, start_index); } + HandleWiimoteSensors(joystick, data); } } #endif /* __wii__ */ From 6614775323654db5acc9d8bfcda9b7e89c474a64 Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Sun, 7 Jan 2024 21:12:58 +0300 Subject: [PATCH 4/4] ogc: deliver Wiimote IR events as mouse events --- src/video/ogc/SDL_ogcevents.c | 51 +++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/src/video/ogc/SDL_ogcevents.c b/src/video/ogc/SDL_ogcevents.c index 7540bc9603350..9451576f9b0bc 100644 --- a/src/video/ogc/SDL_ogcevents.c +++ b/src/video/ogc/SDL_ogcevents.c @@ -22,8 +22,7 @@ #ifdef SDL_VIDEO_DRIVER_OGC -/* Being a null driver, there's no event stream. We just define stubs for - most of the API. */ +#include "SDL.h" #include "../../events/SDL_events_c.h" @@ -31,11 +30,55 @@ #include "SDL_ogcvideo.h" #include +#include /* These variables can be set from the handlers registered in SDL_main() */ bool OGC_PowerOffRequested = false; bool OGC_ResetRequested = false; +#ifdef __wii__ +#define MAX_WII_MOUSE_BUTTONS 2 +static const struct { + int wii; + int mouse; +} s_mouse_button_map[MAX_WII_MOUSE_BUTTONS] = { + { WPAD_BUTTON_B, SDL_BUTTON_LEFT }, + { WPAD_BUTTON_A, SDL_BUTTON_RIGHT }, +}; + +static void pump_ir_events(_THIS) +{ + if (!_this->windows) return; + + if (!SDL_WasInit(SDL_INIT_JOYSTICK)) { + /* Get events from WPAD; we don't need to do this if the joystick + * system was initialized, because in that case this operation is done + * there at every event loop iteration. */ + WPAD_ReadPending(WPAD_CHAN_ALL, NULL); + } + + for (int i = 0; i < 4; i++) { + WPADData *data = WPAD_Data(i); + + if (!data->ir.smooth_valid) continue; + + SDL_SendMouseMotion(_this->windows, i, + 0, data->ir.sx, data->ir.sy); + + for (int b = 0; b < MAX_WII_MOUSE_BUTTONS; b++) { + if (data->btns_d & s_mouse_button_map[b].wii) { + SDL_SendMouseButton(_this->windows, i, + SDL_PRESSED, s_mouse_button_map[b].mouse); + } + if (data->btns_u & s_mouse_button_map[b].wii) { + SDL_SendMouseButton(_this->windows, i, + SDL_RELEASED, s_mouse_button_map[b].mouse); + } + } + } +} +#endif + void OGC_PumpEvents(_THIS) { if (OGC_ResetRequested || OGC_PowerOffRequested) { @@ -46,6 +89,10 @@ void OGC_PumpEvents(_THIS) SYS_ResetSystem(SYS_POWEROFF, 0, 0); } } + +#ifdef __wii__ + pump_ir_events(_this); +#endif } #endif /* SDL_VIDEO_DRIVER_OGC */