Skip to content

Commit

Permalink
GBA Video: Add stubs for saving/loading extra data out of the video r…
Browse files Browse the repository at this point in the history
…enderers
  • Loading branch information
endrift committed Sep 1, 2024
1 parent da553d1 commit a5ea157
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 6 deletions.
6 changes: 6 additions & 0 deletions include/mgba/feature/video-logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ enum mVideoLoggerEvent {
LOGGER_EVENT_DEINIT,
LOGGER_EVENT_RESET,
LOGGER_EVENT_GET_PIXELS,
LOGGER_EVENT_LOAD_STATE,
LOGGER_EVENT_SAVE_STATE,
};

enum mVideoLoggerInjectionPoint {
Expand Down Expand Up @@ -85,6 +87,10 @@ struct mVideoLogger {

const void* pixelBuffer;
size_t pixelStride;

void* stateBuffer;
size_t stateSize;
bool stateStatus;
};

void mVideoLoggerRendererCreate(struct mVideoLogger* logger, bool readonly);
Expand Down
5 changes: 5 additions & 0 deletions include/mgba/internal/gba/serialize.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,11 @@ DECL_BIT(GBASerializedMiscFlags, IrqPending, 2);
DECL_BIT(GBASerializedMiscFlags, Blocked, 3);
DECL_BITS(GBASerializedMiscFlags, KeyIRQKeys, 4, 11);

enum {
GBA_SUBSYSTEM_VIDEO_RENDERER = 0,
GBA_SUBSYSTEM_MAX,
};

struct GBASerializedState {
uint32_t versionMagic;
uint32_t biosChecksum;
Expand Down
4 changes: 4 additions & 0 deletions include/mgba/internal/gba/video.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ struct GBAVideoRenderer {
void (*reset)(struct GBAVideoRenderer* renderer);
void (*deinit)(struct GBAVideoRenderer* renderer);

uint32_t (*rendererId)(const struct GBAVideoRenderer* renderer);
bool (*loadState)(struct GBAVideoRenderer* renderer, const void* state, size_t size);
void (*saveState)(struct GBAVideoRenderer* renderer, void** state, size_t* size);

uint16_t (*writeVideoRegister)(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value);
void (*writeVRAM)(struct GBAVideoRenderer* renderer, uint32_t address);
void (*writePalette)(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value);
Expand Down
41 changes: 36 additions & 5 deletions src/gba/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <mgba/core/core.h>
#include <mgba/core/log.h>
#include <mgba/core/serialize.h>
#include <mgba/internal/arm/debugger/debugger.h>
#include <mgba/internal/arm/isa-inlines.h>
#include <mgba/internal/debugger/symbols.h>
Expand Down Expand Up @@ -833,14 +834,44 @@ static bool _GBACoreSaveState(struct mCore* core, void* state) {
}

static bool _GBACoreLoadExtraState(struct mCore* core, const struct mStateExtdata* extdata) {
UNUSED(core);
UNUSED(extdata);
return true;
struct GBA* gba = core->board;
struct mStateExtdataItem item;
bool ok = true;
if (mStateExtdataGet(extdata, EXTDATA_SUBSYSTEM_START + GBA_SUBSYSTEM_VIDEO_RENDERER, &item)) {
if ((uint32_t) item.size > sizeof(uint32_t)) {
uint32_t type;
LOAD_32(type, 0, item.data);
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));
}
} else if (item.data) {
ok = false;
}
}
return ok;
}

static bool _GBACoreSaveExtraState(struct mCore* core, struct mStateExtdata* extdata) {
UNUSED(core);
UNUSED(extdata);
struct GBA* gba = core->board;
void* buffer = NULL;
size_t size = 0;
gba->video.renderer->saveState(gba->video.renderer, &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->video.renderer->rendererId(gba->video.renderer);
STORE_32(type, 0, item.data);
memcpy((void*) ((uintptr_t) item.data + sizeof(uint32_t)), buffer, size);
mStateExtdataPut(extdata, EXTDATA_SUBSYSTEM_START + GBA_SUBSYSTEM_VIDEO_RENDERER, &item);
}
if (buffer) {
free(buffer);
}

return true;
}

