Core: Migrate extdata to core
jump to
@@ -0,0 +1,131 @@
+/* Copyright (c) 2013-2016 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "serialize.h" + +#include "util/vfs.h" + +struct mStateExtdataHeader { + uint32_t tag; + int32_t size; + int64_t offset; +}; + +bool mStateExtdataInit(struct mStateExtdata* extdata) { + memset(extdata->data, 0, sizeof(extdata->data)); + return true; +} + +void mStateExtdataDeinit(struct mStateExtdata* extdata) { + size_t i; + for (i = 1; i < EXTDATA_MAX; ++i) { + if (extdata->data[i].data && extdata->data[i].clean) { + extdata->data[i].clean(extdata->data[i].data); + } + } +} + +void mStateExtdataPut(struct mStateExtdata* extdata, enum mStateExtdataTag tag, struct mStateExtdataItem* item) { + if (tag == EXTDATA_NONE || tag >= EXTDATA_MAX) { + return; + } + + if (extdata->data[tag].data && extdata->data[tag].clean) { + extdata->data[tag].clean(extdata->data[tag].data); + } + extdata->data[tag] = *item; +} + +bool mStateExtdataGet(struct mStateExtdata* extdata, enum mStateExtdataTag tag, struct mStateExtdataItem* item) { + if (tag == EXTDATA_NONE || tag >= EXTDATA_MAX) { + return false; + } + + *item = extdata->data[tag]; + return true; +} + +bool mStateExtdataSerialize(struct mStateExtdata* extdata, struct VFile* vf) { + ssize_t position = vf->seek(vf, 0, SEEK_CUR); + ssize_t size = sizeof(struct mStateExtdataHeader); + size_t i = 0; + for (i = 1; i < EXTDATA_MAX; ++i) { + if (extdata->data[i].data) { + size += sizeof(struct mStateExtdataHeader); + } + } + if (size == sizeof(struct mStateExtdataHeader)) { + return true; + } + struct mStateExtdataHeader* header = malloc(size); + position += size; + + size_t j; + for (i = 1, j = 0; i < EXTDATA_MAX; ++i) { + if (extdata->data[i].data) { + STORE_32LE(i, offsetof(struct mStateExtdataHeader, tag), &header[j]); + STORE_32LE(extdata->data[i].size, offsetof(struct mStateExtdataHeader, size), &header[j]); + STORE_64LE(position, offsetof(struct mStateExtdataHeader, offset), &header[j]); + position += extdata->data[i].size; + ++j; + } + } + header[j].tag = 0; + header[j].size = 0; + header[j].offset = 0; + + if (vf->write(vf, header, size) != size) { + free(header); + return false; + } + free(header); + + for (i = 1; i < EXTDATA_MAX; ++i) { + if (extdata->data[i].data) { + if (vf->write(vf, extdata->data[i].data, extdata->data[i].size) != extdata->data[i].size) { + return false; + } + } + } + return true; +} + +bool mStateExtdataDeserialize(struct mStateExtdata* extdata, struct VFile* vf) { + while (true) { + struct mStateExtdataHeader buffer, header; + if (vf->read(vf, &buffer, sizeof(buffer)) != sizeof(buffer)) { + return false; + } + LOAD_32LE(header.tag, 0, &buffer.tag); + LOAD_32LE(header.size, 0, &buffer.size); + LOAD_64LE(header.offset, 0, &buffer.offset); + + if (header.tag == EXTDATA_NONE) { + break; + } + if (header.tag >= EXTDATA_MAX) { + continue; + } + ssize_t position = vf->seek(vf, 0, SEEK_CUR); + if (vf->seek(vf, header.offset, SEEK_SET) < 0) { + return false; + } + struct mStateExtdataItem item = { + .data = malloc(header.size), + .size = header.size, + .clean = free + }; + if (!item.data) { + continue; + } + if (vf->read(vf, item.data, header.size) != header.size) { + free(item.data); + continue; + } + mStateExtdataPut(extdata, header.tag, &item); + vf->seek(vf, position, SEEK_SET); + }; + return true; +}
@@ -0,0 +1,42 @@
+/* Copyright (c) 2013-2016 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef M_SERIALIZE_H +#define M_SERIALIZE_H + +#include "util/common.h" + +enum mStateExtdataTag { + EXTDATA_NONE = 0, + EXTDATA_SCREENSHOT = 1, + EXTDATA_SAVEDATA = 2, + EXTDATA_CHEATS = 3, + EXTDATA_MAX +}; + +#define SAVESTATE_SCREENSHOT 1 +#define SAVESTATE_SAVEDATA 2 +#define SAVESTATE_CHEATS 4 + +struct mStateExtdataItem { + int32_t size; + void* data; + void (*clean)(void*); +}; + +struct mStateExtdata { + struct mStateExtdataItem data[EXTDATA_MAX]; +}; + +bool mStateExtdataInit(struct mStateExtdata*); +void mStateExtdataDeinit(struct mStateExtdata*); +void mStateExtdataPut(struct mStateExtdata*, enum mStateExtdataTag, struct mStateExtdataItem*); +bool mStateExtdataGet(struct mStateExtdata*, enum mStateExtdataTag, struct mStateExtdataItem*); + +struct VFile; +bool mStateExtdataSerialize(struct mStateExtdata* extdata, struct VFile* vf); +bool mStateExtdataDeserialize(struct mStateExtdata* extdata, struct VFile* vf); + +#endif
@@ -6,10 +6,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gui-runner.h" #include "core/core.h" +#include "core/serialize.h" #include "feature/gui/gui-config.h" #include "gba/input.h" #include "gba/interface.h" -#include "gba/serialize.h" #include "util/gui/file-select.h" #include "util/gui/font.h" #include "util/gui/menu.h"
@@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cli.h" #include "core/core.h" +#include "core/serialize.h" #include "gb/gb.h" #include "gb/io.h" #include "gb/video.h"
@@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "cli.h" #include "arm/debugger/cli-debugger.h" +#include "core/serialize.h" #include "gba/io.h" #include "gba/serialize.h"
@@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "rr.h" +#include "core/serialize.h" #include "util/vfs.h" mLOG_DEFINE_CATEGORY(GBA_RR, "GBA RR");
@@ -5,6 +5,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "serialize.h" +#include "core/serialize.h" #include "core/sync.h" #include "gba/audio.h" #include "gba/cheats.h"@@ -35,13 +36,7 @@ mLOG_DEFINE_CATEGORY(GBA_STATE, "GBA Savestate");
struct GBABundledState { struct GBASerializedState* state; - struct GBAExtdata* extdata; -}; - -struct GBAExtdataHeader { - uint32_t tag; - int32_t size; - int64_t offset; + struct mStateExtdata* extdata; }; void GBASerialize(struct GBA* gba, struct GBASerializedState* state) {@@ -221,7 +216,7 @@ return true;
} #ifdef USE_PNG -static bool _savePNGState(struct GBA* gba, struct VFile* vf, struct GBAExtdata* extdata) { +static bool _savePNGState(struct GBA* gba, struct VFile* vf, struct mStateExtdata* extdata) { unsigned stride; const void* pixels = 0; gba->video.renderer->getPixels(gba->video.renderer, &stride, &pixels);@@ -290,11 +285,11 @@ uncompress((Bytef*) state, &len, chunk->data, chunk->size);
return 1; } if (!strcmp((const char*) chunk->name, "gbAx")) { - struct GBAExtdata* extdata = bundle->extdata; + struct mStateExtdata* extdata = bundle->extdata; if (!extdata) { return 0; } - struct GBAExtdataItem item; + struct mStateExtdataItem item; if (chunk->size < sizeof(uint32_t) * 2) { return 0; }@@ -314,13 +309,13 @@ const uint8_t* data = chunk->data;
data += sizeof(uint32_t) * 2; uncompress((Bytef*) item.data, &len, data, chunk->size); item.size = len; - GBAExtdataPut(extdata, tag, &item); + mStateExtdataPut(extdata, tag, &item); return 1; } return 0; } -static struct GBASerializedState* _loadPNGState(struct VFile* vf, struct GBAExtdata* extdata) { +static struct GBASerializedState* _loadPNGState(struct VFile* vf, struct mStateExtdata* extdata) { png_structp png = PNGReadOpen(vf, PNG_HEADER_BYTES); png_infop info = png_create_info_struct(png); png_infop end = png_create_info_struct(png);@@ -347,12 +342,12 @@ success = success && PNGReadFooter(png, end);
PNGReadClose(png, info, end); if (success) { - struct GBAExtdataItem item = { + struct mStateExtdataItem item = { .size = VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * 4, .data = pixels, .clean = free }; - GBAExtdataPut(extdata, EXTDATA_SCREENSHOT, &item); + mStateExtdataPut(extdata, EXTDATA_SCREENSHOT, &item); } else { free(pixels); GBADeallocateState(state);@@ -363,19 +358,19 @@ }
#endif bool GBASaveStateNamed(struct GBA* gba, struct VFile* vf, int flags) { - struct GBAExtdata extdata; - GBAExtdataInit(&extdata); + struct mStateExtdata extdata; + mStateExtdataInit(&extdata); if (flags & SAVESTATE_SAVEDATA) { // TODO: A better way to do this would be nice void* sram = malloc(SIZE_CART_FLASH1M); struct VFile* svf = VFileFromMemory(sram, SIZE_CART_FLASH1M); if (GBASavedataClone(&gba->memory.savedata, svf)) { - struct GBAExtdataItem item = { + struct mStateExtdataItem item = { .size = svf->seek(svf, 0, SEEK_CUR), .data = sram, .clean = free }; - GBAExtdataPut(&extdata, EXTDATA_SAVEDATA, &item); + mStateExtdataPut(&extdata, EXTDATA_SAVEDATA, &item); } else { free(sram); }@@ -387,12 +382,12 @@ struct mCheatDevice* device = (struct mCheatDevice*) gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE];
cheatVf = VFileMemChunk(0, 0); if (cheatVf) { mCheatSaveFile(device, cheatVf); - struct GBAExtdataItem item = { + struct mStateExtdataItem item = { .size = cheatVf->size(cheatVf), .data = cheatVf->map(cheatVf, cheatVf->size(cheatVf), MAP_READ), .clean = 0 }; - GBAExtdataPut(&extdata, EXTDATA_CHEATS, &item); + mStateExtdataPut(&extdata, EXTDATA_CHEATS, &item); } }; #ifdef USE_PNG@@ -403,7 +398,7 @@ #endif
vf->truncate(vf, sizeof(struct GBASerializedState)); struct GBASerializedState* state = vf->map(vf, sizeof(struct GBASerializedState), MAP_WRITE); if (!state) { - GBAExtdataDeinit(&extdata); + mStateExtdataDeinit(&extdata); if (cheatVf) { cheatVf->close(cheatVf); }@@ -412,8 +407,8 @@ }
GBASerialize(gba, state); vf->unmap(vf, state, sizeof(struct GBASerializedState)); vf->seek(vf, sizeof(struct GBASerializedState), SEEK_SET); - GBAExtdataSerialize(&extdata, vf); - GBAExtdataDeinit(&extdata); + mStateExtdataSerialize(&extdata, vf); + mStateExtdataDeinit(&extdata); if (cheatVf) { cheatVf->close(cheatVf); }@@ -422,15 +417,15 @@ #ifdef USE_PNG
} else { bool success = _savePNGState(gba, vf, &extdata); - GBAExtdataDeinit(&extdata); + mStateExtdataDeinit(&extdata); return success; } #endif - GBAExtdataDeinit(&extdata); + mStateExtdataDeinit(&extdata); return false; } -struct GBASerializedState* GBAExtractState(struct VFile* vf, struct GBAExtdata* extdata) { +struct GBASerializedState* GBAExtractState(struct VFile* vf, struct mStateExtdata* extdata) { #ifdef USE_PNG if (isPNG(vf)) { return _loadPNGState(vf, extdata);@@ -446,14 +441,14 @@ GBADeallocateState(state);
return 0; } if (extdata) { - GBAExtdataDeserialize(extdata, vf); + mStateExtdataDeserialize(extdata, vf); } return state; } bool GBALoadStateNamed(struct GBA* gba, struct VFile* vf, int flags) { - struct GBAExtdata extdata; - GBAExtdataInit(&extdata); + struct mStateExtdata extdata; + mStateExtdataInit(&extdata); struct GBASerializedState* state = GBAExtractState(vf, &extdata); if (!state) { return false;@@ -461,8 +456,8 @@ }
bool success = GBADeserialize(gba, state); GBADeallocateState(state); - struct GBAExtdataItem item; - if (flags & SAVESTATE_SCREENSHOT && GBAExtdataGet(&extdata, EXTDATA_SCREENSHOT, &item)) { + struct mStateExtdataItem item; + if (flags & SAVESTATE_SCREENSHOT && mStateExtdataGet(&extdata, EXTDATA_SCREENSHOT, &item)) { if (item.size >= VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * 4) { gba->video.renderer->putPixels(gba->video.renderer, VIDEO_HORIZONTAL_PIXELS, item.data); mCoreSyncForceFrame(gba->sync);@@ -470,14 +465,14 @@ } else {
mLOG(GBA_STATE, WARN, "Savestate includes invalid screenshot"); } } - if (flags & SAVESTATE_SAVEDATA && GBAExtdataGet(&extdata, EXTDATA_SAVEDATA, &item)) { + if (flags & SAVESTATE_SAVEDATA && mStateExtdataGet(&extdata, EXTDATA_SAVEDATA, &item)) { struct VFile* svf = VFileFromMemory(item.data, item.size); GBASavedataLoad(&gba->memory.savedata, svf); if (svf) { svf->close(svf); } } - if (flags & SAVESTATE_CHEATS && gba->cpu->components && gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE] && GBAExtdataGet(&extdata, EXTDATA_CHEATS, &item)) { + if (flags & SAVESTATE_CHEATS && gba->cpu->components && gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE] && mStateExtdataGet(&extdata, EXTDATA_CHEATS, &item)) { if (item.size) { struct mCheatDevice* device = (struct mCheatDevice*) gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE]; struct VFile* svf = VFileFromMemory(item.data, item.size);@@ -488,125 +483,8 @@ svf->close(svf);
} } } - GBAExtdataDeinit(&extdata); + mStateExtdataDeinit(&extdata); return success; -} - -bool GBAExtdataInit(struct GBAExtdata* extdata) { - memset(extdata->data, 0, sizeof(extdata->data)); - return true; -} - -void GBAExtdataDeinit(struct GBAExtdata* extdata) { - size_t i; - for (i = 1; i < EXTDATA_MAX; ++i) { - if (extdata->data[i].data && extdata->data[i].clean) { - extdata->data[i].clean(extdata->data[i].data); - } - } -} - -void GBAExtdataPut(struct GBAExtdata* extdata, enum GBAExtdataTag tag, struct GBAExtdataItem* item) { - if (tag == EXTDATA_NONE || tag >= EXTDATA_MAX) { - return; - } - - if (extdata->data[tag].data && extdata->data[tag].clean) { - extdata->data[tag].clean(extdata->data[tag].data); - } - extdata->data[tag] = *item; -} - -bool GBAExtdataGet(struct GBAExtdata* extdata, enum GBAExtdataTag tag, struct GBAExtdataItem* item) { - if (tag == EXTDATA_NONE || tag >= EXTDATA_MAX) { - return false; - } - - *item = extdata->data[tag]; - return true; -} - -bool GBAExtdataSerialize(struct GBAExtdata* extdata, struct VFile* vf) { - ssize_t position = vf->seek(vf, 0, SEEK_CUR); - ssize_t size = sizeof(struct GBAExtdataHeader); - size_t i = 0; - for (i = 1; i < EXTDATA_MAX; ++i) { - if (extdata->data[i].data) { - size += sizeof(struct GBAExtdataHeader); - } - } - if (size == sizeof(struct GBAExtdataHeader)) { - return true; - } - struct GBAExtdataHeader* header = malloc(size); - position += size; - - size_t j; - for (i = 1, j = 0; i < EXTDATA_MAX; ++i) { - if (extdata->data[i].data) { - STORE_32(i, offsetof(struct GBAExtdataHeader, tag), &header[j]); - STORE_32(extdata->data[i].size, offsetof(struct GBAExtdataHeader, size), &header[j]); - STORE_64(position, offsetof(struct GBAExtdataHeader, offset), &header[j]); - position += extdata->data[i].size; - ++j; - } - } - header[j].tag = 0; - header[j].size = 0; - header[j].offset = 0; - - if (vf->write(vf, header, size) != size) { - free(header); - return false; - } - free(header); - - for (i = 1; i < EXTDATA_MAX; ++i) { - if (extdata->data[i].data) { - if (vf->write(vf, extdata->data[i].data, extdata->data[i].size) != extdata->data[i].size) { - return false; - } - } - } - return true; -} - -bool GBAExtdataDeserialize(struct GBAExtdata* extdata, struct VFile* vf) { - while (true) { - struct GBAExtdataHeader buffer, header; - if (vf->read(vf, &buffer, sizeof(buffer)) != sizeof(buffer)) { - return false; - } - LOAD_32(header.tag, 0, &buffer.tag); - LOAD_32(header.size, 0, &buffer.size); - LOAD_64(header.offset, 0, &buffer.offset); - - if (header.tag == EXTDATA_NONE) { - break; - } - if (header.tag >= EXTDATA_MAX) { - continue; - } - ssize_t position = vf->seek(vf, 0, SEEK_CUR); - if (vf->seek(vf, header.offset, SEEK_SET) < 0) { - return false; - } - struct GBAExtdataItem item = { - .data = malloc(header.size), - .size = header.size, - .clean = free - }; - if (!item.data) { - continue; - } - if (vf->read(vf, item.data, header.size) != header.size) { - free(item.data); - continue; - } - GBAExtdataPut(extdata, header.tag, &item); - vf->seek(vf, position, SEEK_SET); - }; - return true; } struct GBASerializedState* GBAAllocateState(void) {
@@ -360,28 +360,6 @@ uint8_t iwram[SIZE_WORKING_IRAM];
uint8_t wram[SIZE_WORKING_RAM]; }; -enum GBAExtdataTag { - EXTDATA_NONE = 0, - EXTDATA_SCREENSHOT = 1, - EXTDATA_SAVEDATA = 2, - EXTDATA_CHEATS = 3, - EXTDATA_MAX -}; - -#define SAVESTATE_SCREENSHOT 1 -#define SAVESTATE_SAVEDATA 2 -#define SAVESTATE_CHEATS 4 - -struct GBAExtdataItem { - int32_t size; - void* data; - void (*clean)(void*); -}; - -struct GBAExtdata { - struct GBAExtdataItem data[EXTDATA_MAX]; -}; - struct VDir; void GBASerialize(struct GBA* gba, struct GBASerializedState* state);@@ -390,14 +368,8 @@
bool GBASaveStateNamed(struct GBA* gba, struct VFile* vf, int flags); bool GBALoadStateNamed(struct GBA* gba, struct VFile* vf, int flags); -bool GBAExtdataInit(struct GBAExtdata*); -void GBAExtdataDeinit(struct GBAExtdata*); -void GBAExtdataPut(struct GBAExtdata*, enum GBAExtdataTag, struct GBAExtdataItem*); -bool GBAExtdataGet(struct GBAExtdata*, enum GBAExtdataTag, struct GBAExtdataItem*); -bool GBAExtdataSerialize(struct GBAExtdata* extpdata, struct VFile* vf); -bool GBAExtdataDeserialize(struct GBAExtdata* extdata, struct VFile* vf); - -struct GBASerializedState* GBAExtractState(struct VFile* vf, struct GBAExtdata* extdata); +struct mStateExtdata; +struct GBASerializedState* GBAExtractState(struct VFile* vf, struct mStateExtdata* extdata); struct GBASerializedState* GBAAllocateState(void); void GBADeallocateState(struct GBASerializedState* state);
@@ -26,11 +26,12 @@ #import "mGBAGameCore.h"
#include "util/common.h" +#include "core/serialize.h" #include "core/core.h" #include "gba/cheats.h" #include "gba/core.h" +#include "gba/gba.h" #include "gba/input.h" -#include "gba/serialize.h" #include "util/circle-buffer.h" #include "util/memory.h" #include "util/vfs.h"
@@ -20,11 +20,11 @@
extern "C" { #include "core/config.h" #include "core/directories.h" +#include "core/serialize.h" #ifdef M_CORE_GBA #include "gba/bios.h" #include "gba/core.h" #include "gba/gba.h" -#include "gba/serialize.h" #include "gba/extra/sharkport.h" #endif #ifdef M_CORE_GB
@@ -15,8 +15,10 @@ #include <QKeyEvent>
#include <QPainter> extern "C" { +#include "core/serialize.h" +#ifdef M_CORE_GBA #include "gba/serialize.h" -#include "gba/video.h" +#endif } using namespace QGBA;@@ -176,21 +178,21 @@ m_slots[slot - 1]->setText(tr("Empty"));
return; } - GBAExtdata extdata; - GBAExtdataInit(&extdata); + mStateExtdata extdata; + mStateExtdataInit(&extdata); GBASerializedState* state = GBAExtractState(vf, &extdata); vf->seek(vf, 0, SEEK_SET); if (!state) { m_slots[slot - 1]->setText(tr("Corrupted")); - GBAExtdataDeinit(&extdata); + mStateExtdataDeinit(&extdata); return; } QDateTime creation(QDateTime::fromMSecsSinceEpoch(state->creationUsec / 1000LL)); QImage stateImage; - GBAExtdataItem item; - if (GBAExtdataGet(&extdata, EXTDATA_SCREENSHOT, &item) && item.size >= VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * 4) { + mStateExtdataItem item; + if (mStateExtdataGet(&extdata, EXTDATA_SCREENSHOT, &item) && item.size >= VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * 4) { stateImage = QImage((uchar*) item.data, VIDEO_HORIZONTAL_PIXELS, VIDEO_VERTICAL_PIXELS, QImage::Format_ARGB32).rgbSwapped(); }
@@ -14,7 +14,8 @@ #include "InputController.h"
#include "ShortcutView.h" extern "C" { -#include "gba/serialize.h" +#include "core/serialize.h" +#include "gba/gba.h" } using namespace QGBA;
@@ -6,12 +6,12 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "sdl-events.h" #include "core/input.h" +#include "core/serialize.h" #include "core/thread.h" #include "debugger/debugger.h" #include "gba/input.h" #include "gba/io.h" #include "gba/rr/rr.h" -#include "gba/serialize.h" #include "gba/video.h" #include "gba/renderers/video-software.h" #include "util/configuration.h"