diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx/GPGX.cs b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx/GPGX.cs index a99e9c5659..19f9ea934c 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx/GPGX.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx/GPGX.cs @@ -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(); diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx/LibGPGX.cs b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx/LibGPGX.cs index f767122380..c0fee1d933 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/gpgx/LibGPGX.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/gpgx/LibGPGX.cs @@ -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)] diff --git a/genplus-gx/cinterface/cinterface.c b/genplus-gx/cinterface/cinterface.c index 2385e0234c..694ae37d67 100644 --- a/genplus-gx/cinterface/cinterface.c +++ b/genplus-gx/cinterface/cinterface.c @@ -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) diff --git a/genplus-gx/core/cart_hw/eeprom_93c.c b/genplus-gx/core/cart_hw/eeprom_93c.c index 3e0a64f81d..02f81790ac 100644 --- a/genplus-gx/core/cart_hw/eeprom_93c.c +++ b/genplus-gx/core/cart_hw/eeprom_93c.c @@ -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; } } diff --git a/genplus-gx/core/cart_hw/eeprom_93c.h b/genplus-gx/core/cart_hw/eeprom_93c.h index 6c4e6e3f04..1e34b5300c 100644 --- a/genplus-gx/core/cart_hw/eeprom_93c.h +++ b/genplus-gx/core/cart_hw/eeprom_93c.h @@ -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 diff --git a/genplus-gx/core/cart_hw/eeprom_spi.c b/genplus-gx/core/cart_hw/eeprom_spi.c index 787eeca1ea..bd9f8c9402 100644 --- a/genplus-gx/core/cart_hw/eeprom_spi.c +++ b/genplus-gx/core/cart_hw/eeprom_spi.c @@ -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() diff --git a/genplus-gx/core/cart_hw/eeprom_spi.h b/genplus-gx/core/cart_hw/eeprom_spi.h index b1287bdd89..f547f86aa5 100644 --- a/genplus-gx/core/cart_hw/eeprom_spi.h +++ b/genplus-gx/core/cart_hw/eeprom_spi.h @@ -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); diff --git a/genplus-gx/core/cart_hw/sram.c b/genplus-gx/core/cart_hw/sram.c index 45b86f521c..063e454d0c 100644 --- a/genplus-gx/core/cart_hw/sram.c +++ b/genplus-gx/core/cart_hw/sram.c @@ -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; + } +} diff --git a/genplus-gx/core/cart_hw/sram.h b/genplus-gx/core/cart_hw/sram.h index 64934cab6e..6103c29c2f 100644 --- a/genplus-gx/core/cart_hw/sram.h +++ b/genplus-gx/core/cart_hw/sram.h @@ -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; diff --git a/genplus-gx/core/cd_hw/scd.c b/genplus-gx/core/cd_hw/scd.c index 4aa8ca7d3e..0e116cab86 100644 --- a/genplus-gx/core/cd_hw/scd.c +++ b/genplus-gx/core/cd_hw/scd.c @@ -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; } diff --git a/genplus-gx/core/state.c b/genplus-gx/core/state.c index 0ac6139c2d..41f75c80c9 100644 --- a/genplus-gx/core/state.c +++ b/genplus-gx/core/state.c @@ -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 */ diff --git a/output/dll/libgenplusgx.dll b/output/dll/libgenplusgx.dll index 33c7afd57c..d3f183fe3b 100644 Binary files a/output/dll/libgenplusgx.dll and b/output/dll/libgenplusgx.dll differ