genesis: big savestate rework. all old savestates are invalid. saveram is now stored in savestate. non-megaCD savestates should be significantly smaller than before; megaCD savestates should be slightly larger.

This commit is contained in:
goyuken 2014-02-03 18:07:21 +00:00
parent d81f2effb5
commit 343fbc7ae4
12 changed files with 171 additions and 76 deletions

View File

@ -108,8 +108,16 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
CoreComm.VsyncDen = fpsden; CoreComm.VsyncDen = fpsden;
} }
savebuff = new byte[LibGPGX.gpgx_state_size()]; // compute state size
savebuff2 = new byte[savebuff.Length + 13]; {
byte[] tmp = new byte[LibGPGX.gpgx_state_max_size()];
int size = LibGPGX.gpgx_state_size(tmp, tmp.Length);
if (size <= 0)
throw new Exception("Couldn't Determine GPGX internal state size!");
savebuff = new byte[size];
savebuff2 = new byte[savebuff.Length + 13];
Console.WriteLine("GPGX Internal State Size: {0}", size);
}
SetControllerDefinition(); SetControllerDefinition();

View File

@ -36,7 +36,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
public static extern void gpgx_get_fps(ref int num, ref int den); public static extern void gpgx_get_fps(ref int num, ref int den);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int gpgx_state_size(); public static extern int gpgx_state_max_size();
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int gpgx_state_size(byte[] dest, int size);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool gpgx_state_save(byte[] dest, int size); public static extern bool gpgx_state_save(byte[] dest, int size);
[DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("libgenplusgx.dll", CallingConvention = CallingConvention.Cdecl)]

View File

