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:
parent
d81f2effb5
commit
343fbc7ae4
|
@ -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();
|
||||
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
Loading…
Reference in New Issue