static int ReadStateChunk(StateMem *st, SFORMAT *sf, int size, int data_only) { SFORMAT *tmp; int temp; if(data_only) { DOReadChunk(st, sf); } else { temp = smem_tell(st); while(smem_tell(st) < temp + size) { uint32 tsize; char toa[32]; if(smem_read(st, toa, 32) <= 0) { puts("Unexpected EOF?"); return 0; } smem_read32le(st, &tsize); if((tmp=CheckS(sf,tsize,toa))) { int32 bytesize = tmp->s&(~(MDFNSTATE_RLSB32 | MDFNSTATE_RLSB16 | RLSB)); smem_read(st, (uint8 *)tmp->v, bytesize); if(tmp->s & MDFNSTATE_RLSB32) Endian_A32_LE_to_NE(tmp->v, bytesize / sizeof(uint32)); else if(tmp->s & MDFNSTATE_RLSB16) Endian_A16_LE_to_NE(tmp->v, bytesize / sizeof(uint16)); else if(tmp->s&RLSB) Endian_V_LE_to_NE(tmp->v, bytesize); } else if(smem_seek(st,tsize,SEEK_CUR) < 0) { puts("Seek error"); return(0); } } // while(...) } return 1; }
static int ReadStateChunk(StateMem *st, SFORMAT *sf, int size) { int temp = st->loc; while (st->loc < (temp + size)) { uint32_t recorded_size; // In bytes uint8_t 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); SFORMAT *tmp = FindSF((char*)toa + 1, sf); if(tmp) { uint32_t 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 { smem_read(st, (uint8_t *)tmp->v, expected_size); if(tmp->flags & MDFNSTATE_BOOL) { // Converting downwards is necessary for the case of sizeof(bool) > 1 for(int32_t bool_monster = expected_size - 1; bool_monster >= 0; bool_monster--) { ((bool *)tmp->v)[bool_monster] = ((uint8_t *)tmp->v)[bool_monster]; } } #ifdef MSB_FIRST if(tmp->flags & MDFNSTATE_RLSB64) Endian_A64_LE_to_NE(tmp->v, expected_size / sizeof(uint64_t)); else if(tmp->flags & MDFNSTATE_RLSB32) Endian_A32_LE_to_NE(tmp->v, expected_size / sizeof(uint32_t)); else if(tmp->flags & MDFNSTATE_RLSB16) Endian_A16_LE_to_NE(tmp->v, expected_size / sizeof(uint16_t)); else if(tmp->flags & RLSB) Endian_V_LE_to_NE(tmp->v, expected_size); #endif } } 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(...) assert(st->loc == (temp + size)); return 1; }
static bool SubWrite(StateMem *st, SFORMAT *sf, const char *name_prefix = NULL) { 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_t)~0) /* Link to another struct. */ { if(!SubWrite(st, (SFORMAT *)sf->v, name_prefix)) return(0); sf++; continue; } int32_t bytesize = sf->size; char nameo[1 + 256]; int slen; slen = snprintf(nameo + 1, 256, "%s%s", name_prefix ? name_prefix : "", sf->name); nameo[0] = slen; if(slen >= 255) { printf("Warning: state variable name possibly too long: %s %s %s %d\n", sf->name, name_prefix, nameo, slen); slen = 255; } smem_write(st, nameo, 1 + nameo[0]); smem_write32le(st, bytesize); #ifdef MSB_FIRST /* Flip the byte order... */ if(sf->flags & MDFNSTATE_BOOL) { } else if(sf->flags & MDFNSTATE_RLSB64) Endian_A64_NE_to_LE(sf->v, bytesize / sizeof(uint64_t)); else if(sf->flags & MDFNSTATE_RLSB32) Endian_A32_NE_to_LE(sf->v, bytesize / sizeof(uint32_t)); else if(sf->flags & MDFNSTATE_RLSB16) Endian_A16_NE_to_LE(sf->v, bytesize / sizeof(uint16_t)); else if(sf->flags & RLSB) Endian_V_NE_to_LE(sf->v, bytesize); #endif // Special case for the evil bool type, to convert bool to 1-byte elements. // Don't do it if we're only saving the raw data. if(sf->flags & MDFNSTATE_BOOL) { for(int32_t bool_monster = 0; bool_monster < bytesize; bool_monster++) { uint8_t tmp_bool = ((bool *)sf->v)[bool_monster]; //printf("Bool write: %.31s\n", sf->name); smem_write(st, &tmp_bool, 1); } } else smem_write(st, (uint8_t *)sf->v, bytesize); #ifdef MSB_FIRST /* Now restore the original byte order. */ if(sf->flags & MDFNSTATE_BOOL) { } else if(sf->flags & MDFNSTATE_RLSB64) Endian_A64_LE_to_NE(sf->v, bytesize / sizeof(uint64_t)); else if(sf->flags & MDFNSTATE_RLSB32) Endian_A32_LE_to_NE(sf->v, bytesize / sizeof(uint32_t)); else if(sf->flags & MDFNSTATE_RLSB16) Endian_A16_LE_to_NE(sf->v, bytesize / sizeof(uint16_t)); else if(sf->flags & RLSB) Endian_V_LE_to_NE(sf->v, bytesize); #endif sf++; } return true; }
static int SubWrite(StateMem *st, SFORMAT *sf, int data_only, gzFile fp) { uint32 acc=0; // FIXME? It's kind of slow, and we definitely don't want it on with state rewinding... //ValidateSFStructure(sf); while(sf->s || sf->desc) // Size can sometimes be zero, so also check for the text description. These two should both be zero only at the end of a struct. { if(!sf->s || !sf->v) { sf++; continue; } if(sf->s == (uint32)~0) /* Link to another struct. */ { uint32 tmp; if(!(tmp=SubWrite(st,(SFORMAT *)sf->v, data_only, fp))) return(0); acc+=tmp; sf++; continue; } if(!data_only) acc+=32 + 4; /* Description + size */ int32 bytesize = sf->s&(~(MDFNSTATE_RLSB32 | MDFNSTATE_RLSB16 | RLSB)); acc += bytesize; //printf("%d %d %d\n", bytesize, data_only, fp); if(st || fp) /* Are we writing or calculating the size of this block? */ { if(!data_only) { char desco[32]; int slen = strlen(sf->desc); memset(desco, 0, 32); if(slen > 32) { printf("Warning: state variable name too long: %s %d\n", sf->desc, slen); slen = 32; } memcpy(desco, sf->desc, slen); smem_write(st, desco, 32); smem_write32le(st, bytesize); /* Flip the byte order... */ if(sf->s & MDFNSTATE_RLSB32) Endian_A32_NE_to_LE(sf->v, bytesize / sizeof(uint32)); else if(sf->s & MDFNSTATE_RLSB16) Endian_A16_NE_to_LE(sf->v, bytesize / sizeof(uint16)); else if(sf->s&RLSB) Endian_V_NE_to_LE(sf->v, bytesize); } if(fp) { //printf("Wrote: %d\n", bytesize); gzwrite(fp, sf->v, bytesize); } else { smem_write(st, (uint8 *)sf->v, bytesize); } if(!data_only) { /* Now restore the original byte order. */ if(sf->s & MDFNSTATE_RLSB32) Endian_A32_LE_to_NE(sf->v, bytesize / sizeof(uint32)); else if(sf->s & MDFNSTATE_RLSB16) Endian_A16_LE_to_NE(sf->v, bytesize / sizeof(uint16)); else if(sf->s&RLSB) Endian_V_LE_to_NE(sf->v, bytesize); } } sf++; } return(acc); }
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 bool SubWrite(StateMem *st, SFORMAT *sf, int data_only, const char *name_prefix = NULL) { // FIXME? It's kind of slow, and we definitely don't want it on with state rewinding... //if(!data_only) // ValidateSFStructure(sf); 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 struct. */ { if(!SubWrite(st, (SFORMAT *)sf->v, data_only, name_prefix)) return(0); sf++; continue; } int32 bytesize = sf->size; // If we're only saving the raw data, and we come across a bool type, we save it as it is in memory, rather than converting it to // 1-byte. In the SFORMAT structure, the size member for bool entries is the number of bool elements, not the total in-memory size, // so we adjust it here. if(data_only && (sf->flags & MDFNSTATE_BOOL)) { bytesize *= sizeof(bool); } if(!data_only) { char nameo[1 + 256]; int slen; slen = snprintf(nameo + 1, 256, "%s%s", name_prefix ? name_prefix : "", sf->name); nameo[0] = slen; if(slen >= 255) { printf("Warning: state variable name possibly too long: %s %s %s %d\n", sf->name, name_prefix, nameo, slen); slen = 255; } smem_write(st, nameo, 1 + nameo[0]); smem_write32le(st, bytesize); /* Flip the byte order... */ if(sf->flags & MDFNSTATE_BOOL) { } else if(sf->flags & MDFNSTATE_RLSB64) Endian_A64_NE_to_LE(sf->v, bytesize / sizeof(uint64)); else if(sf->flags & MDFNSTATE_RLSB32) Endian_A32_NE_to_LE(sf->v, bytesize / sizeof(uint32)); else if(sf->flags & MDFNSTATE_RLSB16) Endian_A16_NE_to_LE(sf->v, bytesize / sizeof(uint16)); else if(sf->flags & RLSB) Endian_V_NE_to_LE(sf->v, bytesize); } // Special case for the evil bool type, to convert bool to 1-byte elements. // Don't do it if we're only saving the raw data. if((sf->flags & MDFNSTATE_BOOL) && !data_only) { for(int32 bool_monster = 0; bool_monster < bytesize; bool_monster++) { uint8 tmp_bool = ((bool *)sf->v)[bool_monster]; //printf("Bool write: %.31s\n", sf->name); smem_write(st, &tmp_bool, 1); } } else smem_write(st, (uint8 *)sf->v, bytesize); if(!data_only) { /* Now restore the original byte order. */ if(sf->flags & MDFNSTATE_BOOL) { } else if(sf->flags & MDFNSTATE_RLSB64) Endian_A64_LE_to_NE(sf->v, bytesize / sizeof(uint64)); else if(sf->flags & MDFNSTATE_RLSB32) Endian_A32_LE_to_NE(sf->v, bytesize / sizeof(uint32)); else if(sf->flags & MDFNSTATE_RLSB16) Endian_A16_LE_to_NE(sf->v, bytesize / sizeof(uint16)); else if(sf->flags & RLSB) Endian_V_LE_to_NE(sf->v, bytesize); } sf++; } return(TRUE); }
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; }