@ -106,25 +106,36 @@ GPGX_EX void gpgx_get_fps(int *num, int *den)
} }
} }
GPGX_EX int gpgx_state_size(void) GPGX_EX int gpgx_state_max_size(void)
{ {
return STATE_SIZE; // original state size, plus 64K sram or 16K ebram, plus 8K ibram or seeprom control structures
return STATE_SIZE + (64 + 8) * 1024;
}
GPGX_EX int gpgx_state_size(void *dest, int size)
{
int actual = 0;
if (size < gpgx_state_max_size())
return -1;
actual = state_save((unsigned char*) dest);
if (actual > size)
// fixme!
return -1;
return actual;
} }
GPGX_EX int gpgx_state_save(void *dest, int size) GPGX_EX int gpgx_state_save(void *dest, int size)
{ {
if (size != STATE_SIZE) return state_save((unsigned char*) dest) == size;
return 0;
return !!state_save((unsigned char*) dest);
} }
GPGX_EX int gpgx_state_load(void *src, int size) GPGX_EX int gpgx_state_load(void *src, int size)
{ {
if (size != STATE_SIZE) if (!size)
return 0; return 0;
if (state_load((unsigned char *) src)) if (state_load((unsigned char *) src) == size)
{ {
update_viewport(); update_viewport();
return 1; return 1;
@ -200,28 +211,7 @@ GPGX_EX void gpgx_advance(void)
// internal: computes sram size (no brams) // internal: computes sram size (no brams)
int saveramsize(void) int saveramsize(void)
{ {
if (!sram.on) return sram_get_actual_size();
return 0;
switch (sram.custom)
{
case 0: // plain bus access saveram
break;
case 1: // i2c
return eeprom_i2c.config.size_mask + 1;
case 2: // spi
return 0x10000; // it doesn't appear to mask anything internally
case 3: // 93c
return 0x10000; // SMS only and i don't have time to look into it
default:
return 0x10000; // who knows
}
// figure size for plain bus access saverams
{
int startaddr = sram.start / 8192;
int endaddr = sram.end / 8192 + 1;
int size = (endaddr - startaddr) * 8192;
return size;
}
} }
GPGX_EX void gpgx_clear_sram(void) GPGX_EX void gpgx_clear_sram(void)

View File

@ -52,7 +52,7 @@ void eeprom_93c_init()
/* default eeprom state */ /* default eeprom state */
memset(&eeprom_93c, 0, sizeof(T_EEPROM_93C)); memset(&eeprom_93c, 0, sizeof(T_EEPROM_93C));
eeprom_93c.data = 1; eeprom_93c.data = 1;
eeprom_93c.state = WAIT_START; eeprom_93c.state = WAIT_START93;
sram.custom = 3; sram.custom = 3;
} }
@ -67,19 +67,19 @@ void eeprom_93c_write(unsigned char data)
/* Current EEPROM state */ /* Current EEPROM state */
switch (eeprom_93c.state) switch (eeprom_93c.state)
{ {
case WAIT_START: case WAIT_START93:
{ {
/* Wait for START bit */ /* Wait for START bit */
if (data & (1 << BIT_DATA)) if (data & (1 << BIT_DATA))
{ {
eeprom_93c.opcode = 0; eeprom_93c.opcode = 0;
eeprom_93c.cycles = 0; eeprom_93c.cycles = 0;
eeprom_93c.state = GET_OPCODE; eeprom_93c.state = GET_OPCODE93;
} }
break; break;
} }
case GET_OPCODE: case GET_OPCODE93:
{ {
/* 8-bit buffer (opcode + address) */ /* 8-bit buffer (opcode + address) */
eeprom_93c.opcode |= ((data >> BIT_DATA) & 1) << (7 - eeprom_93c.cycles); eeprom_93c.opcode |= ((data >> BIT_DATA) & 1) << (7 - eeprom_93c.cycles);
@ -95,7 +95,7 @@ void eeprom_93c_write(unsigned char data)
/* WRITE */ /* WRITE */
eeprom_93c.buffer = 0; eeprom_93c.buffer = 0;
eeprom_93c.cycles = 0; eeprom_93c.cycles = 0;
eeprom_93c.state = WRITE_WORD; eeprom_93c.state = WRITE_WORD93;
break; break;
} }
@ -104,7 +104,7 @@ void eeprom_93c_write(unsigned char data)
/* READ */ /* READ */
eeprom_93c.buffer = *(uint16 *)(sram.sram + ((eeprom_93c.opcode & 0x3F) << 1)); eeprom_93c.buffer = *(uint16 *)(sram.sram + ((eeprom_93c.opcode & 0x3F) << 1));
eeprom_93c.cycles = 0; eeprom_93c.cycles = 0;
eeprom_93c.state = READ_WORD; eeprom_93c.state = READ_WORD93;
/* Force DATA OUT */ /* Force DATA OUT */
eeprom_93c.data = 0; eeprom_93c.data = 0;
@ -120,7 +120,7 @@ void eeprom_93c_write(unsigned char data)
} }
/* wait for next command */ /* wait for next command */
eeprom_93c.state = WAIT_STANDBY; eeprom_93c.state = WAIT_STANDBY93;
break; break;
} }
@ -134,7 +134,7 @@ void eeprom_93c_write(unsigned char data)
/* WRITE ALL */ /* WRITE ALL */
eeprom_93c.buffer = 0; eeprom_93c.buffer = 0;
eeprom_93c.cycles = 0; eeprom_93c.cycles = 0;
eeprom_93c.state = WRITE_WORD; eeprom_93c.state = WRITE_WORD93;
break; break;
} }
@ -147,7 +147,7 @@ void eeprom_93c_write(unsigned char data)
} }
/* wait for next command */ /* wait for next command */
eeprom_93c.state = WAIT_STANDBY; eeprom_93c.state = WAIT_STANDBY93;
break; break;
} }
@ -157,7 +157,7 @@ void eeprom_93c_write(unsigned char data)
eeprom_93c.we = (eeprom_93c.opcode >> 4) & 1; eeprom_93c.we = (eeprom_93c.opcode >> 4) & 1;
/* wait for next command */ /* wait for next command */
eeprom_93c.state = WAIT_STANDBY; eeprom_93c.state = WAIT_STANDBY93;
break; break;
} }
} }
@ -168,7 +168,7 @@ void eeprom_93c_write(unsigned char data)
break; break;
} }
case WRITE_WORD: case WRITE_WORD93:
{ {
/* 16-bit data buffer */ /* 16-bit data buffer */
eeprom_93c.buffer |= ((data >> BIT_DATA) & 1) << (15 - eeprom_93c.cycles); eeprom_93c.buffer |= ((data >> BIT_DATA) & 1) << (15 - eeprom_93c.cycles);
@ -197,12 +197,12 @@ void eeprom_93c_write(unsigned char data)
} }
/* wait for next command */ /* wait for next command */
eeprom_93c.state = WAIT_STANDBY; eeprom_93c.state = WAIT_STANDBY93;
} }
break; break;
} }
case READ_WORD: case READ_WORD93:
{ {
/* set DATA OUT */ /* set DATA OUT */
eeprom_93c.data = ((eeprom_93c.buffer >> (15 - eeprom_93c.cycles)) & 1); eeprom_93c.data = ((eeprom_93c.buffer >> (15 - eeprom_93c.cycles)) & 1);
@ -233,7 +233,7 @@ void eeprom_93c_write(unsigned char data)
{ {
/* standby mode */ /* standby mode */
eeprom_93c.data = 1; eeprom_93c.data = 1;
eeprom_93c.state = WAIT_START; eeprom_93c.state = WAIT_START93;
} }
} }

