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) {