mirror of https://github.com/mgba-emu/mgba.git
Libretro: Convert to mCore
This commit is contained in:
parent
e9fe4a1a9a
commit
1425db6a7a
|
@ -7,10 +7,11 @@
|
||||||
|
|
||||||
#include "util/common.h"
|
#include "util/common.h"
|
||||||
|
|
||||||
|
#include "core/core.h"
|
||||||
#include "gba/cheats.h"
|
#include "gba/cheats.h"
|
||||||
|
#include "gba/core.h"
|
||||||
#include "gba/renderers/video-software.h"
|
#include "gba/renderers/video-software.h"
|
||||||
#include "gba/serialize.h"
|
#include "gba/serialize.h"
|
||||||
#include "gba/context/context.h"
|
|
||||||
#include "util/circle-buffer.h"
|
#include "util/circle-buffer.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "util/vfs.h"
|
#include "util/vfs.h"
|
||||||
|
@ -26,15 +27,15 @@ static retro_input_state_t inputCallback;
|
||||||
static retro_log_printf_t logCallback;
|
static retro_log_printf_t logCallback;
|
||||||
static retro_set_rumble_state_t rumbleCallback;
|
static retro_set_rumble_state_t rumbleCallback;
|
||||||
|
|
||||||
static void GBARetroLog(struct GBAThread* thread, enum GBALogLevel level, const char* format, va_list args);
|
static void GBARetroLog(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args);
|
||||||
|
|
||||||
static void _postAudioBuffer(struct GBAAVStream*, struct GBAAudio* audio);
|
static void _postAudioBuffer(struct GBAAVStream*, struct GBAAudio* audio);
|
||||||
static void _setRumble(struct mRumble* rumble, int enable);
|
static void _setRumble(struct mRumble* rumble, int enable);
|
||||||
static uint8_t _readLux(struct GBALuminanceSource* lux);
|
static uint8_t _readLux(struct GBALuminanceSource* lux);
|
||||||
static void _updateLux(struct GBALuminanceSource* lux);
|
static void _updateLux(struct GBALuminanceSource* lux);
|
||||||
|
|
||||||
static struct GBAContext context;
|
static struct mCore* core;
|
||||||
static struct GBAVideoSoftwareRenderer renderer;
|
static void* outputBuffer;
|
||||||
static void* data;
|
static void* data;
|
||||||
static size_t dataSize;
|
static size_t dataSize;
|
||||||
static void* savedata;
|
static void* savedata;
|
||||||
|
@ -46,6 +47,7 @@ static struct GBALuminanceSource lux;
|
||||||
static int luxLevel;
|
static int luxLevel;
|
||||||
static struct GBACheatDevice cheats;
|
static struct GBACheatDevice cheats;
|
||||||
static struct GBACheatSet cheatSet;
|
static struct GBACheatSet cheatSet;
|
||||||
|
static struct mLogger logger;
|
||||||
|
|
||||||
static void _reloadSettings(void) {
|
static void _reloadSettings(void) {
|
||||||
struct mCoreOptions opts = {
|
struct mCoreOptions opts = {
|
||||||
|
@ -70,15 +72,16 @@ static void _reloadSettings(void) {
|
||||||
var.value = 0;
|
var.value = 0;
|
||||||
if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||||
if (strcmp(var.value, "Don't Remove") == 0) {
|
if (strcmp(var.value, "Don't Remove") == 0) {
|
||||||
mCoreConfigSetDefaultIntValue(&context.config, "idleOptimization", IDLE_LOOP_IGNORE);
|
mCoreConfigSetDefaultIntValue(&core->config, "idleOptimization", IDLE_LOOP_IGNORE);
|
||||||
} else if (strcmp(var.value, "Remove Known") == 0) {
|
} else if (strcmp(var.value, "Remove Known") == 0) {
|
||||||
mCoreConfigSetDefaultIntValue(&context.config, "idleOptimization", IDLE_LOOP_REMOVE);
|
mCoreConfigSetDefaultIntValue(&core->config, "idleOptimization", IDLE_LOOP_REMOVE);
|
||||||
} else if (strcmp(var.value, "Detect and Remove") == 0) {
|
} else if (strcmp(var.value, "Detect and Remove") == 0) {
|
||||||
mCoreConfigSetDefaultIntValue(&context.config, "idleOptimization", IDLE_LOOP_DETECT);
|
mCoreConfigSetDefaultIntValue(&core->config, "idleOptimization", IDLE_LOOP_DETECT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mCoreConfigLoadDefaults(&context.config, &opts);
|
mCoreConfigLoadDefaults(&core->config, &opts);
|
||||||
|
mCoreLoadConfig(core);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned retro_api_version(void) {
|
unsigned retro_api_version(void) {
|
||||||
|
@ -191,18 +194,22 @@ void retro_init(void) {
|
||||||
} else {
|
} else {
|
||||||
logCallback = 0;
|
logCallback = 0;
|
||||||
}
|
}
|
||||||
|
logger.log = GBARetroLog;
|
||||||
|
mLogSetDefaultLogger(&logger);
|
||||||
|
|
||||||
stream.postAudioFrame = 0;
|
stream.postAudioFrame = 0;
|
||||||
stream.postAudioBuffer = _postAudioBuffer;
|
stream.postAudioBuffer = _postAudioBuffer;
|
||||||
stream.postVideoFrame = 0;
|
stream.postVideoFrame = 0;
|
||||||
|
|
||||||
GBAContextInit(&context, 0);
|
core = GBACoreCreate();
|
||||||
context.gba->logHandler = GBARetroLog;
|
mCoreInitConfig(core, NULL);
|
||||||
context.gba->stream = &stream;
|
core->init(core);
|
||||||
|
struct GBA* gba = core->board;
|
||||||
|
gba->stream = &stream;
|
||||||
if (rumbleCallback) {
|
if (rumbleCallback) {
|
||||||
context.gba->rumble = &rumble;
|
gba->rumble = &rumble;
|
||||||
}
|
}
|
||||||
context.gba->luminanceSource = &lux;
|
gba->luminanceSource = &lux;
|
||||||
|
|
||||||
const char* sysDir = 0;
|
const char* sysDir = 0;
|
||||||
if (environCallback(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &sysDir)) {
|
if (environCallback(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &sysDir)) {
|
||||||
|
@ -210,32 +217,30 @@ void retro_init(void) {
|
||||||
snprintf(biosPath, sizeof(biosPath), "%s%s%s", sysDir, PATH_SEP, "gba_bios.bin");
|
snprintf(biosPath, sizeof(biosPath), "%s%s%s", sysDir, PATH_SEP, "gba_bios.bin");
|
||||||
struct VFile* bios = VFileOpen(biosPath, O_RDONLY);
|
struct VFile* bios = VFileOpen(biosPath, O_RDONLY);
|
||||||
if (bios) {
|
if (bios) {
|
||||||
GBAContextLoadBIOSFromVFile(&context, bios);
|
core->loadBIOS(core, bios, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GBAVideoSoftwareRendererCreate(&renderer);
|
outputBuffer = malloc(256 * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
|
||||||
renderer.outputBuffer = malloc(256 * VIDEO_VERTICAL_PIXELS * BYTES_PER_PIXEL);
|
core->setVideoBuffer(core, outputBuffer, 256);
|
||||||
renderer.outputBufferStride = 256;
|
|
||||||
context.renderer = &renderer.d;
|
|
||||||
|
|
||||||
GBAAudioResizeBuffer(&context.gba->audio, SAMPLES);
|
GBAAudioResizeBuffer(&gba->audio, SAMPLES);
|
||||||
|
|
||||||
blip_set_rates(context.gba->audio.psg.left, GBA_ARM7TDMI_FREQUENCY, 32768);
|
blip_set_rates(core->getAudioChannel(core, 0), GBA_ARM7TDMI_FREQUENCY, 32768);
|
||||||
blip_set_rates(context.gba->audio.psg.right, GBA_ARM7TDMI_FREQUENCY, 32768);
|
blip_set_rates(core->getAudioChannel(core, 1), GBA_ARM7TDMI_FREQUENCY, 32768);
|
||||||
|
|
||||||
GBACheatDeviceCreate(&cheats);
|
GBACheatDeviceCreate(&cheats);
|
||||||
GBACheatAttachDevice(context.gba, &cheats);
|
GBACheatAttachDevice(gba, &cheats);
|
||||||
GBACheatSetInit(&cheatSet, "libretro");
|
GBACheatSetInit(&cheatSet, "libretro");
|
||||||
GBACheatAddSet(&cheats, &cheatSet);
|
GBACheatAddSet(&cheats, &cheatSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void retro_deinit(void) {
|
void retro_deinit(void) {
|
||||||
GBAContextDeinit(&context);
|
core->deinit(core);
|
||||||
GBACheatRemoveSet(&cheats, &cheatSet);
|
GBACheatRemoveSet(&cheats, &cheatSet);
|
||||||
GBACheatDeviceDestroy(&cheats);
|
GBACheatDeviceDestroy(&cheats);
|
||||||
GBACheatSetDeinit(&cheatSet);
|
GBACheatSetDeinit(&cheatSet);
|
||||||
free(renderer.outputBuffer);
|
free(outputBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void retro_run(void) {
|
void retro_run(void) {
|
||||||
|
@ -250,7 +255,7 @@ void retro_run(void) {
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) {
|
if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) {
|
||||||
if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||||
context.gba->allowOpposingDirections = strcmp(var.value, "yes") == 0;
|
((struct GBA*) core->board)->allowOpposingDirections = strcmp(var.value, "yes") == 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,6 +270,7 @@ void retro_run(void) {
|
||||||
keys |= (!!inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN)) << 7;
|
keys |= (!!inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN)) << 7;
|
||||||
keys |= (!!inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R)) << 8;
|
keys |= (!!inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R)) << 8;
|
||||||
keys |= (!!inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L)) << 9;
|
keys |= (!!inputCallback(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L)) << 9;
|
||||||
|
core->setKeys(core, keys);
|
||||||
|
|
||||||
static bool wasAdjustingLux = false;
|
static bool wasAdjustingLux = false;
|
||||||
if (wasAdjustingLux) {
|
if (wasAdjustingLux) {
|
||||||
|
@ -286,12 +292,12 @@ void retro_run(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GBAContextFrame(&context, keys);
|
core->runFrame(core);
|
||||||
videoCallback(renderer.outputBuffer, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, BYTES_PER_PIXEL * renderer.outputBufferStride);
|
videoCallback(outputBuffer, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, BYTES_PER_PIXEL * 256);
|
||||||
}
|
}
|
||||||
|
|
||||||
void retro_reset(void) {
|
void retro_reset(void) {
|
||||||
ARMReset(context.cpu);
|
core->reset(core);
|
||||||
|
|
||||||
if (rumbleCallback) {
|
if (rumbleCallback) {
|
||||||
CircleBufferClear(&rumbleHistory);
|
CircleBufferClear(&rumbleHistory);
|
||||||
|
@ -322,13 +328,13 @@ bool retro_load_game(const struct retro_game_info* game) {
|
||||||
struct VFile* save = VFileFromMemory(savedata, SIZE_CART_FLASH1M);
|
struct VFile* save = VFileFromMemory(savedata, SIZE_CART_FLASH1M);
|
||||||
|
|
||||||
_reloadSettings();
|
_reloadSettings();
|
||||||
GBAContextLoadROMFromVFile(&context, rom, save);
|
core->loadROM(core, rom);
|
||||||
GBAContextStart(&context);
|
core->loadSave(core, save);
|
||||||
|
core->reset(core);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void retro_unload_game(void) {
|
void retro_unload_game(void) {
|
||||||
GBAContextStop(&context);
|
|
||||||
mappedMemoryFree(data, dataSize);
|
mappedMemoryFree(data, dataSize);
|
||||||
data = 0;
|
data = 0;
|
||||||
mappedMemoryFree(savedata, SIZE_CART_FLASH1M);
|
mappedMemoryFree(savedata, SIZE_CART_FLASH1M);
|
||||||
|
@ -344,7 +350,7 @@ bool retro_serialize(void* data, size_t size) {
|
||||||
if (size != retro_serialize_size()) {
|
if (size != retro_serialize_size()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
GBASerialize(context.gba, data);
|
GBASerialize(core->board, data);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,7 +358,7 @@ bool retro_unserialize(const void* data, size_t size) {
|
||||||
if (size != retro_serialize_size()) {
|
if (size != retro_serialize_size()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
GBADeserialize(context.gba, data);
|
GBADeserialize(core->board, data);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,7 +417,7 @@ size_t retro_get_memory_size(unsigned id) {
|
||||||
if (id != RETRO_MEMORY_SAVE_RAM) {
|
if (id != RETRO_MEMORY_SAVE_RAM) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
switch (context.gba->memory.savedata.type) {
|
switch (((struct GBA*) core->board)->memory.savedata.type) {
|
||||||
case SAVEDATA_AUTODETECT:
|
case SAVEDATA_AUTODETECT:
|
||||||
case SAVEDATA_FLASH1M:
|
case SAVEDATA_FLASH1M:
|
||||||
return SIZE_CART_FLASH1M;
|
return SIZE_CART_FLASH1M;
|
||||||
|
@ -427,8 +433,8 @@ size_t retro_get_memory_size(unsigned id) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBARetroLog(struct GBAThread* thread, enum GBALogLevel level, const char* format, va_list args) {
|
void GBARetroLog(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) {
|
||||||
UNUSED(thread);
|
UNUSED(logger);
|
||||||
if (!logCallback) {
|
if (!logCallback) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -438,27 +444,23 @@ void GBARetroLog(struct GBAThread* thread, enum GBALogLevel level, const char* f
|
||||||
|
|
||||||
enum retro_log_level retroLevel = RETRO_LOG_INFO;
|
enum retro_log_level retroLevel = RETRO_LOG_INFO;
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case GBA_LOG_ALL:
|
case mLOG_ERROR:
|
||||||
case GBA_LOG_ERROR:
|
case mLOG_FATAL:
|
||||||
case GBA_LOG_FATAL:
|
|
||||||
retroLevel = RETRO_LOG_ERROR;
|
retroLevel = RETRO_LOG_ERROR;
|
||||||
break;
|
break;
|
||||||
case GBA_LOG_WARN:
|
case mLOG_WARN:
|
||||||
retroLevel = RETRO_LOG_WARN;
|
retroLevel = RETRO_LOG_WARN;
|
||||||
break;
|
break;
|
||||||
case GBA_LOG_INFO:
|
case mLOG_INFO:
|
||||||
case GBA_LOG_GAME_ERROR:
|
case mLOG_GAME_ERROR:
|
||||||
case GBA_LOG_SWI:
|
|
||||||
case GBA_LOG_STATUS:
|
|
||||||
retroLevel = RETRO_LOG_INFO;
|
retroLevel = RETRO_LOG_INFO;
|
||||||
break;
|
break;
|
||||||
case GBA_LOG_DEBUG:
|
case mLOG_DEBUG:
|
||||||
case GBA_LOG_STUB:
|
case mLOG_STUB:
|
||||||
case GBA_LOG_SIO:
|
|
||||||
retroLevel = RETRO_LOG_DEBUG;
|
retroLevel = RETRO_LOG_DEBUG;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
logCallback(retroLevel, "%s\n", message);
|
logCallback(retroLevel, "%s: %s\n", mLogCategoryName(category), message);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _postAudioBuffer(struct GBAAVStream* stream, struct GBAAudio* audio) {
|
static void _postAudioBuffer(struct GBAAVStream* stream, struct GBAAudio* audio) {
|
||||||
|
|
Loading…
Reference in New Issue