Expand Down
47 changes: 47 additions & 0 deletions src/gba/extra/proxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
static void GBAVideoProxyRendererInit(struct GBAVideoRenderer* renderer);
static void GBAVideoProxyRendererReset(struct GBAVideoRenderer* renderer);
static void GBAVideoProxyRendererDeinit(struct GBAVideoRenderer* renderer);
static uint32_t GBAVideoProxyRendererId(const struct GBAVideoRenderer* renderer);
static bool GBAVideoProxyRendererLoadState(struct GBAVideoRenderer* renderer, const void* state, size_t size);
static void GBAVideoProxyRendererSaveState(struct GBAVideoRenderer* renderer, void** state, size_t* size);
static uint16_t GBAVideoProxyRendererWriteVideoRegister(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value);
static void GBAVideoProxyRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address);
static void GBAVideoProxyRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value);
Expand All @@ -27,9 +30,13 @@ static bool _parsePacket(struct mVideoLogger* logger, const struct mVideoLoggerD
static uint16_t* _vramBlock(struct mVideoLogger* logger, uint32_t address);

void GBAVideoProxyRendererCreate(struct GBAVideoProxyRenderer* renderer, struct GBAVideoRenderer* backend) {
memset(renderer, 0, sizeof(*renderer));
renderer->d.init = GBAVideoProxyRendererInit;
renderer->d.reset = GBAVideoProxyRendererReset;
renderer->d.deinit = GBAVideoProxyRendererDeinit;
renderer->d.rendererId = GBAVideoProxyRendererId;
renderer->d.loadState = GBAVideoProxyRendererLoadState;
renderer->d.saveState = GBAVideoProxyRendererSaveState;
renderer->d.writeVideoRegister = GBAVideoProxyRendererWriteVideoRegister;
renderer->d.writeVRAM = GBAVideoProxyRendererWriteVRAM;
renderer->d.writeOAM = GBAVideoProxyRendererWriteOAM;
Expand Down Expand Up @@ -172,6 +179,11 @@ void GBAVideoProxyRendererDeinit(struct GBAVideoRenderer* renderer) {
mVideoLoggerRendererDeinit(proxyRenderer->logger);
}

uint32_t GBAVideoProxyRendererId(const struct GBAVideoRenderer* renderer) {
struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer;
return proxyRenderer->backend->rendererId(proxyRenderer->backend);
}

static void _handleEvent(struct mVideoLogger* logger, enum mVideoLoggerEvent event) {
struct GBAVideoProxyRenderer* proxyRenderer = logger->context;
switch (event) {
Expand All @@ -189,6 +201,12 @@ static void _handleEvent(struct mVideoLogger* logger, enum mVideoLoggerEvent eve
case LOGGER_EVENT_GET_PIXELS:
proxyRenderer->backend->getPixels(proxyRenderer->backend, &logger->pixelStride, &logger->pixelBuffer);
break;
case LOGGER_EVENT_LOAD_STATE:
logger->stateStatus = proxyRenderer->backend->loadState(proxyRenderer->backend, logger->stateBuffer, logger->stateSize);
break;
case LOGGER_EVENT_SAVE_STATE:
proxyRenderer->backend->saveState(proxyRenderer->backend, &logger->stateBuffer, &logger->stateSize);
break;
}
}

Expand Down Expand Up @@ -279,6 +297,35 @@ uint16_t GBAVideoProxyRendererWriteVideoRegister(struct GBAVideoRenderer* render
return value;
}

bool GBAVideoProxyRendererLoadState(struct GBAVideoRenderer* renderer, const void* state, size_t size) {
struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer;
if (proxyRenderer->logger->block && proxyRenderer->logger->wait) {
proxyRenderer->logger->wait(proxyRenderer->logger);
proxyRenderer->logger->stateBuffer = (void*) state;
proxyRenderer->logger->stateSize = size;
proxyRenderer->logger->postEvent(proxyRenderer->logger, LOGGER_EVENT_LOAD_STATE);
proxyRenderer->logger->stateBuffer = NULL;
proxyRenderer->logger->stateSize = 0;
return proxyRenderer->logger->stateStatus;
} else {
return proxyRenderer->backend->loadState(proxyRenderer->backend, state, size);
}
}

void GBAVideoProxyRendererSaveState(struct GBAVideoRenderer* renderer, void** state, size_t* size) {
struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer;
if (proxyRenderer->logger->block && proxyRenderer->logger->wait) {
proxyRenderer->logger->wait(proxyRenderer->logger);
proxyRenderer->logger->postEvent(proxyRenderer->logger, LOGGER_EVENT_SAVE_STATE);
*state = proxyRenderer->logger->stateBuffer;
*size = proxyRenderer->logger->stateSize;
proxyRenderer->logger->stateBuffer = NULL;
proxyRenderer->logger->stateSize = 0;
} else {
proxyRenderer->backend->saveState(proxyRenderer->backend, state, size);
}
}

void GBAVideoProxyRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address) {
struct GBAVideoProxyRenderer* proxyRenderer = (struct GBAVideoProxyRenderer*) renderer;
mVideoLoggerRendererWriteVRAM(proxyRenderer->logger, address);
Expand Down
29 changes: 29 additions & 0 deletions src/gba/renderers/gl.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@
#include <mgba/internal/gba/renderers/cache-set.h>
#include <mgba-util/memory.h>

#define OPENGL_MAGIC 0x6E726C67

static void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer);
static void GBAVideoGLRendererDeinit(struct GBAVideoRenderer* renderer);
static void GBAVideoGLRendererReset(struct GBAVideoRenderer* renderer);
static uint32_t GBAVideoGLRendererId(const struct GBAVideoRenderer* renderer);
static bool GBAVideoGLRendererLoadState(struct GBAVideoRenderer* renderer, const void* state, size_t size);
static void GBAVideoGLRendererSaveState(struct GBAVideoRenderer* renderer, void** state, size_t* size);
static void GBAVideoGLRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address);
static void GBAVideoGLRendererWriteOAM(struct GBAVideoRenderer* renderer, uint32_t oam);
static void GBAVideoGLRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value);
Expand Down Expand Up @@ -656,9 +661,13 @@ static const GLint _vertices[] = {
};

