mirror of https://github.com/mgba-emu/mgba.git
GBA Video: Add stubs for saving/loading extra data out of the video renderers
This commit is contained in:
parent
da553d191f
commit
a5ea157c9a
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue