From 3a31577cab0794a929e738f02687c9fc4e40c46a Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Thu, 30 Jul 2015 18:01:16 -0700 Subject: [PATCH] Libretro: Support solar sensor --- src/gba/hardware.c | 2 ++ src/gba/interface.h | 2 ++ src/platform/libretro/libretro.c | 57 ++++++++++++++++++++++++++++++ src/platform/qt/GameController.cpp | 6 ++-- src/platform/qt/GameController.h | 2 -- 5 files changed, 63 insertions(+), 6 deletions(-) diff --git a/src/gba/hardware.c b/src/gba/hardware.c index fc4875f47..b445660ef 100644 --- a/src/gba/hardware.c +++ b/src/gba/hardware.c @@ -9,6 +9,8 @@ #include "gba/serialize.h" #include "util/hash.h" +const int GBA_LUX_LEVELS[10] = { 5, 11, 18, 27, 42, 62, 84, 109, 139, 183 }; + static void _readPins(struct GBACartridgeHardware* hw); static void _outputPins(struct GBACartridgeHardware* hw, unsigned pins); diff --git a/src/gba/interface.h b/src/gba/interface.h index 3daf0dcb8..396f4b549 100644 --- a/src/gba/interface.h +++ b/src/gba/interface.h @@ -79,6 +79,8 @@ struct GBARotationSource { int32_t (*readGyroZ)(struct GBARotationSource*); }; +extern const int GBA_LUX_LEVELS[10]; + struct GBALuminanceSource { void (*sample)(struct GBALuminanceSource*); diff --git a/src/platform/libretro/libretro.c b/src/platform/libretro/libretro.c index 1ae1a9fee..87570da74 100644 --- a/src/platform/libretro/libretro.c +++ b/src/platform/libretro/libretro.c @@ -8,6 +8,7 @@ #include "util/common.h" #include "gba/gba.h" +#include "gba/interface.h" #include "gba/renderers/video-software.h" #include "gba/serialize.h" #include "gba/supervisor/overrides.h" @@ -18,6 +19,8 @@ #define SAMPLES 1024 #define RUMBLE_PWM 35 +#define SOLAR_SENSOR_LEVEL "mgba_solar_sensor_level" + static retro_environment_t environCallback; static retro_video_refresh_t videoCallback; static retro_audio_sample_batch_t audioCallback; @@ -31,6 +34,8 @@ static void GBARetroLog(struct GBAThread* thread, enum GBALogLevel level, const static void _postAudioBuffer(struct GBAAVStream*, struct GBAAudio* audio); static void _postVideoFrame(struct GBAAVStream*, struct GBAVideoRenderer* renderer); static void _setRumble(struct GBARumble* rumble, int enable); +static uint8_t _readLux(struct GBALuminanceSource* lux); +static void _updateLux(struct GBALuminanceSource* lux); static struct GBA gba; static struct ARMCore cpu; @@ -44,6 +49,8 @@ static struct GBAAVStream stream; static int rumbleLevel; static struct CircleBuffer rumbleHistory; static struct GBARumble rumble; +static struct GBALuminanceSource lux; +static int luxLevel; unsigned retro_api_version(void) { return RETRO_API_VERSION; @@ -51,6 +58,13 @@ unsigned retro_api_version(void) { void retro_set_environment(retro_environment_t env) { environCallback = env; + + struct retro_variable vars[] = { + { SOLAR_SENSOR_LEVEL, "Solar sensor level; 0|1|2|3|4|5|6|7|8|9|10" }, + { 0, 0 } + }; + + environCallback(RETRO_ENVIRONMENT_SET_VARIABLES, vars); } void retro_set_video_refresh(retro_video_refresh_t video) { @@ -130,6 +144,11 @@ void retro_init(void) { rumbleCallback = 0; } + luxLevel = 0; + lux.readLuminance = _readLux; + lux.sample = _updateLux; + _updateLux(&lux); + struct retro_log_callback log; if (environCallback(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log)) { logCallback = log.log; @@ -151,6 +170,7 @@ void retro_init(void) { if (rumbleCallback) { gba.rumble = &rumble; } + gba.luminanceSource = &lux; rom = 0; const char* sysDir = 0; @@ -401,3 +421,40 @@ static void _setRumble(struct GBARumble* rumble, int enable) { CircleBufferWrite8(&rumbleHistory, enable); rumbleCallback(0, RETRO_RUMBLE_STRONG, rumbleLevel * 0xFFFF / RUMBLE_PWM); } + +static void _updateLux(struct GBALuminanceSource* lux) { + UNUSED(lux); + struct retro_variable var = { + .key = SOLAR_SENSOR_LEVEL, + .value = 0 + }; + + bool updated = false; + if (!environCallback(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) || !updated) { + return; + } + if (!environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) || !var.value) { + return; + } + + 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; + } + } +} + +static uint8_t _readLux(struct GBALuminanceSource* lux) { + UNUSED(lux); + int value = 0x16; + if (luxLevel > 0) { + value += GBA_LUX_LEVELS[luxLevel - 1]; + } + return 0xFF - value; +} diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index 32c5aa41d..b0e44a095 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -29,8 +29,6 @@ extern "C" { using namespace QGBA; using namespace std; -const int GameController::LUX_LEVELS[10] = { 5, 11, 18, 27, 42, 62, 84, 109, 139, 183 }; - GameController::GameController(QObject* parent) : QObject(parent) , m_drawContext(new uint32_t[256 * 256]) @@ -794,7 +792,7 @@ void GameController::setLuminanceValue(uint8_t value) { value = std::max(value - 0x16, 0); m_luxLevel = 10; for (int i = 0; i < 10; ++i) { - if (value < LUX_LEVELS[i]) { + if (value < GBA_LUX_LEVELS[i]) { m_luxLevel = i; break; } @@ -806,7 +804,7 @@ void GameController::setLuminanceLevel(int level) { int value = 0x16; level = std::max(0, std::min(10, level)); if (level > 0) { - value += LUX_LEVELS[level - 1]; + value += GBA_LUX_LEVELS[level - 1]; } setLuminanceValue(value); } diff --git a/src/platform/qt/GameController.h b/src/platform/qt/GameController.h index bbd5c2171..be698478f 100644 --- a/src/platform/qt/GameController.h +++ b/src/platform/qt/GameController.h @@ -207,8 +207,6 @@ private: uint8_t m_luxValue; int m_luxLevel; - static const int LUX_LEVELS[10]; - GBARTCGenericSource m_rtc; };