void GBAVideoGLRendererCreate(struct GBAVideoGLRenderer* renderer) {
memset(renderer, 0, sizeof(*renderer));
renderer->d.init = GBAVideoGLRendererInit;
renderer->d.reset = GBAVideoGLRendererReset;
renderer->d.deinit = GBAVideoGLRendererDeinit;
renderer->d.rendererId = GBAVideoGLRendererId;
renderer->d.loadState = GBAVideoGLRendererLoadState;
renderer->d.saveState = GBAVideoGLRendererSaveState;
renderer->d.writeVideoRegister = GBAVideoGLRendererWriteVideoRegister;
renderer->d.writeVRAM = GBAVideoGLRendererWriteVRAM;
renderer->d.writeOAM = GBAVideoGLRendererWriteOAM;
Expand Down Expand Up @@ -953,6 +962,26 @@ void GBAVideoGLRendererReset(struct GBAVideoRenderer* renderer) {
}
}

static uint32_t GBAVideoGLRendererId(const struct GBAVideoRenderer* renderer) {
UNUSED(renderer);
return OPENGL_MAGIC;
}

static bool GBAVideoGLRendererLoadState(struct GBAVideoRenderer* renderer, const void* state, size_t size) {
UNUSED(renderer);
UNUSED(state);
UNUSED(size);
// TODO
return false;
}

static void GBAVideoGLRendererSaveState(struct GBAVideoRenderer* renderer, void** state, size_t* size) {
UNUSED(renderer);
*state = NULL;
*size = 0;
// TODO
}

void GBAVideoGLRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address) {
struct GBAVideoGLRenderer* glRenderer = (struct GBAVideoGLRenderer*) renderer;
if (renderer->cache) {
Expand Down
30 changes: 29 additions & 1 deletion src/gba/renderers/video-software.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@

#define DIRTY_SCANLINE(R, Y) R->scanlineDirty[Y >> 5] |= (1U << (Y & 0x1F))
#define CLEAN_SCANLINE(R, Y) R->scanlineDirty[Y >> 5] &= ~(1U << (Y & 0x1F))
#define SOFTWARE_MAGIC 0x6E727773

static void GBAVideoSoftwareRendererInit(struct GBAVideoRenderer* renderer);
static void GBAVideoSoftwareRendererDeinit(struct GBAVideoRenderer* renderer);
static void GBAVideoSoftwareRendererReset(struct GBAVideoRenderer* renderer);
static uint32_t GBAVideoSoftwareRendererId(const struct GBAVideoRenderer* renderer);
static bool GBAVideoSoftwareRendererLoadState(struct GBAVideoRenderer* renderer, const void* state, size_t size);
static void GBAVideoSoftwareRendererSaveState(struct GBAVideoRenderer* renderer, void** state, size_t* size);
static void GBAVideoSoftwareRendererWriteVRAM(struct GBAVideoRenderer* renderer, uint32_t address);
static void GBAVideoSoftwareRendererWriteOAM(struct GBAVideoRenderer* renderer, uint32_t oam);
static void GBAVideoSoftwareRendererWritePalette(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value);
Expand Down Expand Up @@ -47,9 +51,13 @@ static void _breakWindow(struct GBAVideoSoftwareRenderer* softwareRenderer, stru
static void _breakWindowInner(struct GBAVideoSoftwareRenderer* softwareRenderer, struct WindowN* win);

void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer) {
memset(renderer, 0, sizeof(*renderer));
renderer->d.init = GBAVideoSoftwareRendererInit;
renderer->d.reset = GBAVideoSoftwareRendererReset;
renderer->d.deinit = GBAVideoSoftwareRendererDeinit;
renderer->d.rendererId = GBAVideoSoftwareRendererId;
renderer->d.loadState = GBAVideoSoftwareRendererLoadState;
renderer->d.saveState = GBAVideoSoftwareRendererSaveState;
renderer->d.writeVideoRegister = GBAVideoSoftwareRendererWriteVideoRegister;
renderer->d.writeVRAM = GBAVideoSoftwareRendererWriteVRAM;
renderer->d.writeOAM = GBAVideoSoftwareRendererWriteOAM;
Expand Down Expand Up @@ -79,7 +87,7 @@ void GBAVideoSoftwareRendererCreate(struct GBAVideoSoftwareRenderer* renderer) {
renderer->d.highlightColor = M_COLOR_WHITE;
renderer->d.highlightAmount = 0;

renderer->temporaryBuffer = 0;
renderer->temporaryBuffer = NULL;
}

static void GBAVideoSoftwareRendererInit(struct GBAVideoRenderer* renderer) {
Expand Down Expand Up @@ -155,6 +163,26 @@ static void GBAVideoSoftwareRendererDeinit(struct GBAVideoRenderer* renderer) {
UNUSED(softwareRenderer);
}

static uint32_t GBAVideoSoftwareRendererId(const struct GBAVideoRenderer* renderer) {
UNUSED(renderer);
return SOFTWARE_MAGIC;
}

static bool GBAVideoSoftwareRendererLoadState(struct GBAVideoRenderer* renderer, const void* state, size_t size) {
UNUSED(renderer);
UNUSED(state);
UNUSED(size);
// TODO
return false;
}

static void GBAVideoSoftwareRendererSaveState(struct GBAVideoRenderer* renderer, void** state, size_t* size) {
UNUSED(renderer);
*state = NULL;
*size = 0;
// TODO
}

static uint16_t GBAVideoSoftwareRendererWriteVideoRegister(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value) {
struct GBAVideoSoftwareRenderer* softwareRenderer = (struct GBAVideoSoftwareRenderer*) renderer;
if (renderer->cache) {
Expand Down

0 comments on commit a5ea157

Please sign in to comment.