From 630e3a591a89b24a268be772a209de33d8a07824 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 7 Sep 2024 21:12:19 -0700 Subject: [PATCH] GBA SIO: Add support for side data in save states --- include/mgba/gba/interface.h | 3 +++ include/mgba/internal/gba/serialize.h | 1 + src/gba/core.c | 37 ++++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/include/mgba/gba/interface.h b/include/mgba/gba/interface.h index 3d52e7743..cba586632 100644 --- a/include/mgba/gba/interface.h +++ b/include/mgba/gba/interface.h @@ -113,6 +113,9 @@ struct GBASIODriver { void (*reset)(struct GBASIODriver* driver); bool (*load)(struct GBASIODriver* driver); bool (*unload)(struct GBASIODriver* driver); + uint32_t (*driverId)(const struct GBASIODriver* renderer); + bool (*loadState)(struct GBASIODriver* renderer, const void* state, size_t size); + void (*saveState)(struct GBASIODriver* renderer, void** state, size_t* size); void (*setMode)(struct GBASIODriver* driver, enum GBASIOMode mode); bool (*handlesMode)(struct GBASIODriver* driver, enum GBASIOMode mode); int (*connectedDevices)(struct GBASIODriver* driver); diff --git a/include/mgba/internal/gba/serialize.h b/include/mgba/internal/gba/serialize.h index c824e85aa..8b1823a17 100644 --- a/include/mgba/internal/gba/serialize.h +++ b/include/mgba/internal/gba/serialize.h @@ -287,6 +287,7 @@ DECL_BITS(GBASerializedMiscFlags, KeyIRQKeys, 4, 11); enum { GBA_SUBSYSTEM_VIDEO_RENDERER = 0, + GBA_SUBSYSTEM_SIO_DRIVER = 1, GBA_SUBSYSTEM_MAX, }; diff --git a/src/gba/core.c b/src/gba/core.c index a6939406e..00f5ccf97 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -842,7 +842,21 @@ static bool _GBACoreLoadExtraState(struct mCore* core, const struct mStateExtdat if (type == gba->video.renderer->rendererId(gba->video.renderer)) { ok = gba->video.renderer->loadState(gba->video.renderer, (void*) ((uintptr_t) item.data + sizeof(uint32_t)), - item.size - sizeof(type)); + item.size - sizeof(type)) && ok; + } + } else if (item.data) { + ok = false; + } + } + if (gba->sio.activeDriver && gba->sio.activeDriver->driverId && gba->sio.activeDriver->loadState && + mStateExtdataGet(extdata, EXTDATA_SUBSYSTEM_START + GBA_SUBSYSTEM_SIO_DRIVER, &item)) { + if ((uint32_t) item.size > sizeof(uint32_t)) { + uint32_t type; + LOAD_32(type, 0, item.data); + if (type == gba->sio.activeDriver->driverId(gba->sio.activeDriver)) { + ok = gba->sio.activeDriver->loadState(gba->sio.activeDriver, + (void*) ((uintptr_t) item.data + sizeof(uint32_t)), + item.size - sizeof(type)) && ok; } } else if (item.data) { ok = false; @@ -868,6 +882,27 @@ static bool _GBACoreSaveExtraState(struct mCore* core, struct mStateExtdata* ext } if (buffer) { free(buffer); + buffer = NULL; + } + size = 0; + + if (gba->sio.activeDriver && gba->sio.activeDriver->driverId && gba->sio.activeDriver->saveState) { + gba->sio.activeDriver->saveState(gba->sio.activeDriver, &buffer, &size); + if (size > 0 && buffer) { + struct mStateExtdataItem item; + item.size = size + sizeof(uint32_t); + item.data = malloc(item.size); + item.clean = free; + uint32_t type = gba->sio.activeDriver->driverId(gba->sio.activeDriver); + STORE_32(type, 0, item.data); + memcpy((void*) ((uintptr_t) item.data + sizeof(uint32_t)), buffer, size); + mStateExtdataPut(extdata, EXTDATA_SUBSYSTEM_START + GBA_SUBSYSTEM_SIO_DRIVER, &item); + } + if (buffer) { + free(buffer); + buffer = NULL; + } + size = 0; } return true;