msgba/src/core_controller.c

130 lines
4.7 KiB
C

#include <linux/limits.h>
#include <mgba/flags.h>
#include <mgba/core/core.h>
#include <mgba/core/thread.h>
#include <mgba/core/interface.h>
#ifdef M_CORE_GBA
#include <mgba/internal/gba/sio/lockstep.h>
#endif
#ifdef M_CORE_GB
#include <mgba/internal/gb/sio/lockstep.h>
#endif
#include <mgba/core/serialize.h>
#include <mgba-util/vfs.h>
#include <msgba/global.h>
#include <msgba/core_controller.h>
#include <mgba/core/input.h>
#include <mgba/internal/gba/input.h>
struct msCoreController *
msCoreControllerLoadGame (const unsigned char *rom, size_t rom_len,
const unsigned char *state, size_t state_len,
struct msClientConnectionData *const data) {
struct VFile* file_rom = VFileMemChunk (NULL, rom_len);
struct VFile* file_state = VFileMemChunk (NULL, state_len);
file_rom->seek (file_rom, 0, SEEK_SET);
file_state->seek (file_state, 0, SEEK_SET);
file_rom->write (file_rom, rom, rom_len);
file_state->write (file_state, state, state_len);
struct mCore *core = mCoreFindVF (file_rom);
struct msCoreController *controller = NULL;
if (!core) {
ms_last_error = "This rom does not appear to be a GBA or GB/C one";
file_rom->close(file_rom);
goto loadGameReturn;
}
core->init(core);
mInputMapInit(&core->inputMap, &GBAInputInfo);
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_A, GBA_KEY_A);
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_B, GBA_KEY_B);
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_L, GBA_KEY_L);
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_R, GBA_KEY_R);
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_START, GBA_KEY_START);
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_SELECT, GBA_KEY_SELECT);
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_UP, GBA_KEY_UP);
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_DOWN, GBA_KEY_DOWN);
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_LEFT, GBA_KEY_LEFT);
mInputBindKey(&core->inputMap, 80, MSGBA_KEY_RIGHT, GBA_KEY_RIGHT);
unsigned int width;
unsigned int height;
mCoreInitConfig(core, NULL);
mCoreConfigSetIntValue(&core->config, "logLevel", mLOG_FATAL);
mCoreConfigSetFloatValue(&core->config, "fpsTarget", 0.1f);
mCoreConfigSetIntValue(&core->config, "videoSync", 1);
core->desiredVideoDimensions(core, &width, &height);
if (core->platform(core) == mPLATFORM_GB) {
width = 160;
height = 144;
}
color_t *outputBuffer = malloc((sizeof *outputBuffer) * width * height);
printf("controller->outputBuffer width: %u\n", width);
core->setVideoBuffer(core, outputBuffer, width);
core->loadROM (core, file_rom);
controller = msCoreControllerNew (core, data);
controller->outputBuffer = outputBuffer;
controller->stride = width;
controller->saveState = file_state;
loadGameReturn:
return controller;
}
void
msCoreControllerSetFrameCallback(struct msCoreController *const self, void(*callback)(struct mCoreThread *)) {
self->threadContext.frameCallback = callback;
}
void
msCoreControllerSetStartCallback(struct msCoreController *const self, void(*callback)(struct mCoreThread *)) {
self->threadContext.startCallback = callback;
}
void
mCoreThreadAfterStart(struct mCoreThread *threadContext) {
struct msClientConnectionData *data = (struct msClientConnectionData *)threadContext->userData;
struct msCoreController *coreController = data->coreController;
struct mCore *core = coreController->threadContext.core;
if (!mCoreLoadStateNamed (core, coreController->saveState, SAVESTATE_SAVEDATA | SAVESTATE_RTC | SAVESTATE_SCREENSHOT)) {
fprintf(stderr, "Unable to load save state\n");
}
}
void
msCoreControllerThreadStart (struct msCoreController *const core_controller) {
struct mCoreThread *thread = &core_controller->threadContext;
mCoreThreadStart(thread);
mCoreThreadRunFunction(thread, &mCoreThreadAfterStart);
}
void
msCoreControllerDestroy(struct msCoreController **controller_ptr) {
if (controller_ptr && *controller_ptr) {
struct msCoreController *controller = *controller_ptr;
mCoreThreadEnd(&controller->threadContext);
mCoreThreadJoin(&controller->threadContext);
if (controller->threadContext.core) {
struct mCore *core = controller->threadContext.core;
mInputMapDeinit(&core->inputMap);
core->deinit(core);
}
free(controller->outputBuffer);
free(controller);
*controller_ptr = NULL;
}
}
struct msCoreController *
msCoreControllerNew (struct mCore *core, struct msClientConnectionData *const data) {
struct msCoreController *controller = calloc (sizeof *controller, 1);
controller->multiplayer = NULL;
controller->threadContext.core = core;
controller->threadContext.userData = data;
return controller;
}