Commit b5e5ba02 authored by jdgleaver's avatar jdgleaver
Browse files

libretro: Add save state support

parent 17b94ae6
......@@ -297,6 +297,56 @@ void memorymap_load_state(FILE *fp)
READ_BOOL(timer_shot, fp);
}
uint32 memorymap_save_state_buf_size(void)
{
return 0x2000 +
0x2000 +
0x2000 +
sizeof(uint8) +
sizeof(uint8) +
sizeof(uint8);
}
void memorymap_save_state_buf(uint8 *data)
{
uint8 ibank = 0;
memcpy(data, regs, 0x2000);
data += 0x2000;
memcpy(data, lowerRam, 0x2000);
data += 0x2000;
memcpy(data, upperRam, 0x2000);
data += 0x2000;
ibank = (uint8)((lowerRomBank - programRom) / 0x4000);
WRITE_BUF_uint8(ibank, data);
WRITE_BUF_BOOL(dma_finished, data);
WRITE_BUF_BOOL(timer_shot, data);
}
void memorymap_load_state_buf(const uint8 *data)
{
uint8 ibank = 0;
memcpy(regs, data, 0x2000);
data += 0x2000;
memcpy(lowerRam, data, 0x2000);
data += 0x2000;
memcpy(upperRam, data, 0x2000);
data += 0x2000;
READ_BUF_uint8(ibank, data);
lowerRomBank = programRom + ibank * 0x4000;
READ_BUF_BOOL(dma_finished, data);
READ_BUF_BOOL(timer_shot, data);
}
uint8 *memorymap_getLowerRamPointer(void)
{
return lowerRam;
......
......@@ -26,6 +26,10 @@ BOOL memorymap_load(const uint8 *rom, uint32 size);
void memorymap_save_state(FILE *fp);
void memorymap_load_state(FILE *fp);
uint32 memorymap_save_state_buf_size(void);
void memorymap_save_state_buf(uint8 *data);
void memorymap_load_state_buf(const uint8 *data);
uint8 *memorymap_getLowerRamPointer(void);
uint8 *memorymap_getUpperRamPointer(void);
uint8 *memorymap_getRegisters(void);
......
......@@ -341,3 +341,96 @@ void sound_load_state(FILE *fp)
EXPAND_DMA
#undef X
}
uint32 sound_save_state_buf_size(void)
{
uint32 size = 0;
int i;
for (i = 0; i < 2; i++) {
size += sizeof(m_channel[i].reg);
size += sizeof(uint8);
size += sizeof(uint8);
size += sizeof(uint8);
size += sizeof(uint16);
size += sizeof(uint16);
size += sizeof(uint16);
}
size += sizeof(m_noise.reg);
size += sizeof(uint8);
size += sizeof(uint8);
size += sizeof(uint8);
size += sizeof(uint8);
size += sizeof(uint8);
size += sizeof(uint16);
size += sizeof(uint8);
size += sizeof(uint8);
size += sizeof(uint16);
size += sizeof(real);
size += sizeof(real);
size += sizeof(m_dma.reg);
size += sizeof(uint8);
size += sizeof(uint8);
size += sizeof(uint8);
size += sizeof(uint32);
size += sizeof(uint16);
size += sizeof(uint16);
size += sizeof(real);
size += sizeof(real);
return size;
}
void sound_save_state_buf(uint8 *data)
{
int i;
for (i = 0; i < 2; i++) {
memcpy(data, m_channel[i].reg, sizeof(m_channel[i].reg));
data += sizeof(m_channel[i].reg);
#define X(type, member) WRITE_BUF_##type(m_channel[i].member, data);
EXPAND_CHANNEL
#undef X
}
memcpy(data, m_noise.reg, sizeof(m_noise.reg));
data += sizeof(m_noise.reg);
#define X(type, member) WRITE_BUF_##type(m_noise.member, data);
EXPAND_NOISE
#undef X
memcpy(data, m_dma.reg, sizeof(m_dma.reg));
data += sizeof(m_dma.reg);
#define X(type, member) WRITE_BUF_##type(m_dma.member, data);
EXPAND_DMA
#undef X
}
void sound_load_state_buf(const uint8 *data)
{
int i;
sound_reset();
for (i = 0; i < 2; i++) {
memcpy(m_channel[i].reg, data, sizeof(m_channel[i].reg));
data += sizeof(m_channel[i].reg);
#define X(type, member) READ_BUF_##type(m_channel[i].member, data);
EXPAND_CHANNEL
#undef X
}
memcpy(m_noise.reg, data, sizeof(m_noise.reg));
data += sizeof(m_noise.reg);
#define X(type, member) READ_BUF_##type(m_noise.member, data);
EXPAND_NOISE
#undef X
memcpy(m_dma.reg, data, sizeof(m_dma.reg));
data += sizeof(m_dma.reg);
#define X(type, member) READ_BUF_##type(m_dma.member, data);
EXPAND_DMA
#undef X
}
......@@ -19,4 +19,8 @@ void sound_noise_write(int offset, uint8 data);
void sound_save_state(FILE *fp);
void sound_load_state(FILE *fp);
uint32 sound_save_state_buf_size(void);
void sound_save_state_buf(uint8 *data);
void sound_load_state_buf(const uint8 *data);
#endif
......@@ -115,6 +115,10 @@ BOOL supervision_save_state(const char *statePath, int8 id);
*/
BOOL supervision_load_state(const char *statePath, int8 id);
uint32 supervision_save_state_buf_size(void);
BOOL supervision_save_state_buf(uint8 *data, uint32 size);
BOOL supervision_load_state_buf(const uint8 *data, uint32 size);
#ifdef __cplusplus
}
#endif
......
......@@ -46,3 +46,21 @@ void timer_load_state(FILE *fp)
READ_int32(timer_cycles, fp);
READ_BOOL(timer_activated, fp);
}
uint32 timer_save_state_buf_size(void)
{
return sizeof(int32) +
sizeof(uint8);
}
void timer_save_state_buf(uint8 *data)
{
WRITE_BUF_int32(timer_cycles, data);
WRITE_BUF_BOOL(timer_activated, data);
}
void timer_load_state_buf(const uint8 *data)
{
READ_BUF_int32(timer_cycles, data);
READ_BUF_BOOL(timer_activated, data);
}
......@@ -12,4 +12,8 @@ void timer_exec(uint32 cycles);
void timer_save_state(FILE *fp);
void timer_load_state(FILE *fp);
uint32 timer_save_state_buf_size(void);
void timer_save_state_buf(uint8 *data);
void timer_load_state_buf(const uint8 *data);
#endif
#ifndef __TYPES_H__
#define __TYPES_H__
#include <string.h> /* For memcpy() */
#ifdef __cplusplus
extern "C" {
#endif
......@@ -132,6 +134,57 @@ static double SV_SwapDouble(const double x)
fread(&_, sizeof(_), 1, fp); \
x = (real)SV_SwapLEDouble(_); } while (0)
/*
* Buffer
*/
#define WRITE_BUF_BOOL(x, buf) do { \
uint8 _ = x ? 1 : 0; \
memcpy(buf, &_, 1); \
buf += 1; } while (0)
#define READ_BUF_BOOL(x, buf) do { \
uint8 _; \
memcpy(&_, buf, 1); \
buf += 1; \
x = _ ? TRUE : FALSE; } while (0)
#define WRITE_BUF_uint8(x, buf) do { \
memcpy(buf, &x, sizeof(x)); \
buf += sizeof(x); } while (0)
#define READ_BUF_uint8(x, buf) do { \
memcpy(&x, buf, sizeof(x)); \
buf += sizeof(x); } while (0)
#define WRITE_BUF_int8(x, buf) WRITE_BUF_uint8(x, buf)
#define READ_BUF_int8(x, buf) READ_BUF_uint8(x, buf)
#define WRITE_BUF_uint16(x, buf) do { \
memcpy(buf, &x, sizeof(x)); \
buf += sizeof(x); } while (0)
#define READ_BUF_uint16(x, buf) do { \
memcpy(&x, buf, sizeof(x)); \
buf += sizeof(x); } while (0)
#define WRITE_BUF_int16(x, buf) WRITE_BUF_uint16(x, buf)
#define READ_BUF_int16(x, buf) READ_BUF_uint16(x, buf)
#define WRITE_BUF_uint32(x, buf) do { \
memcpy(buf, &x, sizeof(x)); \
buf += sizeof(x); } while (0)
#define READ_BUF_uint32(x, buf) do { \
memcpy(&x, buf, sizeof(x)); \
buf += sizeof(x); } while (0)
#define WRITE_BUF_int32(x, buf) WRITE_BUF_uint32(x, buf)
#define READ_BUF_int32(x, buf) READ_BUF_uint32(x, buf)
#define WRITE_BUF_real(x, buf) do { \
memcpy(buf, &x, sizeof(x)); \
buf += sizeof(x); } while (0)
#define READ_BUF_real(x, buf) do { \
memcpy(&x, buf, sizeof(x)); \
buf += sizeof(x); } while (0)
#ifdef __cplusplus
}
#endif
......
......@@ -215,3 +215,70 @@ BOOL supervision_load_state(const char *statePath, int8 id)
}
return TRUE;
}
uint32 supervision_save_state_buf_size(void)
{
return memorymap_save_state_buf_size() +
sound_save_state_buf_size() +
timer_save_state_buf_size() +
sizeof(uint8) +
sizeof(uint8) +
sizeof(uint8) +
sizeof(uint8) +
sizeof(uint8) +
sizeof(uint8) +
sizeof(uint8) +
sizeof(int32) +
sizeof(int32) +
sizeof(uint8) +
sizeof(uint8) +
sizeof(int32) +
sizeof(uint8) +
128; /* Add some padding, just in case... */
}
BOOL supervision_save_state_buf(uint8 *data, uint32 size)
{
if (!data || size < supervision_save_state_buf_size()) {
return FALSE;
}
memorymap_save_state_buf(data);
data += memorymap_save_state_buf_size();
sound_save_state_buf(data);
data += sound_save_state_buf_size();
timer_save_state_buf(data);
data += timer_save_state_buf_size();
#define X(type, member) WRITE_BUF_##type(m6502_registers.member, data);
EXPAND_M6502
#undef X
WRITE_BUF_BOOL(irq, data);
return TRUE;
}
BOOL supervision_load_state_buf(const uint8 *data, uint32 size)
{
if (!data || size < supervision_save_state_buf_size()) {
return FALSE;
}
memorymap_load_state_buf(data);
data += memorymap_save_state_buf_size();
sound_load_state_buf(data);
data += sound_save_state_buf_size();
timer_load_state_buf(data);
data += timer_save_state_buf_size();
#define X(type, member) READ_BUF_##type(m6502_registers.member, data);
EXPAND_M6502
#undef X
READ_BUF_BOOL(irq, data);
return TRUE;
}
......@@ -230,20 +230,17 @@ void retro_set_controller_port_device(unsigned port, unsigned device)
size_t retro_serialize_size(void)
{
//return (size_t)sv_saveStateBufSize();
return 0;
return (size_t)supervision_save_state_buf_size();
}
bool retro_serialize(void *data, size_t size)
{
//return sv_saveStateBuf(data, (uint32)size);
return false;
return supervision_save_state_buf((uint8*)data, (uint32)size);
}
bool retro_unserialize(const void *data, size_t size)
{
//return sv_loadStateBuf(data, (uint32)size);
return false;
return supervision_load_state_buf((uint8*)data, (uint32)size);
}
void retro_cheat_reset(void)
......@@ -371,6 +368,7 @@ void retro_init(void)
#else
video_buffer = (uint16*)malloc(SV_W * SV_H * sizeof(uint16));
#endif
memset(video_buffer, 0, SV_W * SV_H * sizeof(uint16));
/* Round up sample buffer size to nearest multiple
* of 128, to avoid potential overflows */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment