diff --git a/src/joystick/ogc/SDL_sysjoystick.c b/src/joystick/ogc/SDL_sysjoystick.c index e97a5c686f753..ab84b0f375c8d 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 @@ -99,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; @@ -186,6 +189,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 +298,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 +319,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; @@ -524,22 +538,35 @@ 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; 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 } @@ -612,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(); } @@ -765,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; @@ -932,14 +992,19 @@ static void _HandleWiiJoystickUpdate(SDL_Joystick *joystick) SDL_PrivateJoystickAxis(joystick, 1, axis); prev_state->wiimote.nunchuk_stickY = axis; } + + HandleNunchuckSensors(joystick, &data->exp.nunchuk); } } 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); + } + HandleWiimoteSensors(joystick, data); } } #endif /* __wii__ */ @@ -1043,6 +1108,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, 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 */