diff --git a/CMakeLists.txt b/CMakeLists.txt index dd131af5c..badb86182 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2783,6 +2783,13 @@ elseif(N3DS) set(HAVE_SDL_TIMERS TRUE) endif() + if(SDL_SENSOR) + set(SDL_SENSOR_N3DS 1) + file(GLOB N3DS_SENSOR_SOURCES ${SDL2_SOURCE_DIR}/src/sensor/n3ds/*.c) + list(APPEND SOURCE_FILES ${N3DS_SENSOR_SOURCES}) + set(HAVE_SDL_SENSORS TRUE) + endif() + if(SDL_VIDEO) set(SDL_VIDEO_DRIVER_N3DS 1) file(GLOB N3DS_VIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/n3ds/*.c) diff --git a/include/SDL_config.h.cmake b/include/SDL_config.h.cmake index 6dc89a4a3..6daeadfa0 100644 --- a/include/SDL_config.h.cmake +++ b/include/SDL_config.h.cmake @@ -365,6 +365,7 @@ #cmakedefine SDL_SENSOR_WINDOWS @SDL_SENSOR_WINDOWS@ #cmakedefine SDL_SENSOR_DUMMY @SDL_SENSOR_DUMMY@ #cmakedefine SDL_SENSOR_VITA @SDL_SENSOR_VITA@ +#cmakedefine SDL_SENSOR_N3DS @SDL_SENSOR_N3DS@ /* Enable various shared object loading systems */ #cmakedefine SDL_LOADSO_DLOPEN @SDL_LOADSO_DLOPEN@ diff --git a/src/joystick/n3ds/SDL_sysjoystick.c b/src/joystick/n3ds/SDL_sysjoystick.c index 3f2d5a262..1b98462ad 100644 --- a/src/joystick/n3ds/SDL_sysjoystick.c +++ b/src/joystick/n3ds/SDL_sysjoystick.c @@ -51,23 +51,17 @@ typedef struct N3DSJoystickState u32 kUp; circlePosition circlePos; circlePosition cStickPos; - accelVector acceleration; - angularRate rate; } N3DSJoystickState; SDL_FORCE_INLINE void UpdateAxis(SDL_Joystick *joystick, N3DSJoystickState *previous_state); SDL_FORCE_INLINE void UpdateButtons(SDL_Joystick *joystick, N3DSJoystickState *previous_state); -SDL_FORCE_INLINE void UpdateSensors(SDL_Joystick *joystick, N3DSJoystickState *previous_state); static N3DSJoystickState current_state; -static SDL_bool sensors_enabled = SDL_FALSE; static int N3DS_JoystickInit(void) { hidInit(); - HIDUSER_EnableAccelerometer(); - HIDUSER_EnableGyroscope(); return 0; } @@ -104,17 +98,13 @@ N3DS_JoystickOpen(SDL_Joystick *joystick, int device_index) joystick->nhats = 0; joystick->instance_id = device_index; - SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 0.0f); - SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 0.0f); - return 0; } static int N3DS_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled) { - sensors_enabled = enabled; - return 0; + return SDL_Unsupported(); } static void @@ -124,10 +114,6 @@ N3DS_JoystickUpdate(SDL_Joystick *joystick) UpdateAxis(joystick, &previous_state); UpdateButtons(joystick, &previous_state); - - if (sensors_enabled) { - UpdateSensors(joystick, &previous_state); - } } SDL_FORCE_INLINE void @@ -184,30 +170,6 @@ UpdateButtons(SDL_Joystick *joystick, N3DSJoystickState *previous_state) } } -SDL_FORCE_INLINE void -UpdateSensors(SDL_Joystick *joystick, N3DSJoystickState *previous_state) -{ - float data[3]; - - hidAccelRead(¤t_state.acceleration); - if (SDL_memcmp(&previous_state->acceleration, ¤t_state.acceleration, sizeof(accelVector)) != 0) { - SDL_memcpy(&previous_state->acceleration, ¤t_state.acceleration, sizeof(accelVector)); - data[0] = (float) current_state.acceleration.x * SDL_STANDARD_GRAVITY; - data[1] = (float) current_state.acceleration.y * SDL_STANDARD_GRAVITY; - data[2] = (float) current_state.acceleration.z * SDL_STANDARD_GRAVITY; - SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, data, sizeof data); - } - - hidGyroRead(¤t_state.rate); - if (SDL_memcmp(&previous_state->rate, ¤t_state.rate, sizeof(angularRate)) != 0) { - SDL_memcpy(&previous_state->rate, ¤t_state.rate, sizeof(angularRate)); - data[0] = (float) current_state.rate.y; - data[1] = (float) current_state.rate.z; - data[2] = (float) current_state.rate.x; - SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, data, sizeof data); - } -} - static void N3DS_JoystickClose(SDL_Joystick *joystick) { @@ -216,8 +178,6 @@ N3DS_JoystickClose(SDL_Joystick *joystick) static void N3DS_JoystickQuit(void) { - HIDUSER_DisableGyroscope(); - HIDUSER_DisableAccelerometer(); hidExit(); } diff --git a/src/sensor/SDL_sensor.c b/src/sensor/SDL_sensor.c index ba86528e4..6db4c633f 100644 --- a/src/sensor/SDL_sensor.c +++ b/src/sensor/SDL_sensor.c @@ -41,12 +41,15 @@ static SDL_SensorDriver *SDL_sensor_drivers[] = { #ifdef SDL_SENSOR_WINDOWS &SDL_WINDOWS_SensorDriver, #endif +#ifdef SDL_SENSOR_VITA + &SDL_VITA_SensorDriver, +#endif +#ifdef SDL_SENSOR_N3DS + &SDL_N3DS_SensorDriver, +#endif #if defined(SDL_SENSOR_DUMMY) || defined(SDL_SENSOR_DISABLED) &SDL_DUMMY_SensorDriver #endif -#if defined(SDL_SENSOR_VITA) - &SDL_VITA_SensorDriver -#endif }; static SDL_Sensor *SDL_sensors = NULL; static SDL_bool SDL_updating_sensor = SDL_FALSE; diff --git a/src/sensor/SDL_syssensor.h b/src/sensor/SDL_syssensor.h index 6e601a278..30d44009a 100644 --- a/src/sensor/SDL_syssensor.h +++ b/src/sensor/SDL_syssensor.h @@ -102,6 +102,7 @@ extern SDL_SensorDriver SDL_COREMOTION_SensorDriver; extern SDL_SensorDriver SDL_WINDOWS_SensorDriver; extern SDL_SensorDriver SDL_DUMMY_SensorDriver; extern SDL_SensorDriver SDL_VITA_SensorDriver; +extern SDL_SensorDriver SDL_N3DS_SensorDriver; #endif /* SDL_syssensor_h_ */ diff --git a/src/sensor/n3ds/SDL_n3dssensor.c b/src/sensor/n3ds/SDL_n3dssensor.c new file mode 100644 index 000000000..7204fcc78 --- /dev/null +++ b/src/sensor/n3ds/SDL_n3dssensor.c @@ -0,0 +1,218 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2022 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "../../SDL_internal.h" + +#ifdef SDL_SENSOR_N3DS + +#include <3ds.h> + +#include "../SDL_syssensor.h" + +/* 1 accelerometer and 1 gyroscope */ +#define N3DS_SENSOR_COUNT 2 + +typedef struct +{ + SDL_SensorType type; + SDL_SensorID instance_id; +} SDL_N3DSSensor; + +static SDL_N3DSSensor N3DS_sensors[N3DS_SENSOR_COUNT]; + +SDL_FORCE_INLINE int InitN3DSServices(void); +SDL_FORCE_INLINE void UpdateN3DSAccelerometer(SDL_Sensor *sensor); +SDL_FORCE_INLINE void UpdateN3DSGyroscope(SDL_Sensor *sensor); + +SDL_FORCE_INLINE SDL_bool +IsDeviceIndexValid(int device_index) +{ + return device_index >= 0 && device_index < N3DS_SENSOR_COUNT; +} + +static int +N3DS_SensorInit(void) +{ + if (InitN3DSServices() < 0) { + return SDL_SetError("Failed to initialise N3DS services"); + } + + N3DS_sensors[0].type = SDL_SENSOR_ACCEL; + N3DS_sensors[0].instance_id = SDL_GetNextSensorInstanceID(); + N3DS_sensors[1].type = SDL_SENSOR_GYRO; + N3DS_sensors[1].instance_id = SDL_GetNextSensorInstanceID(); + return 0; +} + +SDL_FORCE_INLINE int +InitN3DSServices(void) +{ + if (R_FAILED(hidInit())) { + return -1; + } + + if (R_FAILED(HIDUSER_EnableAccelerometer())) { + return -1; + } + + if (R_FAILED(HIDUSER_EnableGyroscope())) { + return -1; + } + return 0; +} + +static int +N3DS_SensorGetCount(void) +{ + return N3DS_SENSOR_COUNT; +} + +static void +N3DS_SensorDetect(void) +{ +} + +static const char * +N3DS_SensorGetDeviceName(int device_index) +{ + if (IsDeviceIndexValid(device_index)) { + switch (N3DS_sensors[device_index].type) { + case SDL_SENSOR_ACCEL: + return "Accelerometer"; + case SDL_SENSOR_GYRO: + return "Gyroscope"; + default: + return "Unknown"; + } + } + + return NULL; +} + +static SDL_SensorType +N3DS_SensorGetDeviceType(int device_index) +{ + if (IsDeviceIndexValid(device_index)) { + return N3DS_sensors[device_index].type; + } + return SDL_SENSOR_INVALID; +} + +static int +N3DS_SensorGetDeviceNonPortableType(int device_index) +{ + return (int) N3DS_SensorGetDeviceType(device_index); +} + +static SDL_SensorID +N3DS_SensorGetDeviceInstanceID(int device_index) +{ + if (IsDeviceIndexValid(device_index)) { + return N3DS_sensors[device_index].instance_id; + } + return -1; +} + +static int +N3DS_SensorOpen(SDL_Sensor *sensor, int device_index) +{ + return 0; +} + +static void +N3DS_SensorUpdate(SDL_Sensor *sensor) +{ + switch (sensor->type) { + case SDL_SENSOR_ACCEL: + UpdateN3DSAccelerometer(sensor); + break; + case SDL_SENSOR_GYRO: + UpdateN3DSGyroscope(sensor); + break; + default: + break; + } +} + +SDL_FORCE_INLINE void +UpdateN3DSAccelerometer(SDL_Sensor *sensor) +{ + static accelVector previous_state = { 0, 0, 0 }; + accelVector current_state; + float data[3]; + + hidAccelRead(¤t_state); + if (SDL_memcmp(&previous_state, ¤t_state, sizeof(accelVector)) != 0) { + SDL_memcpy(&previous_state, ¤t_state, sizeof(accelVector)); + data[0] = (float) current_state.x * SDL_STANDARD_GRAVITY; + data[1] = (float) current_state.y * SDL_STANDARD_GRAVITY; + data[2] = (float) current_state.z * SDL_STANDARD_GRAVITY; + SDL_PrivateSensorUpdate(sensor, data, sizeof data); + } +} + +SDL_FORCE_INLINE void +UpdateN3DSGyroscope(SDL_Sensor *sensor) +{ + static angularRate previous_state = { 0, 0, 0 }; + angularRate current_state; + float data[3]; + + hidGyroRead(¤t_state); + if (SDL_memcmp(&previous_state, ¤t_state, sizeof(angularRate)) != 0) { + SDL_memcpy(&previous_state, ¤t_state, sizeof(angularRate)); + data[0] = (float) current_state.x; + data[1] = (float) current_state.y; + data[2] = (float) current_state.z; + SDL_PrivateSensorUpdate(sensor, data, sizeof data); + } +} + +static void +N3DS_SensorClose(SDL_Sensor *sensor) +{ +} + +static void +N3DS_SensorQuit(void) +{ + HIDUSER_DisableGyroscope(); + HIDUSER_DisableAccelerometer(); + hidExit(); +} + +SDL_SensorDriver SDL_N3DS_SensorDriver = { + N3DS_SensorInit, + N3DS_SensorGetCount, + N3DS_SensorDetect, + N3DS_SensorGetDeviceName, + N3DS_SensorGetDeviceType, + N3DS_SensorGetDeviceNonPortableType, + N3DS_SensorGetDeviceInstanceID, + N3DS_SensorOpen, + N3DS_SensorUpdate, + N3DS_SensorClose, + N3DS_SensorQuit, +}; + +#endif /* SDL_SENSOR_N3DS */ + +/* vi: set ts=4 sw=4 expandtab: */