View File

@ -41,11 +41,11 @@
typedef enum typedef enum
{ {
WAIT_STANDBY, WAIT_STANDBY93,
WAIT_START, WAIT_START93,
GET_OPCODE, GET_OPCODE93,
WRITE_WORD, WRITE_WORD93,
READ_WORD READ_WORD93
} T_STATE_93C; } T_STATE_93C;
typedef struct typedef struct

View File

@ -37,6 +37,7 @@
****************************************************************************************/ ****************************************************************************************/
#include "shared.h" #include "shared.h"
#include "eeprom_spi.h"
/* max supported size 64KB (25x512/95x512) */ /* max supported size 64KB (25x512/95x512) */
#define SIZE_MASK 0xffff #define SIZE_MASK 0xffff
@ -48,28 +49,6 @@
#define BIT_HOLD (2) #define BIT_HOLD (2)
#define BIT_CS (3) #define BIT_CS (3)
typedef enum
{
STANDBY,
GET_OPCODE,
GET_ADDRESS,
WRITE_BYTE,
READ_BYTE
} T_STATE_SPI;
typedef struct
{
uint8 cs; /* !CS line state */
uint8 clk; /* SCLK line state */
uint8 out; /* SO line state */
uint8 status; /* status register */
uint8 opcode; /* 8-bit opcode */
uint8 buffer; /* 8-bit data buffer */
uint16 addr; /* 16-bit address */
uint32 cycles; /* current operation cycle */
T_STATE_SPI state; /* current operation state */
} T_EEPROM_SPI;
T_EEPROM_SPI spi_eeprom; T_EEPROM_SPI spi_eeprom;
void eeprom_spi_init() void eeprom_spi_init()

View File

@ -39,6 +39,30 @@
#ifndef _EEPROM_SPI_H_ #ifndef _EEPROM_SPI_H_
#define _EEPROM_SPI_H_ #define _EEPROM_SPI_H_
typedef enum
{
STANDBY,
GET_OPCODE,
GET_ADDRESS,
WRITE_BYTE,
READ_BYTE
} T_STATE_SPI;
typedef struct
{
uint8 cs; /* !CS line state */
uint8 clk; /* SCLK line state */
uint8 out; /* SO line state */
uint8 status; /* status register */
uint8 opcode; /* 8-bit opcode */
uint8 buffer; /* 8-bit data buffer */
uint16 addr; /* 16-bit address */
uint32 cycles; /* current operation cycle */
T_STATE_SPI state; /* current operation state */
} T_EEPROM_SPI;
extern T_EEPROM_SPI spi_eeprom;
/* Function prototypes */ /* Function prototypes */
extern void eeprom_spi_init(); extern void eeprom_spi_init();
extern void eeprom_spi_write(unsigned char data); extern void eeprom_spi_write(unsigned char data);

View File

