+/* 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 */