X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=platform%2Flibretro.c;h=d46cc4a2c180320ae324c128eb11728902d8e683;hb=86b38dc46d93354418faf5aecd430f8661adb4b3;hp=15a83bad0640d6b0fb61927e017afa0eb4372130;hpb=41946d7023cded9999495eb8916eeb5ab0480a1f;p=picodrive.git diff --git a/platform/libretro.c b/platform/libretro.c index 15a83ba..d46cc4a 100644 --- a/platform/libretro.c +++ b/platform/libretro.c @@ -17,6 +17,7 @@ #endif #include +#include #include "common/input_pico.h" #include "common/version.h" #include "libretro.h" @@ -226,20 +227,124 @@ void retro_get_system_av_info(struct retro_system_av_info *info) info->geometry.aspect_ratio = 4.0 / 3.0; } -/* savestates - TODO */ +/* savestates */ +struct savestate_state { + const char *load_buf; + char *save_buf; + size_t size; + size_t pos; +}; + +size_t state_read(void *p, size_t size, size_t nmemb, void *file) +{ + struct savestate_state *state = file; + size_t bsize = size * nmemb; + + if (state->pos + bsize > state->size) { + lprintf("savestate error: %u/%u\n", + state->pos + bsize, state->size); + bsize = state->size - state->pos; + if ((int)bsize <= 0) + return 0; + } + + memcpy(p, state->load_buf + state->pos, bsize); + state->pos += bsize; + return bsize; +} + +size_t state_write(void *p, size_t size, size_t nmemb, void *file) +{ + struct savestate_state *state = file; + size_t bsize = size * nmemb; + + if (state->pos + bsize > state->size) { + lprintf("savestate error: %u/%u\n", + state->pos + bsize, state->size); + bsize = state->size - state->pos; + if ((int)bsize <= 0) + return 0; + } + + memcpy(state->save_buf + state->pos, p, bsize); + state->pos += bsize; + return bsize; +} + +size_t state_skip(void *p, size_t size, size_t nmemb, void *file) +{ + struct savestate_state *state = file; + size_t bsize = size * nmemb; + + state->pos += bsize; + return bsize; +} + +size_t state_eof(void *file) +{ + struct savestate_state *state = file; + + return state->pos >= state->size; +} + +int state_fseek(void *file, long offset, int whence) +{ + struct savestate_state *state = file; + + switch (whence) { + case SEEK_SET: + state->pos = offset; + break; + case SEEK_CUR: + state->pos += offset; + break; + case SEEK_END: + state->pos = state->size + offset; + break; + } + return (int)state->pos; +} + +/* savestate sizes vary wildly depending if cd/32x or + * carthw is active, so run the whole thing to get size */ size_t retro_serialize_size(void) { - return 0; + struct savestate_state state = { 0, }; + int ret; + + ret = PicoStateFP(&state, 1, NULL, state_skip, NULL, state_fseek); + if (ret != 0) + return 0; + + return state.pos; } bool retro_serialize(void *data, size_t size) { - return false; + struct savestate_state state = { 0, }; + int ret; + + state.save_buf = data; + state.size = size; + state.pos = 0; + + ret = PicoStateFP(&state, 1, NULL, state_write, + NULL, state_fseek); + return ret == 0; } bool retro_unserialize(const void *data, size_t size) { - return false; + struct savestate_state state = { 0, }; + int ret; + + state.load_buf = data; + state.size = size; + state.pos = 0; + + ret = PicoStateFP(&state, 0, state_read, NULL, + state_eof, state_fseek); + return ret == 0; } /* cheats - TODO */