Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 124 additions & 14 deletions src/platform/libretro/libretro.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ static int32_t _readTiltX(struct mRotationSource* source);
static int32_t _readTiltY(struct mRotationSource* source);
static int32_t _readGyroZ(struct mRotationSource* source);
static void _setupMaps(struct mCore* core);
static void _updateLuxFromExternalInput(void);
static int _boktai1StepToBar(int step);
static int _boktai1BarToStep(int bar);

static struct mCore* core;
static mColor* outputBuffer = NULL;
Expand All @@ -106,6 +109,8 @@ static int luxLevelIndex;
static uint8_t luxLevel;
static bool luxSensorEnabled;
static bool luxSensorUsed;
static bool luxExternalSensorUsed;
static bool boktai1Game;
static struct mLogger logger;
static struct retro_camera_callback cam;
static struct mImageSource imageSource;
Expand All @@ -128,6 +133,7 @@ static bool updateAudioRate;
static bool deferredSetup = false;
static bool useBitmasks = true;
static bool envVarsUpdated;
static unsigned inputMaxUsers = 1;
static int32_t tiltX = 0;
static int32_t tiltY = 0;
static int32_t gyroZ = 0;
Expand All @@ -152,8 +158,10 @@ static const int keymap[] = {
#ifndef GIT_VERSION
#define GIT_VERSION ""
#endif
#ifndef MGBA_LIBRETRO_USE_GENERATED_VERSION
const char* const projectVersion = "0.11-dev" GIT_VERSION;
const char* const projectName = "mGBA";
#endif

/* Maximum number of consecutive frames that
* can be skipped */
Expand Down Expand Up @@ -1414,6 +1422,12 @@ void retro_init(void) {
environCallback(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, &inputDescriptors);

useBitmasks = environCallback(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL);
unsigned maxUsers = 1;
if (environCallback(RETRO_ENVIRONMENT_GET_INPUT_MAX_USERS, &maxUsers) && maxUsers > 0) {
inputMaxUsers = maxUsers;
} else {
inputMaxUsers = 1;
}

// TODO: RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME when BIOS booting is supported

Expand All @@ -1435,7 +1449,9 @@ void retro_init(void) {

envVarsUpdated = true;
luxSensorUsed = false;
luxExternalSensorUsed = false;
luxSensorEnabled = false;
boktai1Game = false;
luxLevelIndex = 0;
luxLevel = 0;
lux.readLuminance = _readLux;
Expand Down Expand Up @@ -1606,22 +1622,30 @@ void retro_run(void) {

core->setKeys(core, keys);

if (!luxSensorUsed) {
if (luxExternalSensorUsed) {
_updateLuxFromExternalInput();
} else 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;
if (boktai1Game) {
int bar = _boktai1StepToBar(luxLevelIndex) + 1;
if (bar > 8) bar = 8;
luxLevelIndex = _boktai1BarToStep(bar);
} else {
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;
if (boktai1Game) {
int bar = _boktai1StepToBar(luxLevelIndex) - 1;
if (bar < 0) bar = 0;
luxLevelIndex = _boktai1BarToStep(bar);
} else {
if (--luxLevelIndex < 0) luxLevelIndex = 0;
}
wasAdjustingLux = true;
}
Expand Down Expand Up @@ -2097,6 +2121,13 @@ bool retro_load_game(const struct retro_game_info* game) {
if (core->platform(core) == mPLATFORM_GBA) {
core->setPeripheral(core, mPERIPH_GBA_LUMINANCE, &lux);
biosName = "gba_bios.bin";

const struct GBACartridge* cart = (const struct GBACartridge*) ((struct GBA*) core->board)->memory.rom;
if (cart) {
boktai1Game = memcmp(&cart->id, "U3IJ", 4) == 0
|| memcmp(&cart->id, "U3IE", 4) == 0
|| memcmp(&cart->id, "U3IP", 4) == 0;
}
}
#endif

Expand Down Expand Up @@ -2466,6 +2497,67 @@ static void _setRumble(struct mRumbleIntegrator* rumble, float level) {
rumbleCallback(0, RETRO_RUMBLE_WEAK, level * 0xFFFF);
}

static int _boktai1StepToBar(int step) {
static const int map[] = { 0, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8 };
if (step < 0) return 0;
if (step > 10) return 8;
return map[step];
}

static int _boktai1BarToStep(int bar) {
static const int map[] = { 0, 1, 2, 3, 5, 6, 7, 8, 10 };
if (bar < 0) return 0;
if (bar > 8) return 10;
return map[bar];
}

static void _updateLuxFromExternalInput(void) {
unsigned port;
bool unlocked = false;
float maxDeflection = 0.0f;
int maxBars = boktai1Game ? 8 : 10;
int numLevels = maxBars + 1;
int bars;

for (port = 0; port < inputMaxUsers; ++port) {
int16_t rawAxis;
float normalized = 0.0f;

if (!inputCallback(port, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R3)) {
continue;
}

unlocked = true;
rawAxis = inputCallback(port, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X);

if (rawAxis > 0) {
normalized = (float) rawAxis / 32767.0f;
if (normalized > 1.0f) {
normalized = 1.0f;
}
}

if (normalized > maxDeflection) {
maxDeflection = normalized;
}
}

if (!unlocked) {
return;
}

bars = (int) (maxDeflection * numLevels);
if (bars > maxBars) {
bars = maxBars;
}

if (boktai1Game) {
luxLevelIndex = _boktai1BarToStep(bars);
} else {
luxLevelIndex = bars;
}
}

static void _updateLux(struct GBALuminanceSource* lux) {
UNUSED(lux);
struct retro_variable var = {
Expand All @@ -2480,24 +2572,42 @@ static void _updateLux(struct GBALuminanceSource* lux) {

if (luxVarUpdated) {
luxSensorUsed = strcmp(var.value, "sensor") == 0;
luxExternalSensorUsed = strcmp(var.value, "external") == 0;
}

if (luxSensorUsed) {
_initSensors();
float fLux = luxSensorEnabled ? sensorGetCallback(0, RETRO_SENSOR_ILLUMINANCE) : 0.0f;
luxLevel = cbrtf(fLux) * 8;
int sensorLevel = (int)(cbrtf(fLux) * 8);
if (boktai1Game) {
if (sensorLevel > 8) sensorLevel = 8;
luxLevelIndex = _boktai1BarToStep(sensorLevel);
} else {
if (sensorLevel > 10) sensorLevel = 10;
luxLevelIndex = sensorLevel;
}
luxLevel = 0x16;
if (luxLevelIndex > 0) {
luxLevel += GBA_LUX_LEVELS[luxLevelIndex - 1];
}
} else {
if (luxVarUpdated) {
if (luxVarUpdated && !luxExternalSensorUsed) {
char* end;
int newLuxLevelIndex = strtol(var.value, &end, 10);

if (!*end) {
if (newLuxLevelIndex > 10) {
luxLevelIndex = 10;
} else if (newLuxLevelIndex < 0) {
luxLevelIndex = 0;
if (boktai1Game) {
if (newLuxLevelIndex < 0) newLuxLevelIndex = 0;
if (newLuxLevelIndex > 8) newLuxLevelIndex = 8;
luxLevelIndex = _boktai1BarToStep(newLuxLevelIndex);
} else {
luxLevelIndex = newLuxLevelIndex;
if (newLuxLevelIndex > 10) {
luxLevelIndex = 10;
} else if (newLuxLevelIndex < 0) {
luxLevelIndex = 0;
} else {
luxLevelIndex = newLuxLevelIndex;
}
}
}
}
Expand Down
27 changes: 14 additions & 13 deletions src/platform/libretro/libretro_core_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,24 +269,25 @@ struct retro_core_option_v2_definition option_defs_us[] = {
},
{
"mgba_solar_sensor_level",
"Solar Sensor Level",
"Solar Sensor",
NULL,
"Sets ambient sunlight intensity. Can be used by games that included a solar sensor in their cartridges, e.g: the Boktai series.",
"Sets sunlight intensity for games with cartridge solar sensors (e.g. Boktai). External sensor mode also supports R3 + Right Stick X+ to set the solar meter.",
NULL,
"input",
{
{ "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 },
{ "external", "Use external sensor (Ojo del Sol)" },
{ "0", "Static: 0 bars" },
{ "1", "Static: 1 bars" },
{ "2", "Static: 2 bars" },
{ "3", "Static: 3 bars" },
{ "4", "Static: 4 bars" },
{ "5", "Static: 5 bars" },
{ "6", "Static: 6 bars" },
{ "7", "Static: 7 bars" },
{ "8", "Static: 8 bars" },
{ "9", "Static: 9 bars" },
{ "10", "Static: 10 bars" },
{ NULL, NULL },
},
"0"
Expand Down
Loading