Mercurial > repos > blastem
diff blastem.c @ 451:b7c3b2d22858
Added support for saving savestates. Added gst savestate format test harness
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 26 Jul 2013 19:55:04 -0700 |
parents | e730fc040169 |
children | 608815ab4ff2 |
line wrap: on
line diff
--- a/blastem.c Sat Jul 20 23:49:31 2013 -0700 +++ b/blastem.c Fri Jul 26 19:55:04 2013 -0700 @@ -5,6 +5,7 @@ #include "vdp.h" #include "render.h" #include "blastem.h" +#include "gst.h" #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -152,6 +153,7 @@ } int break_on_sync = 0; +int save_state = 0; uint8_t reset = 1; uint8_t need_reset = 0; @@ -258,9 +260,19 @@ context->int_ack = 0; } adjust_int_cycle(context, v_context); - if (break_on_sync && address) { - break_on_sync = 0; - debugger(context, address); + if (address) { + if (break_on_sync) { + break_on_sync = 0; + debugger(context, address); + } + if (save_state) { + save_state = 0; + while (!z_context->pc) + { + sync_z80(z_context, z_context->current_cycle * MCLKS_PER_Z80 + MCLKS_PER_Z80); + } + save_gst(gen, "savestate.gst", address); + } } return context; } @@ -1465,190 +1477,6 @@ return context; } -#define GST_68K_REGS 0x80 -#define GST_68K_REG_SIZE (0xDA-GST_68K_REGS) -#define GST_68K_PC_OFFSET (0xC8-GST_68K_REGS) -#define GST_68K_SR_OFFSET (0xD0-GST_68K_REGS) -#define GST_68K_USP_OFFSET (0xD2-GST_68K_REGS) -#define GST_68K_SSP_OFFSET (0xD6-GST_68K_REGS) -#define GST_68K_RAM 0x2478 -#define GST_Z80_REGS 0x404 -#define GST_Z80_REG_SIZE (0x440-GST_Z80_REGS) -#define GST_Z80_RAM 0x474 - -uint32_t read_le_32(uint8_t * data) -{ - return data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0]; -} - -uint16_t read_le_16(uint8_t * data) -{ - return data[1] << 8 | data[0]; -} - -uint16_t read_be_16(uint8_t * data) -{ - return data[0] << 8 | data[1]; -} - -uint32_t m68k_load_gst(m68k_context * context, FILE * gstfile) -{ - uint8_t buffer[4096]; - fseek(gstfile, GST_68K_REGS, SEEK_SET); - if (fread(buffer, 1, GST_68K_REG_SIZE, gstfile) != GST_68K_REG_SIZE) { - fputs("Failed to read 68K registers from savestate\n", stderr); - return 0; - } - uint8_t * curpos = buffer; - for (int i = 0; i < 8; i++) { - context->dregs[i] = read_le_32(curpos); - curpos += sizeof(uint32_t); - } - for (int i = 0; i < 8; i++) { - context->aregs[i] = read_le_32(curpos); - curpos += sizeof(uint32_t); - } - uint32_t pc = read_le_32(buffer + GST_68K_PC_OFFSET); - uint16_t sr = read_le_16(buffer + GST_68K_SR_OFFSET); - context->status = sr >> 8; - for (int flag = 4; flag >= 0; flag--) { - context->flags[flag] = sr & 1; - sr >>= 1; - } - if (context->status & (1 << 5)) { - context->aregs[8] = read_le_32(buffer + GST_68K_USP_OFFSET); - } else { - context->aregs[8] = read_le_32(buffer + GST_68K_SSP_OFFSET); - } - fseek(gstfile, GST_68K_RAM, SEEK_SET); - for (int i = 0; i < (32*1024);) { - if (fread(buffer, 1, sizeof(buffer), gstfile) != sizeof(buffer)) { - fputs("Failed to read 68K RAM from savestate\n", stderr); - return 0; - } - for(curpos = buffer; curpos < (buffer + sizeof(buffer)); curpos += sizeof(uint16_t)) { - context->mem_pointers[1][i++] = read_be_16(curpos); - } - } - return pc; -} - -uint8_t z80_load_gst(z80_context * context, FILE * gstfile) -{ - uint8_t regdata[GST_Z80_REG_SIZE]; - fseek(gstfile, GST_Z80_REGS, SEEK_SET); - if (fread(regdata, 1, sizeof(regdata), gstfile) != sizeof(regdata)) { - fputs("Failed to read Z80 registers from savestate\n", stderr); - return 0; - } - uint8_t * curpos = regdata; - uint8_t f = *(curpos++); - context->flags[ZF_C] = f & 1; - f >>= 1; - context->flags[ZF_N] = f & 1; - f >>= 1; - context->flags[ZF_PV] = f & 1; - f >>= 2; - context->flags[ZF_H] = f & 1; - f >>= 2; - context->flags[ZF_Z] = f & 1; - f >>= 1; - context->flags[ZF_S] = f; - - context->regs[Z80_A] = *curpos; - curpos += 3; - for (int reg = Z80_C; reg <= Z80_IYH; reg++) { - context->regs[reg++] = *(curpos++); - context->regs[reg] = *curpos; - curpos += 3; - } - uint16_t pc = read_le_16(curpos); - curpos += 4; - context->sp = read_le_16(curpos); - curpos += 4; - f = *(curpos++); - context->alt_flags[ZF_C] = f & 1; - f >>= 1; - context->alt_flags[ZF_N] = f & 1; - f >>= 1; - context->alt_flags[ZF_PV] = f & 1; - f >>= 2; - context->alt_flags[ZF_H] = f & 1; - f >>= 2; - context->alt_flags[ZF_Z] = f & 1; - f >>= 1; - context->alt_flags[ZF_S] = f; - context->alt_regs[Z80_A] = *curpos; - curpos += 3; - for (int reg = Z80_C; reg <= Z80_H; reg++) { - context->alt_regs[reg++] = *(curpos++); - context->alt_regs[reg] = *curpos; - curpos += 3; - } - context->regs[Z80_I] = *curpos; - curpos += 2; - context->iff1 = context->iff2 = *curpos; - curpos += 2; - reset = !*(curpos++); - busreq = *curpos; - curpos += 3; - uint32_t bank = read_le_32(curpos); - if (bank < 0x400000) { - context->mem_pointers[1] = context->mem_pointers[2] + bank; - } else { - context->mem_pointers[1] = NULL; - } - context->bank_reg = bank >> 15; - fseek(gstfile, GST_Z80_RAM, SEEK_SET); - if(fread(context->mem_pointers[0], 1, 8*1024, gstfile) != (8*1024)) { - fputs("Failed to read Z80 RAM from savestate\n", stderr); - return 0; - } - context->native_pc = z80_get_native_address_trans(context, pc); - return 1; -} - -uint32_t load_gst(genesis_context * gen, char * fname) -{ - FILE * gstfile = fopen(fname, "rb"); - if (!gstfile) { - fprintf(stderr, "Could not open file %s for reading\n", fname); - goto error; - } - char ident[5]; - if (fread(ident, 1, sizeof(ident), gstfile) != sizeof(ident)) { - fprintf(stderr, "Could not read ident code from %s\n", fname); - goto error_close; - } - if (memcmp(ident, "GST\xE0\x40", 3) != 0) { - fprintf(stderr, "%s doesn't appear to be a GST savestate. The ident code is %c%c%c\\x%X\\x%X instead of GST\\xE0\\x40.\n", fname, ident[0], ident[1], ident[2], ident[3], ident[4]); - goto error_close; - } - uint32_t pc = m68k_load_gst(gen->m68k, gstfile); - if (!pc) { - goto error_close; - } - if (!vdp_load_gst(gen->vdp, gstfile)) { - goto error_close; - } - if (!ym_load_gst(gen->ym, gstfile)) { - goto error_close; - } - if (!z80_load_gst(gen->z80, gstfile)) { - goto error_close; - } - gen->ports[0].control = 0x40; - gen->ports[1].control = 0x40; - adjust_int_cycle(gen->m68k, gen->vdp); - fclose(gstfile); - return pc; - -error_close: - fclose(gstfile); -error: - return 0; -} - #define ROM_END 0x1A4 #define RAM_ID 0x1B0 #define RAM_FLAGS 0x1B2 @@ -1805,11 +1633,15 @@ if (statefile) { uint32_t pc = load_gst(gen, statefile); if (!pc) { + fprintf(stderr, "Failed to load save state %s\n", statefile); exit(1); } + printf("Loaded %s\n", statefile); if (debug) { insert_breakpoint(&context, pc, (uint8_t *)debugger); } + adjust_int_cycle(gen->m68k, gen->vdp); + gen->z80->native_pc = z80_get_native_address_trans(gen->z80, gen->z80->pc); start_68k_context(&context, pc); } else { if (debug) {