static void MakeSFMap(SFORMAT *sf, SFMap_t &sfmap) { while(sf->size || sf->name) // Size can sometimes be zero, so also check for the text name. These two should both be zero only at the end of a struct. { if(!sf->size || !sf->v) { sf++; continue; } if(sf->size == (uint32)~0) /* Link to another SFORMAT structure. */ MakeSFMap((SFORMAT *)sf->v, sfmap); else { assert(sf->name); if(sfmap.find(sf->name) != sfmap.end()) printf("Duplicate save state variable in internal emulator structures(CLUB THE PROGRAMMERS WITH BREADSTICKS): %s\n", sf->name); sfmap[sf->name] = sf; } sf++; } }
static int ReadStateChunk(StateMem *st, SFORMAT *sf, int size, int data_only) { int temp; if(data_only) { DOReadChunk(st, sf); } else { SFMap_t sfmap; SFMap_t sfmap_found; // Used for identify variables that are missing in the save state. MakeSFMap(sf, sfmap); temp = smem_tell(st); while(smem_tell(st) < (temp + size)) { uint32 tsize; char toa[1 + 256]; if(smem_read(st, toa, 1) != 1) { puts("Unexpected EOF"); return(0); } if(smem_read(st, toa + 1, toa[0]) != toa[0]) { puts("Unexpected EOF?"); return 0; } toa[1 + toa[0]] = 0; smem_read32le(st, &tsize); SFMap_t::iterator sfmit; sfmit = sfmap.find(toa + 1); if(sfmit != sfmap.end()) { SFORMAT *tmp = sfmit->second; int32 bytesize = tmp->size; sfmap_found[tmp->name] = tmp; smem_read(st, (uint8 *)tmp->v, bytesize); if(tmp->flags & MDFNSTATE_BOOL) { // Converting downwards is necessary for the case of sizeof(bool) > 1 for(int32 bool_monster = bytesize - 1; bool_monster >= 0; bool_monster--) { ((bool *)tmp->v)[bool_monster] = (bool)((uint8 *)tmp->v)[bool_monster]; } } if(tmp->flags & MDFNSTATE_RLSB64) Endian_A64_LE_to_NE(tmp->v, bytesize / sizeof(uint64)); else if(tmp->flags & MDFNSTATE_RLSB32) Endian_A32_LE_to_NE(tmp->v, bytesize / sizeof(uint32)); else if(tmp->flags & MDFNSTATE_RLSB16) Endian_A16_LE_to_NE(tmp->v, bytesize / sizeof(uint16)); else if(tmp->flags & RLSB) Endian_V_LE_to_NE(tmp->v, bytesize); } else { printf("Unknown variable in save state: %s\n", toa + 1); if(smem_seek(st, tsize, SEEK_CUR) < 0) { puts("Seek error"); return(0); } } } // while(...) for(SFMap_t::const_iterator it = sfmap.begin(); it != sfmap.end(); it++) { if(sfmap_found.find(it->second->name) == sfmap_found.end()) { printf("Variable missing from save state: %s\n", it->second->name); } } assert(smem_tell(st) == (temp + size)); } return 1; }
static int ReadStateChunk(StateMem *st, SFORMAT *sf, int size) { int temp; { SFMap_t sfmap; SFMap_t sfmap_found; // Used for identifying variables that are missing in the save state. MakeSFMap(sf, sfmap); temp = smem_tell(st); while(smem_tell(st) < (temp + size)) { uint32 recorded_size; // In bytes uint8 toa[1 + 256]; // Don't change to char unless cast toa[0] to unsigned to smem_read() and other places. if(smem_read(st, toa, 1) != 1) { puts("Unexpected EOF"); return(0); } if(smem_read(st, toa + 1, toa[0]) != toa[0]) { puts("Unexpected EOF?"); return 0; } toa[1 + toa[0]] = 0; smem_read32le(st, &recorded_size); SFMap_t::iterator sfmit; sfmit = sfmap.find((char *)toa + 1); if(sfmit != sfmap.end()) { SFORMAT *tmp = sfmit->second; uint32 expected_size = tmp->size; // In bytes if(recorded_size != expected_size) { printf("Variable in save state wrong size: %s. Need: %d, got: %d\n", toa + 1, expected_size, recorded_size); if(smem_seek(st, recorded_size, SEEK_CUR) < 0) { puts("Seek error"); return(0); } } else { sfmap_found[tmp->name] = tmp; smem_read(st, (uint8 *)tmp->v, expected_size); if(tmp->flags & MDFNSTATE_BOOL) { // Converting downwards is necessary for the case of sizeof(bool) > 1 for(int32 bool_monster = expected_size - 1; bool_monster >= 0; bool_monster--) { ((bool *)tmp->v)[bool_monster] = ((uint8 *)tmp->v)[bool_monster]; } } if(tmp->flags & MDFNSTATE_RLSB64) Endian_A64_LE_to_NE(tmp->v, expected_size / sizeof(uint64)); else if(tmp->flags & MDFNSTATE_RLSB32) Endian_A32_LE_to_NE(tmp->v, expected_size / sizeof(uint32)); else if(tmp->flags & MDFNSTATE_RLSB16) Endian_A16_LE_to_NE(tmp->v, expected_size / sizeof(uint16)); else if(tmp->flags & RLSB) Endian_V_LE_to_NE(tmp->v, expected_size); } } else { printf("Unknown variable in save state: %s\n", toa + 1); if(smem_seek(st, recorded_size, SEEK_CUR) < 0) { puts("Seek error"); return(0); } } } // while(...) for(SFMap_t::const_iterator it = sfmap.begin(); it != sfmap.end(); it++) { if(sfmap_found.find(it->second->name) == sfmap_found.end()) { printf("Variable missing from save state: %s\n", it->second->name); } } assert(smem_tell(st) == (temp + size)); } return 1; }
static void ReadStateChunk(Stream *st, SFORMAT *sf, uint32 size, const bool svbe) { SFMap_t sfmap; SFMap_t sfmap_found; // Used for identifying variables that are missing in the save state. MakeSFMap(sf, sfmap); uint64 temp = st->tell(); while(st->tell() < (temp + size)) { uint32 recorded_size; // In bytes uint8 toa[1 + 256]; // Don't change to char unless cast toa[0] to unsigned to smem_read() and other places. st->read(toa, 1); st->read(toa + 1, toa[0]); toa[1 + toa[0]] = 0; recorded_size = st->get_LE<uint32>(); SFMap_t::iterator sfmit; sfmit = sfmap.find((char *)toa + 1); if(sfmit != sfmap.end()) { SFORMAT *tmp = sfmit->second; uint32 expected_size = tmp->size; // In bytes if(recorded_size != expected_size) { // Don't error out(throw), but still printf-log it. printf("Variable in save state wrong size: %s. Need: %u, got: %u\n", toa + 1, expected_size, recorded_size); st->seek(recorded_size, SEEK_CUR); } else { sfmap_found[tmp->name] = tmp; st->read((uint8 *)tmp->v, expected_size); if(tmp->flags & MDFNSTATE_BOOL) { // Converting downwards is necessary for the case of sizeof(bool) > 1 for(int32 bool_monster = expected_size - 1; bool_monster >= 0; bool_monster--) { ((bool *)tmp->v)[bool_monster] = ((uint8 *)tmp->v)[bool_monster]; } } else { if(svbe) { if(tmp->flags & MDFNSTATE_RLSB64) Endian_A64_NE_BE(tmp->v, expected_size / sizeof(uint64)); else if(tmp->flags & MDFNSTATE_RLSB32) Endian_A32_NE_BE(tmp->v, expected_size / sizeof(uint32)); else if(tmp->flags & MDFNSTATE_RLSB16) Endian_A16_NE_BE(tmp->v, expected_size / sizeof(uint16)); else if(tmp->flags & MDFNSTATE_RLSB) Endian_V_NE_BE(tmp->v, expected_size); } else { if(tmp->flags & MDFNSTATE_RLSB64) Endian_A64_NE_LE(tmp->v, expected_size / sizeof(uint64)); else if(tmp->flags & MDFNSTATE_RLSB32) Endian_A32_NE_LE(tmp->v, expected_size / sizeof(uint32)); else if(tmp->flags & MDFNSTATE_RLSB16) Endian_A16_NE_LE(tmp->v, expected_size / sizeof(uint16)); else if(tmp->flags & MDFNSTATE_RLSB) Endian_V_NE_LE(tmp->v, expected_size); } } } } else { printf("Unknown variable in save state: %s\n", toa + 1); st->seek(recorded_size, SEEK_CUR); } } // while(...) for(SFMap_t::const_iterator it = sfmap.begin(); it != sfmap.end(); it++) { if(sfmap_found.find(it->second->name) == sfmap_found.end()) { printf("Variable of bytesize %u missing from save state: %s\n", it->second->size, it->second->name); } } }