Libretro: Support solar sensor
Jeffrey Pfau jeffrey@endrift.com
Thu, 30 Jul 2015 18:01:16 -0700
5 files changed,
63 insertions(+),
6 deletions(-)
M
src/gba/hardware.c
→
src/gba/hardware.c
@@ -9,6 +9,8 @@ #include "gba/io.h"
#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);
M
src/gba/interface.h
→
src/gba/interface.h
@@ -79,6 +79,8 @@
int32_t (*readGyroZ)(struct GBARotationSource*); }; +extern const int GBA_LUX_LEVELS[10]; + struct GBALuminanceSource { void (*sample)(struct GBALuminanceSource*);
M
src/platform/libretro/libretro.c
→
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"@@ -17,6 +18,8 @@ #include "util/vfs.h"
#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;@@ -31,6 +34,8 @@
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 @@ }
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 @@ } else {
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 @@ gba.idleOptimization = IDLE_LOOP_REMOVE; // TODO: Settings
if (rumbleCallback) { gba.rumble = &rumble; } + gba.luminanceSource = &lux; rom = 0; const char* sysDir = 0;@@ -401,3 +421,40 @@ }
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; +}
M
src/platform/qt/GameController.cpp
→
src/platform/qt/GameController.cpp
@@ -29,8 +29,6 @@
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 @@ m_luxValue = value;
value = std::max<int>(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); }
M
src/platform/qt/GameController.h
→
src/platform/qt/GameController.h
@@ -207,8 +207,6 @@ } m_lux;
uint8_t m_luxValue; int m_luxLevel; - static const int LUX_LEVELS[10]; - GBARTCGenericSource m_rtc; };