X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=fceu.git;a=blobdiff_plain;f=state.c;h=ab2f0c92492ffcea10c244cb7e931e208a5ddfe9;hp=871ef80c02a7caaf2b330d2b3bd0367ef8077413;hb=ed531dd606f7ea4558517576afee38253450d1c3;hpb=22f08d9598e12f15de5e3c2f503c2ad1298dcc17 diff --git a/state.c b/state.c index 871ef80..ab2f0c9 100644 --- a/state.c +++ b/state.c @@ -24,6 +24,9 @@ #include #include #include +#ifdef GP2X +#include +#endif #include "types.h" #include "x6502.h" @@ -40,59 +43,46 @@ #include "memory.h" #include "ppu.h" -static SFORMAT SFMDATA[64]; +static void (*SPreSave)(void) = 0; +static void (*SPostSave)(void) = 0; + +#define SFMDATA_SIZE (64) +static SFORMAT SFMDATA[SFMDATA_SIZE]; static int SFEXINDEX; static int stateversion; -#define RLSB 0x80000000 +extern SFORMAT FCEUPPU_STATEINFO[]; // 3 +extern SFORMAT FCEUCTRL_STATEINFO[]; // 4 -#define SFCPUELEMENTS 7 - -SFORMAT SFCPU[SFCPUELEMENTS]={ +SFORMAT SFCPU[]={ // 1 { &X.PC, 2|RLSB, "PC\0"}, { &X.A, 1, "A\0\0"}, { &X.P, 1, "P\0\0"}, { &X.X, 1, "X\0\0"}, { &X.Y, 1, "Y\0\0"}, { &X.S, 1, "S\0\0"}, - { RAM, 0x800, "RAM"} + { RAM, 0x800, "RAM"}, + { 0, } }; -#define SFCPUCELEMENTS 6 -SFORMAT SFCPUC[SFCPUCELEMENTS]={ +SFORMAT SFCPUC[]={ // 2 { &X.jammed, 1, "JAMM"}, { &X.IRQlow, 1, "IRQL"}, { &X.tcount, 4|RLSB, "ICoa"}, { &X.count, 4|RLSB, "ICou"}, { ×tamp, 4|RLSB, "TIME"}, - { ×tampbase, 8|RLSB, "TMEB"} + { ×tampbase, 8|RLSB, "TMEB"}, + // from 0.98.15 + { ×tampbase, sizeof(timestampbase) | RLSB, "TSBS"}, // size seems to match? + { &X.mooPI, 1, "MooP"}, // alternative to the "quick and dirty hack" + // TODO: IQLB? + { 0, } }; -static uint16 TempAddrT,RefreshAddrT; - -#define SFPPUELEMENTS 10 -SFORMAT SFPPU[SFPPUELEMENTS]={ - { NTARAM, 0x800, "NTAR"}, - { PALRAM, 0x20, "PRAM"}, - { SPRAM, 0x100, "SPRA"}, - { PPU, 0x4, "PPUR"}, - { &XOffset, 1, "XOFF"}, - { &vtoggle, 1, "VTOG"}, - { &RefreshAddrT, 2|RLSB, "RADD"}, - { &TempAddrT, 2|RLSB, "TADD"}, - { &VRAMBuffer, 1, "VBUF"}, - { &PPUGenLatch, 1, "PGEN"}, -}; +extern uint16 TempAddrT,RefreshAddrT; -// Is this chunk necessary? I'll fix it later. -//#define SFCTLRELEMENTS 2 -//SFORMAT SFCTLR[SFCTLRELEMENTS]={ -// { &joy_readbit, 1, "J1RB"}, -// { &joy2_readbit, 1, "J2RB"} -//}; -#define SFSNDELEMENTS 18 -SFORMAT SFSND[SFSNDELEMENTS]={ +SFORMAT SFSND[]={ { &fhcnt, 4|RLSB,"FHCN"}, { &fcnt, 1, "FCNT"}, { PSG, 14, "PSG"}, @@ -110,139 +100,135 @@ SFORMAT SFSND[SFSNDELEMENTS]={ { DecCountTo1, 3,"DCT1"}, { &PCMBitIndex, 1,"PBIN"}, { &PCMAddressIndex, 4|RLSB, "PAIN"}, - { &PCMSizeIndex, 4|RLSB, "PSIN"} + { &PCMSizeIndex, 4|RLSB, "PSIN"}, + { 0, } }; -int WriteStateChunk(FILE *st, int type, SFORMAT *sf, int count) -{ - int bsize; - int x; - fputc(type,st); +static int SubWrite(FILE *st, SFORMAT *sf) +{ + uint32 acc=0; - for(x=bsize=0;xv) { - fwrite(sf[x].desc,1,4,st); - write32(sf[x].s&(~RLSB),st); - #ifdef LSB_FIRST - fwrite((uint8 *)sf[x].v,1,sf[x].s&(~RLSB),st); - #else + if(sf->s==~0) /* Link to another struct. */ { - int z; - if(sf[x].s&RLSB) - { - for(z=(sf[x].s&(~RLSB))-1;z>=0;z--) - { - fputc(*(uint8*)sf[x].v,st); - } + uint32 tmp; + + if(!(tmp=SubWrite(st,(SFORMAT *)sf->v))) + return(0); + acc+=tmp; + sf++; + continue; } - else - fwrite((uint8 *)sf[x].v,1,sf[x].s&(~RLSB),st); + + acc+=8; /* Description + size */ + acc+=sf->s&(~RLSB); + + if(st) /* Are we writing or calculating the size of this block? */ + { + fwrite(sf->desc,1,4,st); + write32le(sf->s&(~RLSB),st); + + #ifndef LSB_FIRST + if(sf->s&RLSB) + FlipByteOrder(sf->v,sf->s&(~RLSB)); + #endif + + fwrite((uint8 *)sf->v,1,sf->s&(~RLSB),st); + /* Now restore the original byte order. */ + #ifndef LSB_FIRST + if(sf->s&RLSB) + FlipByteOrder(sf->v,sf->s&(~RLSB)); + #endif } - #endif + sf++; } - return (bsize+5); + + return(acc); } -int ReadStateChunk(FILE *st, SFORMAT *sf, int count, int size) +static int WriteStateChunk(FILE *st, int type, SFORMAT *sf) { - uint8 tmpyo[16]; int bsize; - int x; - for(x=bsize=0;x=53) - bsize+=count<<3; - else + fputc(type,st); + + bsize=SubWrite(0,sf); + write32le(bsize,st); + + if(!SubWrite(st,sf)) + { + return(0); + } + return (bsize+5); +} + +static SFORMAT *CheckS(SFORMAT *sf, uint32 tsize, char *desc) +{ + while(sf->v) { - if(bsize!=size) + if(sf->s==~0) /* Link to another SFORMAT structure. */ { - fseek(st,size,SEEK_CUR); - return 0; + SFORMAT *tmp; + if((tmp= CheckS((SFORMAT *)sf->v, tsize, desc) )) + return(tmp); + sf++; + continue; } + if(!memcmp(desc,sf->desc,4)) + { + if(tsize!=(sf->s&(~RLSB))) + { + printf("ReadStateChunk: sect \"%c%c%c%c\" has wrong size\n", desc[0], desc[1], desc[2], desc[3]); + return(0); + } + return(sf); + } + sf++; } + return(0); +} - if(stateversion<56) - memcpy(tmpyo,mapbyte3,16); +static int ReadStateChunk(FILE *st, SFORMAT *sf, int size) +{ + //if(scan_chunks) + // return fseek(st,size,SEEK_CUR) == 0; - if(stateversion>=53) - { - int temp; - temp=ftell(st); + SFORMAT *tmp; + int temp; + temp=ftell(st); - while(ftell(st)=0;z--) - *(uint8*)sf[x].v=fgetc(st); - } - else - #endif - { - fread((uint8 *)sf[x].v,1,sf[x].s&(~RLSB),st); - } - goto bloo; - } - } - nkayo: - fseek(st,tsize,SEEK_CUR); - bloo:; - } // while(...) - } // >=53 - else - { - for(x=0;x=0;z--) - { - *(uint8*)sf[x].v=fgetc(st); - } - else - fread((uint8 *)sf[x].v,1,sf[x].s&(~RLSB),st); + fread((uint8 *)tmp->v,1,tmp->s&(~RLSB),st); + + #ifndef LSB_FIRST + if(tmp->s&RLSB) + FlipByteOrder(tmp->v,tmp->s&(~RLSB)); #endif } - } - if(stateversion<56) - { - for(x=0;x<16;x++) - #ifdef LSB_FIRST - mapbyte1[x]=mapbyte1[x<<1]; - #else - mapbyte1[x]=mapbyte1[(x<<1)+1]; - #endif - memcpy(mapbyte3,tmpyo,16); - } + else + { + fseek(st,tsize,SEEK_CUR); + printf("ReadStateChunk: sect \"%c%c%c%c\" not handled\n", toa[0], toa[1], toa[2], toa[3]); + } + } // while(...) return 1; } -int ReadStateChunks(FILE *st) + +static int ReadStateChunks(FILE *st) { int t; uint32 size; @@ -253,20 +239,27 @@ for(;;) t=fgetc(st); if(t==EOF) break; if(!read32(&size,st)) break; + + // printf("ReadStateChunks: chunk %i\n", t); switch(t) { - case 1:if(!ReadStateChunk(st,SFCPU,SFCPUELEMENTS,size)) ret=0;break; - case 2:if(!ReadStateChunk(st,SFCPUC,SFCPUCELEMENTS,size)) ret=0; + case 1:if(!ReadStateChunk(st,SFCPU,size)) ret=0; +#ifdef ASM_6502 + asmcpu_unpack(); +#endif + break; + case 2:if(!ReadStateChunk(st,SFCPUC,size)) ret=0; else { X.mooPI=X.P; // Quick and dirty hack. } break; - case 3:if(!ReadStateChunk(st,SFPPU,SFPPUELEMENTS,size)) ret=0;break; -// case 4:if(!ReadStateChunk(st,SFCTLR,SFCTLRELEMENTS,size)) ret=0;break; - case 5:if(!ReadStateChunk(st,SFSND,SFSNDELEMENTS,size)) ret=0;break; - case 0x10:if(!ReadStateChunk(st,SFMDATA,SFEXINDEX,size)) ret=0;break; - default: if(fseek(st,size,SEEK_CUR)<0) goto endo;break; + case 3:if(!ReadStateChunk(st,FCEUPPU_STATEINFO,size)) ret=0;break; + case 4:if(!ReadStateChunk(st,FCEUCTRL_STATEINFO,size)) ret=0;break; + case 5:if(!ReadStateChunk(st,SFSND,size)) ret=0;break; + case 0x10:if(!ReadStateChunk(st,SFMDATA,size)) ret=0;break; + default:printf("ReadStateChunks: unknown chunk: %i\n", t); + if(fseek(st,size,SEEK_CUR)<0) goto endo;break; } } endo: @@ -279,6 +272,7 @@ extern int geniestage; void SaveState(void) { FILE *st=NULL; + char *fname; TempAddrT=TempAddr; RefreshAddrT=RefreshAddr; @@ -289,27 +283,39 @@ void SaveState(void) return; } - st=fopen(FCEU_MakeFName(FCEUMKF_STATE,CurrentState,0),"wb"); + fname = FCEU_MakeFName(FCEUMKF_STATE,CurrentState,0); + st=fopen(fname,"wb"); + free(fname); if(st!=NULL) { - static uint32 totalsize; - static uint8 header[16]="FCS"; - memset(header+4,0,13); + uint32 totalsize; + uint8 header[16]="FCS"; + memset(header+4,0,sizeof(header)-4); header[3]=VERSION_NUMERIC; fwrite(header,1,16,st); - totalsize=WriteStateChunk(st,1,SFCPU,SFCPUELEMENTS); - totalsize+=WriteStateChunk(st,2,SFCPUC,SFCPUCELEMENTS); - totalsize+=WriteStateChunk(st,3,SFPPU,SFPPUELEMENTS); - // totalsize+=WriteStateChunk(st,4,SFCTLR,SFCTLRELEMENTS); - totalsize+=WriteStateChunk(st,5,SFSND,SFSNDELEMENTS); - totalsize+=WriteStateChunk(st,0x10,SFMDATA,SFEXINDEX); +#ifdef ASM_6502 + asmcpu_pack(); +#endif + totalsize=WriteStateChunk(st,1,SFCPU); + totalsize+=WriteStateChunk(st,2,SFCPUC); + totalsize+=WriteStateChunk(st,3,FCEUPPU_STATEINFO); + totalsize+=WriteStateChunk(st,4,FCEUCTRL_STATEINFO); + totalsize+=WriteStateChunk(st,5,SFSND); + + + if(SPreSave) SPreSave(); + totalsize+=WriteStateChunk(st,0x10,SFMDATA); + if(SPostSave) SPostSave(); fseek(st,4,SEEK_SET); write32(totalsize,st); SaveStateStatus[CurrentState]=1; fclose(st); +#ifdef GP2X + sync(); +#endif FCEU_DispMessage("State %d saved.",CurrentState); } else @@ -317,19 +323,9 @@ void SaveState(void) } static int LoadStateOld(FILE *st); -void LoadState(void) +int FCEUSS_LoadFP(FILE *st, int make_backup) { int x; - FILE *st=NULL; - - if(geniestage==1) - { - FCEU_DispMessage("Cannot load FCS in GG screen."); - return; - } - - st=fopen(FCEU_MakeFName(FCEUMKF_STATE,CurrentState,0),"rb"); - if(st!=NULL) { uint8 header[16]; @@ -368,12 +364,40 @@ void LoadState(void) lerror: FCEU_DispMessage("State %d load error.",CurrentState); SaveStateStatus[CurrentState]=0; - return; + return 0; + } + return 1; +} + +void LoadState(void) +{ + FILE *st=NULL; + char *fname; + + if(geniestage==1) + { + FCEU_DispMessage("Cannot load FCS in GG screen."); + return; + } + + fname = FCEU_MakeFName(FCEUMKF_STATE,CurrentState,0); + st=fopen(fname,"rb"); + free(fname); + + if (st) + { + FCEUSS_LoadFP(st, 0); + fclose(st); + } + else + { + FCEU_DispMessage("State %d load error (no file).",CurrentState); + SaveStateStatus[CurrentState]=0; } - fclose(st); } char SaveStateStatus[10]; +#if 0 // leaks memory void CheckStates(void) { FILE *st=NULL; @@ -392,33 +416,54 @@ void CheckStates(void) SaveStateStatus[ssel]=0; } } +#endif void SaveStateRefresh(void) { SaveStateStatus[0]=-1; } -void ResetExState(void) +void ResetExState(void (*PreSave)(void), void (*PostSave)(void)) { int x; for(x=0;x