From 983a4825278af11c1a35726edd95c28bbd037a1b Mon Sep 17 00:00:00 2001 From: p-sam Date: Mon, 28 Oct 2019 08:40:11 +0000 Subject: [PATCH] Use sensor interface; add sensor light core option Behavior synced from standalone mgba --- src/platform/libretro/libretro.c | 180 ++++++++++++++---- src/platform/libretro/libretro_core_options.h | 25 +-- .../libretro/libretro_core_options_intl.h | 25 +-- 3 files changed, 169 insertions(+), 61 deletions(-) diff --git a/src/platform/libretro/libretro.c b/src/platform/libretro/libretro.c index 803e44ccc..c18361b8c 100644 --- a/src/platform/libretro/libretro.c +++ b/src/platform/libretro/libretro.c @@ -30,6 +30,7 @@ #define SAMPLES 1024 #define RUMBLE_PWM 35 +#define EVENT_RATE 60 static retro_environment_t environCallback; static retro_video_refresh_t videoCallback; @@ -38,6 +39,8 @@ static retro_input_poll_t inputPollCallback; static retro_input_state_t inputCallback; static retro_log_printf_t logCallback; static retro_set_rumble_state_t rumbleCallback; +static retro_sensor_get_input_t sensorGetCallback; +static retro_set_sensor_state_t sensorStateCallback; static void GBARetroLog(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args); @@ -56,11 +59,17 @@ static void* data; static size_t dataSize; static void* savedata; static struct mAVStream stream; +static bool sensorsInitDone; static int rumbleUp; static int rumbleDown; static struct mRumble rumble; static struct GBALuminanceSource lux; -static int luxLevel; +static struct mRotationSource rotation; +static bool rotationEnabled; +static int luxLevelIndex; +static uint8_t luxLevel; +static bool luxSensorEnabled; +static bool luxSensorUsed; static struct mLogger logger; static struct retro_camera_callback cam; static struct mImageSource imageSource; @@ -71,6 +80,30 @@ static unsigned imcapWidth; static unsigned imcapHeight; static size_t camStride; static bool deferredSetup = false; +static bool envVarsUpdated; + +static void _initSensors(void) { + if(sensorsInitDone) { + return; + } + + struct retro_sensor_interface sensorInterface; + if (environCallback(RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE, &sensorInterface)) { + sensorGetCallback = sensorInterface.get_sensor_input; + sensorStateCallback = sensorInterface.set_sensor_state; + + if(sensorStateCallback(0, RETRO_SENSOR_ACCELEROMETER_ENABLE, EVENT_RATE) + && sensorStateCallback(0, RETRO_SENSOR_GYROSCOPE_ENABLE, EVENT_RATE)) { + rotationEnabled = true; + } + + if(sensorStateCallback(0, RETRO_SENSOR_ILLUMINANCE_ENABLE, EVENT_RATE)) { + luxSensorEnabled = true; + } + } + + sensorsInitDone = true; +} static void _reloadSettings(void) { struct mCoreOptions opts = { @@ -272,6 +305,19 @@ void retro_init(void) { rumbleCallback = 0; } + sensorsInitDone = false; + sensorGetCallback = 0; + sensorStateCallback = 0; + + rotationEnabled = false; + rotation.readTiltX = _readTiltX; + rotation.readTiltY = _readTiltY; + rotation.readGyroZ = _readGyroZ; + + envVarsUpdated = true; + luxSensorUsed = false; + luxSensorEnabled = false; + luxLevelIndex = 0; luxLevel = 0; lux.readLuminance = _readLux; lux.sample = _updateLux; @@ -298,6 +344,15 @@ void retro_init(void) { void retro_deinit(void) { free(outputBuffer); + + if(sensorStateCallback) { + sensorStateCallback(0, RETRO_SENSOR_ACCELEROMETER_DISABLE, EVENT_RATE); + sensorStateCallback(0, RETRO_SENSOR_GYROSCOPE_DISABLE, EVENT_RATE); + sensorStateCallback(0, RETRO_SENSOR_ILLUMINANCE_DISABLE, EVENT_RATE); + } + + rotationEnabled = false; + luxSensorEnabled = false; } void retro_run(void) { @@ -305,10 +360,14 @@ void retro_run(void) { _doDeferredSetup(); } uint16_t keys; + + _initSensors(); inputPollCallback(); bool updated = false; if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) { + envVarsUpdated = true; + struct retro_variable var = { .key = "mgba_allow_opposing_directions", .value = 0 @@ -339,23 +398,25 @@ void retro_run(void) { keys |= (!!inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L)) << 9; core->setKeys(core, keys); - static bool wasAdjustingLux = false; - if (wasAdjustingLux) { - wasAdjustingLux = inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3) || - inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3); - } else { - if (inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3)) { - ++luxLevel; - if (luxLevel > 10) { - luxLevel = 10; + if(!luxSensorUsed) { + static bool wasAdjustingLux = false; + if (wasAdjustingLux) { + wasAdjustingLux = inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3) || + inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3); + } else { + if (inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3)) { + ++luxLevelIndex; + if (luxLevelIndex > 10) { + luxLevelIndex = 10; + } + wasAdjustingLux = true; + } else if (inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3)) { + --luxLevelIndex; + if (luxLevelIndex < 0) { + luxLevelIndex = 0; + } + wasAdjustingLux = true; } - wasAdjustingLux = true; - } else if (inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3)) { - --luxLevel; - if (luxLevel < 0) { - luxLevel = 0; - } - wasAdjustingLux = true; } } @@ -938,35 +999,47 @@ static void _updateLux(struct GBALuminanceSource* lux) { .key = "mgba_solar_sensor_level", .value = 0 }; + bool luxVarUpdated = envVarsUpdated; - bool updated = false; - if (!environCallback(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) || !updated) { - return; - } - if (!environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || !var.value) { - return; + if (luxVarUpdated && (!environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || !var.value)) { + luxVarUpdated = false; } - char* end; - int newLuxLevel = strtol(var.value, &end, 10); - if (!*end) { - if (newLuxLevel > 10) { - luxLevel = 10; - } else if (newLuxLevel < 0) { - luxLevel = 0; - } else { - luxLevel = newLuxLevel; + if(luxVarUpdated) { + luxSensorUsed = strcmp(var.value, "sensor") == 0; + } + + if(luxSensorUsed) { + float fLux = luxSensorEnabled ? sensorGetCallback(0, RETRO_SENSOR_ILLUMINANCE) : 0.0f; + luxLevel = cbrtf(fLux) * 8; + } else { + if(luxVarUpdated) { + char* end; + int newLuxLevelIndex = strtol(var.value, &end, 10); + + if (!*end) { + if (newLuxLevelIndex > 10) { + luxLevelIndex = 10; + } else if (newLuxLevelIndex < 0) { + luxLevelIndex = 0; + } else { + luxLevelIndex = newLuxLevelIndex; + } + } + } + + luxLevel = 0x16; + if (luxLevelIndex > 0) { + luxLevel += GBA_LUX_LEVELS[luxLevelIndex - 1]; } } + + envVarsUpdated = false; } static uint8_t _readLux(struct GBALuminanceSource* lux) { UNUSED(lux); - int value = 0x16; - if (luxLevel > 0) { - value += GBA_LUX_LEVELS[luxLevel - 1]; - } - return 0xFF - value; + return 0xFF - luxLevel; } static void _updateCamera(const uint32_t* buffer, unsigned width, unsigned height, size_t pitch) { @@ -1032,3 +1105,36 @@ static void _requestImage(struct mImageSource* image, const void** buffer, size_ *stride = camStride; *colorFormat = mCOLOR_XRGB8; } + +static int32_t _readTiltX(struct mRotationSource* source) { + UNUSED(source); + int32_t tiltX = 0; + + if(rotationEnabled) { + tiltX = sensorGetCallback(0, RETRO_SENSOR_ACCELEROMETER_X) * 3e8f; + } + + return tiltX; +} + +static int32_t _readTiltY(struct mRotationSource* source) { + UNUSED(source); + int32_t tiltY = 0; + + if(rotationEnabled) { + tiltY = sensorGetCallback(0, RETRO_SENSOR_ACCELEROMETER_Y) * -3e8f; + } + + return tiltY; +} + +static int32_t _readGyroZ(struct mRotationSource* source) { + UNUSED(source); + int32_t gyroZ = 0; + + if(rotationEnabled) { + gyroZ = sensorGetCallback(0, RETRO_SENSOR_GYROSCOPE_Z) * -1.1e9f; + } + + return gyroZ; +} diff --git a/src/platform/libretro/libretro_core_options.h b/src/platform/libretro/libretro_core_options.h index b42655e11..e41e6cda2 100644 --- a/src/platform/libretro/libretro_core_options.h +++ b/src/platform/libretro/libretro_core_options.h @@ -54,18 +54,19 @@ struct retro_core_option_definition option_defs_us[] = { "Solar Sensor Level", "Sets ambient sunlight intensity. Can be used by games that included a solar sensor in their cartridges, e.g: the Boktai series.", { - { "0", NULL }, - { "1", NULL }, - { "2", NULL }, - { "3", NULL }, - { "4", NULL }, - { "5", NULL }, - { "6", NULL }, - { "7", NULL }, - { "8", NULL }, - { "9", NULL }, - { "10", NULL }, - { NULL, NULL }, + { "sensor", "Use device sensor if available" }, + { "0", NULL }, + { "1", NULL }, + { "2", NULL }, + { "3", NULL }, + { "4", NULL }, + { "5", NULL }, + { "6", NULL }, + { "7", NULL }, + { "8", NULL }, + { "9", NULL }, + { "10", NULL }, + { NULL, NULL }, }, "0" }, diff --git a/src/platform/libretro/libretro_core_options_intl.h b/src/platform/libretro/libretro_core_options_intl.h index c19dd40f2..c2d23f242 100644 --- a/src/platform/libretro/libretro_core_options_intl.h +++ b/src/platform/libretro/libretro_core_options_intl.h @@ -208,18 +208,19 @@ struct retro_core_option_definition option_defs_tr[] = { "Güneş Sensörü Seviyesi", "Ortam güneş ışığının yoğunluğunu ayarlar. Boktai serisi, kartuşlarına güneş sensörü içeren oyunlar tarafından kullanılabilir.", { - { "0", NULL }, - { "1", NULL }, - { "2", NULL }, - { "3", NULL }, - { "4", NULL }, - { "5", NULL }, - { "6", NULL }, - { "7", NULL }, - { "8", NULL }, - { "9", NULL }, - { "10", NULL }, - { NULL, NULL }, + { "sensor", "Sensörü" }, + { "0", NULL }, + { "1", NULL }, + { "2", NULL }, + { "3", NULL }, + { "4", NULL }, + { "5", NULL }, + { "6", NULL }, + { "7", NULL }, + { "8", NULL }, + { "9", NULL }, + { "10", NULL }, + { NULL, NULL }, }, "0" },