Libretro: Support solar sensor

This commit is contained in:
Jeffrey Pfau 2015-07-30 18:01:16 -07:00
parent 903a8a654d
commit 3a31577cab
5 changed files with 63 additions and 6 deletions

View File

@ -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);

View File

@ -79,6 +79,8 @@ struct GBARotationSource {
int32_t (*readGyroZ)(struct GBARotationSource*);
};
extern const int GBA_LUX_LEVELS[10];
struct GBALuminanceSource {
void (*sample)(struct GBALuminanceSource*);

View File

@ -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;
}

View File

@ -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<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);
}

View File

@ -207,8 +207,6 @@ private:
uint8_t m_luxValue;
int m_luxLevel;
static const int LUX_LEVELS[10];
GBARTCGenericSource m_rtc;
};