msgba/src/core_controller.c

98 lines
3.3 KiB
C

#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>
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);
file_state->close(file_rom);
goto loadGameReturn;
}
core->init(core);
unsigned int width;
unsigned int height;
mCoreInitConfig(core, NULL);
mCoreConfigSetIntValue(&core->config, "logLevel", mLOG_FATAL);
core->desiredVideoDimensions(core, &width, &height);
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);
mCoreLoadStateNamed (core, file_state, SAVESTATE_SAVEDATA & SAVESTATE_RTC);
controller = msCoreControllerNew (core, data);
controller->outputBuffer = outputBuffer;
controller->stride = width;
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
msCoreControllerThreadStart (struct msCoreController *const core_controller) {
struct mCoreThread *thread = &core_controller->threadContext;
mCoreThreadStart(thread);
}
void
msCoreControllerDestroy(struct msCoreController **controller_ptr) {
if (controller_ptr && *controller_ptr) {
struct msCoreController *controller = *controller_ptr;
if (mCoreThreadHasStarted(&controller->threadContext)
&& !mCoreThreadHasExited(&controller->threadContext)) {
mCoreThreadEnd(&controller->threadContext);
}
if (controller->threadContext.core) {
struct mCore *core = controller->threadContext.core;
core->deinit(core);
}
free(controller->outputBuffer);
free(controller);
*controller_ptr = NULL;
}
}
struct msCoreController *
msCoreControllerNew (struct mCore *core, struct msClientConnectionData *const data) {
struct msCoreController *controller = malloc (sizeof *controller);
controller->multiplayer = NULL;
controller->threadContext.core = core;
controller->threadContext.userData = data;
return controller;
}