152 lines
3.5 KiB
C
152 lines
3.5 KiB
C
|
|
#include "common.h"
|
|
|
|
const u8 *state_mem_read_ptr;
|
|
u8 *state_mem_write_ptr;
|
|
|
|
const u8* bson_find_key(const u8 *srcp, const char *key)
|
|
{
|
|
unsigned keyl = strlen(key) + 1;
|
|
unsigned doclen = bson_read_u32(srcp);
|
|
const u8* p = &srcp[4];
|
|
while (*p != 0 && (p - srcp) < doclen) {
|
|
u8 tp = *p;
|
|
unsigned tlen = strlen((char*)&p[1]) + 1;
|
|
if (keyl == tlen && !memcmp(key, &p[1], tlen))
|
|
return &p[tlen + 1];
|
|
p += 1 + tlen;
|
|
if (tp == 3 || tp == 4)
|
|
p += bson_read_u32(p);
|
|
else if (tp == 5)
|
|
p += bson_read_u32(p) + 1 + 4;
|
|
else if (tp == 0x10)
|
|
p += 4;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
bool bson_read_int32(const u8 *srcp, const char *key, u32* value)
|
|
{
|
|
const u8* p = srcp ? bson_find_key(srcp, key) : NULL;
|
|
if (!p)
|
|
return false;
|
|
*value = bson_read_u32(p);
|
|
return true;
|
|
}
|
|
|
|
bool bson_read_int32_array(const u8 *srcp, const char *key, u32* value, unsigned cnt)
|
|
{
|
|
const u8* p = srcp ? bson_find_key(srcp, key) : NULL;
|
|
if (p) {
|
|
unsigned arrsz = bson_read_u32(p);
|
|
p += 4;
|
|
if (arrsz < 5)
|
|
return false;
|
|
arrsz = (arrsz - 5) >> 3;
|
|
while (arrsz--) {
|
|
p += 4; // type and name
|
|
*value++ = bson_read_u32(p);
|
|
p += 4; // value
|
|
}
|
|
return true;
|
|
}
|
|
*value = bson_read_u32(p);
|
|
return false;
|
|
}
|
|
|
|
bool bson_read_bytes(const u8 *srcp, const char *key, void* buffer, unsigned cnt)
|
|
{
|
|
const u8* p = srcp ? bson_find_key(srcp, key) : NULL;
|
|
if (p) {
|
|
unsigned bufsz = bson_read_u32(p);
|
|
if (bufsz != cnt)
|
|
return false;
|
|
|
|
// Skip byte array type and size
|
|
memcpy(buffer, &p[5], cnt);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool gba_load_state(const void* src)
|
|
{
|
|
u32 i, tmp;
|
|
u8* srcptr = (u8*)src;
|
|
u32 docsize = bson_read_u32(srcptr);
|
|
if (docsize != GBA_STATE_MEM_SIZE)
|
|
return false;
|
|
|
|
if (!bson_read_int32(srcptr, "info-magic", &tmp) || tmp != GBA_STATE_MAGIC)
|
|
return false;
|
|
if (!bson_read_int32(srcptr, "info-version", &tmp) || tmp != GBA_STATE_VERSION)
|
|
return false;
|
|
|
|
if (!(cpu_read_savestate(srcptr) &&
|
|
input_read_savestate(srcptr) &&
|
|
main_read_savestate(srcptr) &&
|
|
memory_read_savestate(srcptr) &&
|
|
sound_read_savestate(srcptr)))
|
|
{
|
|
// TODO: reset state instead! Should revert instead??
|
|
return false;
|
|
}
|
|
|
|
// Generate converted palette (since it is not saved)
|
|
for(i = 0; i < 512; i++)
|
|
{
|
|
palette_ram_converted[i] = convert_palette(eswap16(palette_ram[i]));
|
|
}
|
|
|
|
video_reload_counters();
|
|
|
|
// Reset most of the frame state and dynarec state
|
|
#ifdef HAVE_DYNAREC
|
|
if (dynarec_enable)
|
|
flush_dynarec_caches();
|
|
#endif
|
|
|
|
instruction_count = 0;
|
|
reg[COMPLETED_FRAME] = 0;
|
|
reg[OAM_UPDATED] = 1;
|
|
|
|
return true;
|
|
}
|
|
|
|
void gba_save_state(void* dst)
|
|
{
|
|
u8 *stptr = (u8*)dst;
|
|
u8 *wrptr = (u8*)dst;
|
|
|
|
// Initial bson size
|
|
bson_write_u32(wrptr, 0);
|
|
|
|
// Add some info fields
|
|
bson_write_int32(wrptr, "info-magic", GBA_STATE_MAGIC);
|
|
bson_write_int32(wrptr, "info-version", GBA_STATE_VERSION);
|
|
|
|
wrptr += cpu_write_savestate(wrptr);
|
|
wrptr += input_write_savestate(wrptr);
|
|
wrptr += main_write_savestate(wrptr);
|
|
wrptr += memory_write_savestate(wrptr);
|
|
wrptr += sound_write_savestate(wrptr);
|
|
|
|
// The padding space is pushed into a padding field for easy parsing
|
|
{
|
|
unsigned padsize = GBA_STATE_MEM_SIZE - (wrptr - stptr);
|
|
padsize -= 1 + 9 + 4 + 1 + 1;
|
|
*wrptr++ = 0x05; // Byte array
|
|
bson_write_cstring(wrptr, "zpadding");
|
|
bson_write_u32(wrptr, padsize);
|
|
*wrptr++ = 0;
|
|
wrptr += padsize;
|
|
}
|
|
|
|
*wrptr++ = 0;
|
|
|
|
// Update the doc size
|
|
bson_write_u32(stptr, wrptr - stptr);
|
|
}
|
|
|
|
|