diff --git a/desmume/src/saves.cpp b/desmume/src/saves.cpp index 50a4c56b4..f6ab2cd7e 100644 --- a/desmume/src/saves.cpp +++ b/desmume/src/saves.cpp @@ -36,95 +36,95 @@ #include "gfx3d.h" -//void*v is actually a void** which will be indirected before reading -//since this isnt supported right now, it is declared in here to make things compile +//void*v is actually a void** which will be indirected before reading +//since this isnt supported right now, it is declared in here to make things compile #define SS_INDIRECT 0x80000000 savestates_t savestates[NB_STATES]; #define SAVESTATE_VERSION 10 -static const char* magic = "DeSmuME SState\0"; +static const char* magic = "DeSmuME SState\0"; #ifndef MAX_PATH #define MAX_PATH 256 #endif -SFORMAT SF_ARM7[]={ - { &NDS_ARM7.instruction, 4|SS_RLSB, "7INS" }, - { &NDS_ARM7.instruct_adr, 4|SS_RLSB, "7INA" }, - { &NDS_ARM7.next_instruction, 4|SS_RLSB, "7INN" }, - { NDS_ARM7.R, 4|SS_MULT(16), "7REG" }, - { &NDS_ARM7.CPSR, 4|SS_RLSB, "7CPS" }, - { &NDS_ARM7.SPSR, 4|SS_RLSB, "7SPS" }, - { &NDS_ARM7.R13_usr, 4|SS_RLSB, "7DUS" }, - { &NDS_ARM7.R14_usr, 4|SS_RLSB, "7EUS" }, - { &NDS_ARM7.R13_svc, 4|SS_RLSB, "7DSV" }, - { &NDS_ARM7.R14_svc, 4|SS_RLSB, "7ESV" }, - { &NDS_ARM7.R13_abt, 4|SS_RLSB, "7DAB" }, - { &NDS_ARM7.R14_abt, 4|SS_RLSB, "7EAB" }, - { &NDS_ARM7.R13_und, 4|SS_RLSB, "7DUN" }, - { &NDS_ARM7.R14_und, 4|SS_RLSB, "7EUN" }, - { &NDS_ARM7.R13_irq, 4|SS_RLSB, "7DIR" }, - { &NDS_ARM7.R14_irq, 4|SS_RLSB, "7EIR" }, - { &NDS_ARM7.R8_fiq, 4|SS_RLSB, "78FI" }, - { &NDS_ARM7.R9_fiq, 4|SS_RLSB, "79FI" }, - { &NDS_ARM7.R10_fiq, 4|SS_RLSB, "7AFI" }, - { &NDS_ARM7.R11_fiq, 4|SS_RLSB, "7BFI" }, - { &NDS_ARM7.R12_fiq, 4|SS_RLSB, "7CFI" }, - { &NDS_ARM7.R13_fiq, 4|SS_RLSB, "7DFI" }, - { &NDS_ARM7.R14_fiq, 4|SS_RLSB, "7EFI" }, - { &NDS_ARM7.SPSR_svc, 4|SS_RLSB, "7SVC" }, - { &NDS_ARM7.SPSR_abt, 4|SS_RLSB, "7ABT" }, - { &NDS_ARM7.SPSR_und, 4|SS_RLSB, "7UND" }, - { &NDS_ARM7.SPSR_irq, 4|SS_RLSB, "7IRQ" }, - { &NDS_ARM7.SPSR_fiq, 4|SS_RLSB, "7FIQ" }, - { &NDS_ARM7.intVector, 4|SS_RLSB, "7int" }, - { &NDS_ARM7.LDTBit, 1, "7LDT" }, - { &NDS_ARM7.waitIRQ, 4|SS_RLSB, "7Wai" }, - { &NDS_ARM7.wIRQ, 4|SS_RLSB, "7wIR" }, - { &NDS_ARM7.wirq, 4|SS_RLSB, "7wir" }, - { 0 } +SFORMAT SF_ARM7[]={ + { &NDS_ARM7.instruction, 4|SS_RLSB, "7INS" }, + { &NDS_ARM7.instruct_adr, 4|SS_RLSB, "7INA" }, + { &NDS_ARM7.next_instruction, 4|SS_RLSB, "7INN" }, + { NDS_ARM7.R, 4|SS_MULT(16), "7REG" }, + { &NDS_ARM7.CPSR, 4|SS_RLSB, "7CPS" }, + { &NDS_ARM7.SPSR, 4|SS_RLSB, "7SPS" }, + { &NDS_ARM7.R13_usr, 4|SS_RLSB, "7DUS" }, + { &NDS_ARM7.R14_usr, 4|SS_RLSB, "7EUS" }, + { &NDS_ARM7.R13_svc, 4|SS_RLSB, "7DSV" }, + { &NDS_ARM7.R14_svc, 4|SS_RLSB, "7ESV" }, + { &NDS_ARM7.R13_abt, 4|SS_RLSB, "7DAB" }, + { &NDS_ARM7.R14_abt, 4|SS_RLSB, "7EAB" }, + { &NDS_ARM7.R13_und, 4|SS_RLSB, "7DUN" }, + { &NDS_ARM7.R14_und, 4|SS_RLSB, "7EUN" }, + { &NDS_ARM7.R13_irq, 4|SS_RLSB, "7DIR" }, + { &NDS_ARM7.R14_irq, 4|SS_RLSB, "7EIR" }, + { &NDS_ARM7.R8_fiq, 4|SS_RLSB, "78FI" }, + { &NDS_ARM7.R9_fiq, 4|SS_RLSB, "79FI" }, + { &NDS_ARM7.R10_fiq, 4|SS_RLSB, "7AFI" }, + { &NDS_ARM7.R11_fiq, 4|SS_RLSB, "7BFI" }, + { &NDS_ARM7.R12_fiq, 4|SS_RLSB, "7CFI" }, + { &NDS_ARM7.R13_fiq, 4|SS_RLSB, "7DFI" }, + { &NDS_ARM7.R14_fiq, 4|SS_RLSB, "7EFI" }, + { &NDS_ARM7.SPSR_svc, 4|SS_RLSB, "7SVC" }, + { &NDS_ARM7.SPSR_abt, 4|SS_RLSB, "7ABT" }, + { &NDS_ARM7.SPSR_und, 4|SS_RLSB, "7UND" }, + { &NDS_ARM7.SPSR_irq, 4|SS_RLSB, "7IRQ" }, + { &NDS_ARM7.SPSR_fiq, 4|SS_RLSB, "7FIQ" }, + { &NDS_ARM7.intVector, 4|SS_RLSB, "7int" }, + { &NDS_ARM7.LDTBit, 1, "7LDT" }, + { &NDS_ARM7.waitIRQ, 4|SS_RLSB, "7Wai" }, + { &NDS_ARM7.wIRQ, 4|SS_RLSB, "7wIR" }, + { &NDS_ARM7.wirq, 4|SS_RLSB, "7wir" }, + { 0 } }; -SFORMAT SF_ARM9[]={ - { &NDS_ARM9.instruction, 4|SS_RLSB, "9INS" }, - { &NDS_ARM9.instruct_adr, 4|SS_RLSB, "9INA" }, - { &NDS_ARM9.next_instruction, 4|SS_RLSB, "9INN" }, - { NDS_ARM9.R, 4|SS_MULT(16), "9REG" }, - { &NDS_ARM9.CPSR, 4|SS_RLSB, "9CPS" }, - { &NDS_ARM9.SPSR, 4|SS_RLSB, "9SPS" }, - { &NDS_ARM9.R13_usr, 4|SS_RLSB, "9DUS" }, - { &NDS_ARM9.R14_usr, 4|SS_RLSB, "9EUS" }, - { &NDS_ARM9.R13_svc, 4|SS_RLSB, "9DSV" }, - { &NDS_ARM9.R14_svc, 4|SS_RLSB, "9ESV" }, - { &NDS_ARM9.R13_abt, 4|SS_RLSB, "9DAB" }, - { &NDS_ARM9.R14_abt, 4|SS_RLSB, "9EAB" }, - { &NDS_ARM9.R13_und, 4|SS_RLSB, "9DUN" }, - { &NDS_ARM9.R14_und, 4|SS_RLSB, "9EUN" }, - { &NDS_ARM9.R13_irq, 4|SS_RLSB, "9DIR" }, - { &NDS_ARM9.R14_irq, 4|SS_RLSB, "9EIR" }, - { &NDS_ARM9.R8_fiq, 4|SS_RLSB, "98FI" }, - { &NDS_ARM9.R9_fiq, 4|SS_RLSB, "99FI" }, - { &NDS_ARM9.R10_fiq, 4|SS_RLSB, "9AFI" }, - { &NDS_ARM9.R11_fiq, 4|SS_RLSB, "9BFI" }, - { &NDS_ARM9.R12_fiq, 4|SS_RLSB, "9CFI" }, - { &NDS_ARM9.R13_fiq, 4|SS_RLSB, "9DFI" }, - { &NDS_ARM9.R14_fiq, 4|SS_RLSB, "9EFI" }, - { &NDS_ARM9.SPSR_svc, 4|SS_RLSB, "9SVC" }, - { &NDS_ARM9.SPSR_abt, 4|SS_RLSB, "9ABT" }, - { &NDS_ARM9.SPSR_und, 4|SS_RLSB, "9UND" }, - { &NDS_ARM9.SPSR_irq, 4|SS_RLSB, "9IRQ" }, - { &NDS_ARM9.SPSR_fiq, 4|SS_RLSB, "9FIQ" }, - { &NDS_ARM9.intVector, 4|SS_RLSB, "9int" }, - { &NDS_ARM9.LDTBit, 1, "9LDT" }, - { &NDS_ARM9.waitIRQ, 4|SS_RLSB, "9Wai" }, - { &NDS_ARM9.wIRQ, 4|SS_RLSB, "9wIR" }, - { &NDS_ARM9.wirq, 4|SS_RLSB, "9wir" }, - { 0 } +SFORMAT SF_ARM9[]={ + { &NDS_ARM9.instruction, 4|SS_RLSB, "9INS" }, + { &NDS_ARM9.instruct_adr, 4|SS_RLSB, "9INA" }, + { &NDS_ARM9.next_instruction, 4|SS_RLSB, "9INN" }, + { NDS_ARM9.R, 4|SS_MULT(16), "9REG" }, + { &NDS_ARM9.CPSR, 4|SS_RLSB, "9CPS" }, + { &NDS_ARM9.SPSR, 4|SS_RLSB, "9SPS" }, + { &NDS_ARM9.R13_usr, 4|SS_RLSB, "9DUS" }, + { &NDS_ARM9.R14_usr, 4|SS_RLSB, "9EUS" }, + { &NDS_ARM9.R13_svc, 4|SS_RLSB, "9DSV" }, + { &NDS_ARM9.R14_svc, 4|SS_RLSB, "9ESV" }, + { &NDS_ARM9.R13_abt, 4|SS_RLSB, "9DAB" }, + { &NDS_ARM9.R14_abt, 4|SS_RLSB, "9EAB" }, + { &NDS_ARM9.R13_und, 4|SS_RLSB, "9DUN" }, + { &NDS_ARM9.R14_und, 4|SS_RLSB, "9EUN" }, + { &NDS_ARM9.R13_irq, 4|SS_RLSB, "9DIR" }, + { &NDS_ARM9.R14_irq, 4|SS_RLSB, "9EIR" }, + { &NDS_ARM9.R8_fiq, 4|SS_RLSB, "98FI" }, + { &NDS_ARM9.R9_fiq, 4|SS_RLSB, "99FI" }, + { &NDS_ARM9.R10_fiq, 4|SS_RLSB, "9AFI" }, + { &NDS_ARM9.R11_fiq, 4|SS_RLSB, "9BFI" }, + { &NDS_ARM9.R12_fiq, 4|SS_RLSB, "9CFI" }, + { &NDS_ARM9.R13_fiq, 4|SS_RLSB, "9DFI" }, + { &NDS_ARM9.R14_fiq, 4|SS_RLSB, "9EFI" }, + { &NDS_ARM9.SPSR_svc, 4|SS_RLSB, "9SVC" }, + { &NDS_ARM9.SPSR_abt, 4|SS_RLSB, "9ABT" }, + { &NDS_ARM9.SPSR_und, 4|SS_RLSB, "9UND" }, + { &NDS_ARM9.SPSR_irq, 4|SS_RLSB, "9IRQ" }, + { &NDS_ARM9.SPSR_fiq, 4|SS_RLSB, "9FIQ" }, + { &NDS_ARM9.intVector, 4|SS_RLSB, "9int" }, + { &NDS_ARM9.LDTBit, 1, "9LDT" }, + { &NDS_ARM9.waitIRQ, 4|SS_RLSB, "9Wai" }, + { &NDS_ARM9.wIRQ, 4|SS_RLSB, "9wIR" }, + { &NDS_ARM9.wirq, 4|SS_RLSB, "9wir" }, + { 0 } }; -SFORMAT SF_MEM[]={ +SFORMAT SF_MEM[]={ { ARM9Mem.ARM9_ITCM, 0x8000, "ITCM" }, { ARM9Mem.ARM9_DTCM, 0x4000, "DTCM" }, { ARM9Mem.MAIN_MEM, 0x400000, "WRAM" }, @@ -276,146 +276,146 @@ int sram_save (const char *file_name) { } -static SFORMAT *CheckS(SFORMAT *sf, u32 tsize, char *desc) -{ - while(sf->v) - { - if(sf->s==~0) // Link to another SFORMAT structure. - { - SFORMAT *tmp; - if((tmp= CheckS((SFORMAT *)sf->v, tsize, desc) )) - return(tmp); - sf++; - continue; - } - if(!memcmp(desc,sf->desc,4)) - { - if(tsize!=(sf->s)) - return(0); - return(sf); - } - sf++; - } - return(0); +static SFORMAT *CheckS(SFORMAT *sf, u32 tsize, char *desc) +{ + while(sf->v) + { + if(sf->s==~0) // Link to another SFORMAT structure. + { + SFORMAT *tmp; + if((tmp= CheckS((SFORMAT *)sf->v, tsize, desc) )) + return(tmp); + sf++; + continue; + } + if(!memcmp(desc,sf->desc,4)) + { + if(tsize!=(sf->s)) + return(0); + return(sf); + } + sf++; + } + return(0); } -static bool ReadStateChunk(std::istream* is, SFORMAT *sf, int size) -{ - SFORMAT *tmp; - int temp = is->tellg(); - - while(is->tellg()read(toa,4); - if(is->fail()) - return false; - - read32le(&tsize,is); - int count = SS_UNMULT(tsize); - int size = tsize & ~SS_FLAGS; - bool rlsb = (count!=0); - - if((tmp=CheckS(sf,tsize,toa))) - { - - - if(count == 0) count=1; - - for(int i=0;is&SS_INDIRECT) - is->read(*(char **)tmp->v,size); - else - is->read((char *)tmp->v + i*size,size); - - #ifndef LOCAL_LE - if(rlsb) - FlipByteOrder((u8*)tmp->v + i*size,size); - #endif - } - } - else - is->seekg(size*count,std::ios::cur); - } // while(...) - return true; +static bool ReadStateChunk(std::istream* is, SFORMAT *sf, int size) +{ + SFORMAT *tmp; + int temp = is->tellg(); + + while(is->tellg()read(toa,4); + if(is->fail()) + return false; + + read32le(&tsize,is); + int count = SS_UNMULT(tsize); + int size = tsize & ~SS_FLAGS; + bool rlsb = (count!=0); + + if((tmp=CheckS(sf,tsize,toa))) + { + + + if(count == 0) count=1; + + for(int i=0;is&SS_INDIRECT) + is->read(*(char **)tmp->v,size); + else + is->read((char *)tmp->v + i*size,size); + + #ifndef LOCAL_LE + if(rlsb) + FlipByteOrder((u8*)tmp->v + i*size,size); + #endif + } + } + else + is->seekg(size*count,std::ios::cur); + } // while(...) + return true; } -static int SubWrite(std::ostream* os, SFORMAT *sf) -{ - uint32 acc=0; - - while(sf->v) - { - if(sf->s==~0) //Link to another struct - { - uint32 tmp; - - if(!(tmp=SubWrite(os,(SFORMAT *)sf->v))) - return(0); - acc+=tmp; - sf++; - continue; - } - - int count = SS_UNMULT(sf->s); - int size = sf->s & ~SS_FLAGS; - bool rlsb = (count!=0); - - acc+=8; //Description + size - - if(count==0) count=1; - - acc += count * size; - - if(os) //Are we writing or calculating the size of this block? - { - os->write(sf->desc,4); - write32le(sf->s,os); - - for(int i=0;iv,sf->s&(~SS_FLAGS)); - #endif - - if(sf->s&SS_INDIRECT) - os->write(*(char **)sf->v,size); - else - os->write((char*)sf->v + i*size,size); - - //Now restore the original byte order. - #ifndef LOCAL_LE - if(rlsb) - FlipByteOrder((u8*)sf->v,sf->s&(~SS_FLAGS)); - #endif - - } - } - sf++; - } - - return(acc); +static int SubWrite(std::ostream* os, SFORMAT *sf) +{ + uint32 acc=0; + + while(sf->v) + { + if(sf->s==~0) //Link to another struct + { + uint32 tmp; + + if(!(tmp=SubWrite(os,(SFORMAT *)sf->v))) + return(0); + acc+=tmp; + sf++; + continue; + } + + int count = SS_UNMULT(sf->s); + int size = sf->s & ~SS_FLAGS; + bool rlsb = (count!=0); + + acc+=8; //Description + size + + if(count==0) count=1; + + acc += count * size; + + if(os) //Are we writing or calculating the size of this block? + { + os->write(sf->desc,4); + write32le(sf->s,os); + + for(int i=0;iv,sf->s&(~SS_FLAGS)); + #endif + + if(sf->s&SS_INDIRECT) + os->write(*(char **)sf->v,size); + else + os->write((char*)sf->v + i*size,size); + + //Now restore the original byte order. + #ifndef LOCAL_LE + if(rlsb) + FlipByteOrder((u8*)sf->v,sf->s&(~SS_FLAGS)); + #endif + + } + } + sf++; + } + + return(acc); } -static int savestate_WriteChunk(std::ostream* os, int type, SFORMAT *sf) -{ - write32le(type,os); - if(!sf) return 4; - int bsize = SubWrite((std::ostream*)0,sf); - write32le(bsize,os); - FILE* outf; - - if(!SubWrite(os,sf)) - { - return 8; - } - return (bsize+8); +static int savestate_WriteChunk(std::ostream* os, int type, SFORMAT *sf) +{ + write32le(type,os); + if(!sf) return 4; + int bsize = SubWrite((std::ostream*)0,sf); + write32le(bsize,os); + FILE* outf; + + if(!SubWrite(os,sf)) + { + return 8; + } + return (bsize+8); } static void savestate_WriteChunk(std::ostream* os, int type, void (*saveproc)(std::ostream* os)) @@ -442,41 +442,49 @@ bool savestate_save(std::ostream* outstream, int compressionLevel) writechunks(os); ms.flush(); - //save the length of the file + //save the length of the file u32 len = ms.size(); - - u32 comprlen = -1; - u8* cbuf = (u8*)ms.buf(); + + u32 comprlen = -1; + u8* cbuf = (u8*)ms.buf(); #ifdef HAVE_LIBZ //compress the data - int error = Z_OK; - if(compressionLevel != Z_NO_COMPRESSION) - { - //worst case compression. - //zlib says "0.1% larger than sourceLen plus 12 bytes" - comprlen = (len>>9)+12 + len; - cbuf = new u8[comprlen]; - error = compress2(cbuf,&comprlen,(u8*)ms.buf(),len,compressionLevel); - } -#endif + int error = Z_OK; + if(compressionLevel != Z_NO_COMPRESSION) + { + //worst case compression. + //zlib says "0.1% larger than sourceLen plus 12 bytes" + comprlen = (len>>9)+12 + len; + cbuf = new u8[comprlen]; + error = compress2(cbuf,&comprlen,(u8*)ms.buf(),len,compressionLevel); + } +#endif - //dump the header - outstream->write(magic,16); - write32le(SAVESTATE_VERSION,outstream); - write32le(DESMUME_VERSION_NUMERIC,outstream); //desmume version - write32le(len,outstream); //uncompressed length - write32le(comprlen,outstream); //compressed length (-1 if it is not compressed) - - outstream->write((char*)cbuf,comprlen==-1?len:comprlen); - if(cbuf != (uint8*)ms.buf()) delete[] cbuf; - return error == Z_OK; + //dump the header + outstream->write(magic,16); + write32le(SAVESTATE_VERSION,outstream); + write32le(DESMUME_VERSION_NUMERIC,outstream); //desmume version + write32le(len,outstream); //uncompressed length + write32le(comprlen,outstream); //compressed length (-1 if it is not compressed) + + outstream->write((char*)cbuf,comprlen==-1?len:comprlen); + if(cbuf != (uint8*)ms.buf()) delete[] cbuf; +#ifdef HAVE_LIBZ + return error == Z_OK; +#else + return true; +#endif } bool savestate_save (const char *file_name) { memorystream ms; +#ifdef HAVE_LIBZ if(!savestate_save(&ms, Z_DEFAULT_COMPRESSION)) +#else + if(!savestate_save(&ms, 0)) +#endif return false; ms.flush(); FILE* file = fopen(file_name,"wb"); @@ -504,15 +512,15 @@ static void writechunks(std::ostream* os) { static bool ReadStateChunks(std::istream* is, s32 totalsize) { bool ret = true; - while(totalsize > 0) + while(totalsize > 0) { uint32 size; u32 t; if(!read32le(&t,is)) { ret=false; break; } if(t == 0xFFFFFFFF) goto done; if(!read32le(&size,is)) { ret=false; break; } - switch(t) - { + switch(t) + { case 1: if(!ReadStateChunk(is,SF_ARM9,size)) ret=false; break; case 2: if(!ReadStateChunk(is,SF_ARM7,size)) ret=false; break; case 3: if(!ReadStateChunk(is,SF_MEM,size)) ret=false; break; @@ -569,12 +577,14 @@ bool savestate_load(std::istream* is) is->read(&cbuf[0],comprlen); if(is->fail()) return false; - uLongf uncomprlen = len; - int error = uncompress((uint8*)&buf[0],&uncomprlen,(uint8*)&cbuf[0],comprlen); - if(error != Z_OK || uncomprlen != len) +#ifdef HAVE_LIBZ + uLongf uncomprlen = len; + int error = uncompress((uint8*)&buf[0],&uncomprlen,(uint8*)&cbuf[0],comprlen); + if(error != Z_OK || uncomprlen != len) return false; +#endif } else { - is->read((char*)&buf[0],len); + is->read((char*)&buf[0],len); } memorystream mstemp(&buf);