@ -37,6 +37,9 @@
****************************************************************************************/ ****************************************************************************************/
#include "shared.h" #include "shared.h"
#include "eeprom_i2c.h"
#include "eeprom_spi.h"
#include "eeprom_93c.h"
T_SRAM sram; T_SRAM sram;
@ -69,7 +72,7 @@ void sram_init()
/* initialize Backup RAM */ /* initialize Backup RAM */
memset(sram.sram, 0xFF, 0x10000); memset(sram.sram, 0xFF, 0x10000);
sram.crc = crc32(0, sram.sram, 0x10000); //sram.crc = crc32(0, sram.sram, 0x10000);
/* retrieve informations from header */ /* retrieve informations from header */
if ((READ_BYTE(cart.rom,0x1b0) == 0x52) && (READ_BYTE(cart.rom,0x1b1) == 0x41)) if ((READ_BYTE(cart.rom,0x1b0) == 0x52) && (READ_BYTE(cart.rom,0x1b1) == 0x41))
@ -221,3 +224,74 @@ void sram_write_word(unsigned int address, unsigned int data)
sram.sram[address] = data >> 8; sram.sram[address] = data >> 8;
sram.sram[address + 1] = data & 0xff; sram.sram[address + 1] = data & 0xff;
} }
// the variables in SRAM_T are all part of "configuration", so we don't have to save those.
// the only thing that needs to be saved is the SRAM itself and the SEEPROM struct (if applicable)
int sram_context_save(uint8 *state)
{
int bufferptr = 0;
if (!sram.on)
return 0;
save_param(sram.sram, sram_get_actual_size());
switch (sram.custom)
{
case 1:
save_param(&eeprom_i2c, sizeof(eeprom_i2c));
break;
case 2:
save_param(&spi_eeprom, sizeof(spi_eeprom));
break;
case 3:
save_param(&eeprom_93c, sizeof(eeprom_93c));
break;
}
return bufferptr;
}
int sram_context_load(uint8 *state)
{
int bufferptr = 0;
if (!sram.on)
return 0;
load_param(sram.sram, sram_get_actual_size());
switch (sram.custom)
{
case 1:
load_param(&eeprom_i2c, sizeof(eeprom_i2c));
break;
case 2:
load_param(&spi_eeprom, sizeof(spi_eeprom));
break;
case 3:
load_param(&eeprom_93c, sizeof(eeprom_93c));
break;
}
return bufferptr;
}
int sram_get_actual_size()
{
if (!sram.on)
return 0;
switch (sram.custom)
{
case 0: // plain bus access saveram
break;
case 1: // i2c
return eeprom_i2c.config.size_mask + 1;
case 2: // spi
return 0x10000; // it doesn't appear to mask anything internally
case 3: // 93c
return 0x10000; // SMS only and i don't have time to look into it
default:
return 0x10000; // who knows
}
// figure size for plain bus access saverams
{
int startaddr = sram.start / 8192;
int endaddr = sram.end / 8192 + 1;
int size = (endaddr - startaddr) * 8192;
return size;
}
}

View File

@ -46,7 +46,7 @@ typedef struct
uint8 custom; uint8 custom;
uint32 start; uint32 start;
uint32 end; uint32 end;
uint32 crc; //uint32 crc;
uint8 *sram; uint8 *sram;
} T_SRAM; } T_SRAM;
@ -57,6 +57,10 @@ extern unsigned int sram_read_word(unsigned int address);
extern void sram_write_byte(unsigned int address, unsigned int data); extern void sram_write_byte(unsigned int address, unsigned int data);
extern void sram_write_word(unsigned int address, unsigned int data); extern void sram_write_word(unsigned int address, unsigned int data);
extern int sram_context_save(uint8 *state);
extern int sram_context_load(uint8 *state);
extern int sram_get_actual_size();
/* global variables */ /* global variables */
extern T_SRAM sram; extern T_SRAM sram;

View File

@ -1441,6 +1441,11 @@ int scd_context_save(uint8 *state)
bufferptr += md_cart_context_save(&state[bufferptr]); bufferptr += md_cart_context_save(&state[bufferptr]);
} }
save_param(scd.bram, 0x2000);
// we don't save scd.cartridge.id separately, so it must be non-changing!
if (scd.cartridge.id)
save_param(scd.cartridge.area, scd.cartridge.mask + 1);
return bufferptr; return bufferptr;
} }
@ -1641,6 +1646,11 @@ int scd_context_load(uint8 *state)
bufferptr += md_cart_context_load(&state[bufferptr]); bufferptr += md_cart_context_load(&state[bufferptr]);
} }
load_param(scd.bram, 0x2000);
// we don't save scd.cartridge.id separately, so it must be non-changing!
if (scd.cartridge.id)
load_param(scd.cartridge.area, scd.cartridge.mask + 1);
return bufferptr; return bufferptr;
} }

View File

@ -189,6 +189,8 @@ int state_load(unsigned char *state)
sms_cart_switch(~io_reg[0x0E]); sms_cart_switch(~io_reg[0x0E]);
} }
bufferptr += sram_context_load(&state[bufferptr]);
load_param(&bitmap.viewport, sizeof(bitmap.viewport)); load_param(&bitmap.viewport, sizeof(bitmap.viewport));
return bufferptr; return bufferptr;
@ -282,6 +284,8 @@ int state_save(unsigned char *state)
bufferptr += sms_cart_context_save(&state[bufferptr]); bufferptr += sms_cart_context_save(&state[bufferptr]);
} }
bufferptr += sram_context_save(&state[bufferptr]);
save_param(&bitmap.viewport, sizeof(bitmap.viewport)); save_param(&bitmap.viewport, sizeof(bitmap.viewport));
/* return total size */ /* return total size */

Binary file not shown.