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;
}
savebuff = new byte[LibGPGX.gpgx_state_size()];
savebuff2 = new byte[savebuff.Length + 13];
// compute state size
{
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();

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);
[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)]
public static extern bool gpgx_state_save(byte[] dest, int size);
[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)
{
if (size != STATE_SIZE)
return 0;
return !!state_save((unsigned char*) dest);
return state_save((unsigned char*) dest) == size;
}
GPGX_EX int gpgx_state_load(void *src, int size)
{
if (size != STATE_SIZE)
if (!size)
return 0;
if (state_load((unsigned char *) src))
if (state_load((unsigned char *) src) == size)
{
update_viewport();
return 1;
@ -200,28 +211,7 @@ GPGX_EX void gpgx_advance(void)
// internal: computes sram size (no brams)
int saveramsize(void)
{
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;
}
return sram_get_actual_size();
}
GPGX_EX void gpgx_clear_sram(void)

View File

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

View File

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

View File

@ -37,6 +37,7 @@
****************************************************************************************/
#include "shared.h"
#include "eeprom_spi.h"
/* max supported size 64KB (25x512/95x512) */
#define SIZE_MASK 0xffff
@ -48,28 +49,6 @@
#define BIT_HOLD (2)
#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;
void eeprom_spi_init()

View File

@ -39,6 +39,30 @@
#ifndef _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 */
extern void eeprom_spi_init();
extern void eeprom_spi_write(unsigned char data);

View File

@ -37,6 +37,9 @@
****************************************************************************************/
#include "shared.h"
#include "eeprom_i2c.h"
#include "eeprom_spi.h"
#include "eeprom_93c.h"
T_SRAM sram;
@ -69,7 +72,7 @@ void sram_init()
/* initialize Backup RAM */
memset(sram.sram, 0xFF, 0x10000);
sram.crc = crc32(0, sram.sram, 0x10000);
//sram.crc = crc32(0, sram.sram, 0x10000);
/* retrieve informations from header */
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 + 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;
uint32 start;
uint32 end;
uint32 crc;
//uint32 crc;
uint8 *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_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 */
extern T_SRAM sram;

View File

@ -1441,6 +1441,11 @@ int scd_context_save(uint8 *state)
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;
}
@ -1641,6 +1646,11 @@ int scd_context_load(uint8 *state)
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;
}

View File

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

Binary file not shown.