gpfce patch part2
[fceu.git] / state.c
1 /* FCE Ultra - NES/Famicom Emulator
2  *
3  * Copyright notice for this file:
4  *  Copyright (C) 2002 Ben Parnell
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 /*  TODO: Add (better) file io error checking */
22 /*  TODO: Change save state file format. */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "types.h"
29 #include "x6502.h"
30 #include "version.h"
31 #include "fce.h"
32 #include "sound.h"
33 #define INESPRIV                // Take this out when old save state support is removed in a future version.
34 #include "ines.h"
35 #include "svga.h"
36 #include "endian.h"
37 #include "fds.h"
38 #include "general.h"
39 #include "state.h"
40 #include "memory.h"
41 #include "ppu.h"
42
43 static SFORMAT SFMDATA[64];
44 static int SFEXINDEX;
45 static int stateversion;
46
47 #define RLSB            0x80000000
48
49 #define SFCPUELEMENTS 7
50
51 SFORMAT SFCPU[SFCPUELEMENTS]={
52  { &X.PC, 2|RLSB, "PC\0"},
53  { &X.A, 1, "A\0\0"},
54  { &X.P, 1, "P\0\0"},
55  { &X.X, 1, "X\0\0"},
56  { &X.Y, 1, "Y\0\0"},
57  { &X.S, 1, "S\0\0"},
58  { RAM, 0x800, "RAM"}
59 };
60
61 #define SFCPUCELEMENTS 6
62 SFORMAT SFCPUC[SFCPUCELEMENTS]={
63  { &X.jammed, 1, "JAMM"},
64  { &X.IRQlow, 1, "IRQL"},
65  { &X.tcount, 4|RLSB, "ICoa"},
66  { &X.count,  4|RLSB, "ICou"},
67  { &timestamp, 4|RLSB, "TIME"},
68  { &timestampbase, 8|RLSB, "TMEB"}
69 };
70
71 static uint16 TempAddrT,RefreshAddrT;
72
73 #define SFPPUELEMENTS 10
74 SFORMAT SFPPU[SFPPUELEMENTS]={
75  { NTARAM, 0x800, "NTAR"},
76  { PALRAM, 0x20, "PRAM"},
77  { SPRAM, 0x100, "SPRA"},
78  { PPU, 0x4, "PPUR"},
79  { &XOffset, 1, "XOFF"},
80  { &vtoggle, 1, "VTOG"},
81  { &RefreshAddrT, 2|RLSB, "RADD"},
82  { &TempAddrT, 2|RLSB, "TADD"},
83  { &VRAMBuffer, 1, "VBUF"},
84  { &PPUGenLatch, 1, "PGEN"},
85 };
86
87 // Is this chunk necessary?  I'll fix it later.
88 //#define SFCTLRELEMENTS 2
89 //SFORMAT SFCTLR[SFCTLRELEMENTS]={
90 // { &joy_readbit, 1, "J1RB"},
91 // { &joy2_readbit, 1, "J2RB"}
92 //};
93
94 #define SFSNDELEMENTS 18
95 SFORMAT SFSND[SFSNDELEMENTS]={
96  { &fhcnt, 4|RLSB,"FHCN"},
97  { &fcnt, 1, "FCNT"},
98  { PSG, 14, "PSG"},
99  { &PSG[0x15], 1, "P15"},
100  { &PSG[0x17], 1, "P17"},
101  { decvolume, 3, "DECV"},
102  { &sqnon, 1, "SQNO"},
103  { &nreg, 2|RLSB, "NREG"},
104  { &trimode, 1, "TRIM"},
105  { &tricoop, 1, "TRIC"},
106  { sweepon, 2, "SWEE"},
107  { &curfreq[0], 4|RLSB,"CRF1"},
108  { &curfreq[1], 4|RLSB,"CRF2"},
109  { SweepCount, 2,"SWCT"},
110  { DecCountTo1, 3,"DCT1"},
111  { &PCMBitIndex, 1,"PBIN"},
112  { &PCMAddressIndex, 4|RLSB, "PAIN"},
113  { &PCMSizeIndex, 4|RLSB, "PSIN"}
114 };
115
116
117 int WriteStateChunk(FILE *st, int type, SFORMAT *sf, int count)
118 {
119  int bsize;
120  int x;
121
122  fputc(type,st);
123  
124  for(x=bsize=0;x<count;x++)
125   bsize+=sf[x].s&(~RLSB);
126  bsize+=count<<3;
127  write32(bsize,st);
128  for(x=0;x<count;x++)
129  {
130   fwrite(sf[x].desc,1,4,st);
131   write32(sf[x].s&(~RLSB),st);
132   #ifdef LSB_FIRST
133   fwrite((uint8 *)sf[x].v,1,sf[x].s&(~RLSB),st);
134   #else
135   {
136   int z;
137   if(sf[x].s&RLSB)
138   {
139    for(z=(sf[x].s&(~RLSB))-1;z>=0;z--)
140    {
141     fputc(*(uint8*)sf[x].v,st);
142    }
143   }
144   else
145    fwrite((uint8 *)sf[x].v,1,sf[x].s&(~RLSB),st);
146   }
147   #endif
148  }
149  return (bsize+5);
150 }
151
152 int ReadStateChunk(FILE *st, SFORMAT *sf, int count, int size)
153 {
154  uint8 tmpyo[16];
155  int bsize;
156  int x;
157
158  for(x=bsize=0;x<count;x++)
159   bsize+=sf[x].s&(~RLSB);
160  if(stateversion>=53)
161   bsize+=count<<3;
162  else
163  {
164   if(bsize!=size)
165   {
166    fseek(st,size,SEEK_CUR);
167    return 0;
168   }
169  }
170
171  if(stateversion<56)
172   memcpy(tmpyo,mapbyte3,16);
173
174  if(stateversion>=53)
175  {
176   int temp;
177   temp=ftell(st);
178
179   while(ftell(st)<temp+size)
180   {
181    int tsize;
182    char toa[4];
183
184    if(fread(toa,1,4,st)<=0)
185     return 0;
186    read32(&tsize,st);
187
188    for(x=0;x<count;x++)
189    {
190     if(!memcmp(toa,sf[x].desc,4))
191     {
192      if(tsize!=(sf[x].s&(~RLSB)))
193       goto nkayo;
194      #ifndef LSB_FIRST
195      if(sf[x].s&RLSB)
196      {
197       int z;
198        for(z=(sf[x].s&(~RLSB))-1;z>=0;z--)       
199         *(uint8*)sf[x].v=fgetc(st);
200      }
201      else
202      #endif
203      {
204        fread((uint8 *)sf[x].v,1,sf[x].s&(~RLSB),st);
205      }
206      goto bloo;
207     }
208    }
209   nkayo:
210   fseek(st,tsize,SEEK_CUR);
211   bloo:;
212   } // while(...)
213  }  // >=53
214  else
215  {
216   for(x=0;x<count;x++)
217   {
218    #ifdef LSB_FIRST
219    fread((uint8 *)sf[x].v,1,sf[x].s&(~RLSB),st);
220    #else
221    int z;
222    if(sf[x].s&RLSB)
223     for(z=(sf[x].s&(~RLSB))-1;z>=0;z--)
224     {
225      *(uint8*)sf[x].v=fgetc(st);
226     }
227    else
228     fread((uint8 *)sf[x].v,1,sf[x].s&(~RLSB),st);
229    #endif
230   }
231  }
232  if(stateversion<56)
233  {
234   for(x=0;x<16;x++)
235    #ifdef LSB_FIRST
236    mapbyte1[x]=mapbyte1[x<<1];
237    #else
238    mapbyte1[x]=mapbyte1[(x<<1)+1];
239    #endif
240   memcpy(mapbyte3,tmpyo,16);
241  }
242  return 1;
243 }
244
245 int ReadStateChunks(FILE *st)
246 {
247  int t;
248  uint32 size;
249  int ret=1;
250
251 for(;;)
252  {
253   t=fgetc(st);
254   if(t==EOF) break;
255   if(!read32(&size,st)) break;
256   switch(t)
257   {
258    case 1:if(!ReadStateChunk(st,SFCPU,SFCPUELEMENTS,size)) ret=0;break;
259    case 2:if(!ReadStateChunk(st,SFCPUC,SFCPUCELEMENTS,size)) ret=0;
260           else
261           {
262            X.mooPI=X.P; // Quick and dirty hack.
263           }
264           break;
265    case 3:if(!ReadStateChunk(st,SFPPU,SFPPUELEMENTS,size)) ret=0;break;
266 //   case 4:if(!ReadStateChunk(st,SFCTLR,SFCTLRELEMENTS,size)) ret=0;break;
267    case 5:if(!ReadStateChunk(st,SFSND,SFSNDELEMENTS,size)) ret=0;break;
268    case 0x10:if(!ReadStateChunk(st,SFMDATA,SFEXINDEX,size)) ret=0;break;
269    default: if(fseek(st,size,SEEK_CUR)<0) goto endo;break;
270   }
271  }
272  endo:
273  return ret;
274 }
275
276
277 int CurrentState=0;
278 extern int geniestage;
279 void SaveState(void)
280 {
281         FILE *st=NULL;
282
283         TempAddrT=TempAddr;
284         RefreshAddrT=RefreshAddr;
285
286         if(geniestage==1)
287         {
288          FCEU_DispMessage("Cannot save FCS in GG screen.");
289          return;
290         }
291
292          st=fopen(FCEU_MakeFName(FCEUMKF_STATE,CurrentState,0),"wb");
293
294          if(st!=NULL)
295          {
296           static uint32 totalsize;
297           static uint8 header[16]="FCS";
298           memset(header+4,0,13);
299           header[3]=VERSION_NUMERIC;
300           fwrite(header,1,16,st);
301
302           totalsize=WriteStateChunk(st,1,SFCPU,SFCPUELEMENTS);
303           totalsize+=WriteStateChunk(st,2,SFCPUC,SFCPUCELEMENTS);
304           totalsize+=WriteStateChunk(st,3,SFPPU,SFPPUELEMENTS);
305         //  totalsize+=WriteStateChunk(st,4,SFCTLR,SFCTLRELEMENTS);
306           totalsize+=WriteStateChunk(st,5,SFSND,SFSNDELEMENTS);
307           totalsize+=WriteStateChunk(st,0x10,SFMDATA,SFEXINDEX);
308         
309           fseek(st,4,SEEK_SET);
310           write32(totalsize,st);
311           SaveStateStatus[CurrentState]=1;
312           fclose(st);
313           FCEU_DispMessage("State %d saved.",CurrentState);
314          }
315          else
316           FCEU_DispMessage("State %d save error.",CurrentState);
317 }
318
319 static int LoadStateOld(FILE *st);
320 void LoadState(void)
321 {
322         int x;
323         FILE *st=NULL;
324
325         if(geniestage==1)
326         {
327          FCEU_DispMessage("Cannot load FCS in GG screen.");
328          return;
329         }
330
331         st=fopen(FCEU_MakeFName(FCEUMKF_STATE,CurrentState,0),"rb");
332
333         if(st!=NULL)
334         {
335          uint8 header[16];
336
337          fread(&header,1,16,st);
338          if(memcmp(header,"FCS",3))
339          {
340           fseek(st,0,SEEK_SET);    
341           if(!LoadStateOld(st))
342            goto lerror;
343           goto okload;
344          }
345          stateversion=header[3];
346          if(stateversion<53)
347          FixOldSaveStateSFreq();
348          x=ReadStateChunks(st);
349          if(GameStateRestore) GameStateRestore(header[3]);
350          if(x)
351          {
352           okload:
353           TempAddr=TempAddrT;
354           RefreshAddr=RefreshAddrT;
355
356           SaveStateStatus[CurrentState]=1;
357           FCEU_DispMessage("State %d loaded.",CurrentState);
358           SaveStateStatus[CurrentState]=1;
359          }
360          else
361          {
362           SaveStateStatus[CurrentState]=1;
363           FCEU_DispMessage("Error(s) reading state %d!",CurrentState);
364          }
365         }
366         else
367         {
368          lerror:
369          FCEU_DispMessage("State %d load error.",CurrentState);
370          SaveStateStatus[CurrentState]=0;
371          return;
372         }
373         fclose(st);
374 }
375
376 char SaveStateStatus[10];
377 void CheckStates(void)
378 {
379         FILE *st=NULL;
380         int ssel;
381
382         if(SaveStateStatus[0]==-1)
383          for(ssel=0;ssel<10;ssel++)
384          {
385           st=fopen(FCEU_MakeFName(FCEUMKF_STATE,ssel,0),"rb");
386           if(st)
387           {
388            SaveStateStatus[ssel]=1;
389            fclose(st);
390           }
391           else
392            SaveStateStatus[ssel]=0;
393          }
394 }
395
396 void SaveStateRefresh(void)
397 {
398  SaveStateStatus[0]=-1;
399 }
400
401 void ResetExState(void)
402 {
403  int x;
404  for(x=0;x<SFEXINDEX;x++)
405   free(SFMDATA[x].desc);
406  SFEXINDEX=0;
407 }
408
409 void AddExState(void *v, uint32 s, int type, char *desc)
410 {
411  SFMDATA[SFEXINDEX].desc=FCEU_malloc(5);
412  if(SFMDATA[SFEXINDEX].desc)
413  {
414   strcpy(SFMDATA[SFEXINDEX].desc,desc);
415   SFMDATA[SFEXINDEX].v=v;
416   SFMDATA[SFEXINDEX].s=s;
417   if(type) SFMDATA[SFEXINDEX].s|=RLSB;
418   if(SFEXINDEX<63) SFEXINDEX++;
419  }
420 }
421
422 /* Old state loading code follows */
423
424 uint8 *StateBuffer;
425 unsigned int intostate;
426
427 static void afread(void *ptr, size_t _size, size_t _nelem)
428 {
429         memcpy(ptr,StateBuffer+intostate,_size*_nelem);
430         intostate+=_size*_nelem;
431 }
432
433
434 static void areadlower8of16(int8 *d)
435 {
436 #ifdef LSB_FIRST
437         *d=StateBuffer[intostate++];
438 #else
439         d[1]=StateBuffer[intostate++];
440 #endif
441 }
442
443
444 static void areadupper8of16(int8 *d)
445 {
446 #ifdef LSB_FIRST
447         d[1]=StateBuffer[intostate++];
448 #else
449         *d=StateBuffer[intostate++];
450 #endif
451 }
452
453
454 static void aread16(int8 *d)
455 {
456 #ifdef LSB_FIRST
457         *d=StateBuffer[intostate++];
458         d[1]=StateBuffer[intostate++];
459 #else
460         d[1]=StateBuffer[intostate++];
461         *d=StateBuffer[intostate++];
462 #endif
463 }
464
465
466 static void aread32(int8 *d)
467 {
468 #ifdef LSB_FIRST
469         *d=StateBuffer[intostate++];
470         d[1]=StateBuffer[intostate++];
471         d[2]=StateBuffer[intostate++];
472         d[3]=StateBuffer[intostate++];
473 #else
474         d[3]=StateBuffer[intostate++];
475         d[2]=StateBuffer[intostate++];
476         d[1]=StateBuffer[intostate++];
477         *d=StateBuffer[intostate++];
478 #endif
479 }
480
481 static int LoadStateOld(FILE *st)
482 {
483         int x;
484         int32 nada;
485         uint8 version;
486         nada=0;
487         
488         StateBuffer=FCEU_malloc(59999);
489         if(StateBuffer==NULL)
490          return 0;
491         if(!fread(StateBuffer,59999,1,st))
492         {
493             fclose(st);
494             free(StateBuffer);
495             return 0;
496         }
497
498         intostate=0;
499
500         {
501          uint8 a[2];
502          afread(&a[0],1,1);
503          afread(&a[1],1,1);
504          X.PC=a[0]|(a[1]<<8);
505         }
506         afread(&X.A,1,1);
507         afread(&X.P,1,1);
508         afread(&X.X,1,1);
509         afread(&X.Y,1,1);
510         afread(&X.S,1,1);
511         afread(&version,1,1);
512         afread(&nada,1,1);
513         afread(&nada,1,1);
514         afread(&nada,1,1);
515         afread(&nada,1,1);
516         aread32((int8 *)&X.count);
517         afread(&nada,1,1);
518         afread(&nada,1,1);
519         afread(&nada,1,1);
520         afread(&nada,1,1);
521         aread32((int8 *)&nada);
522         afread(&nada,1,1);
523         afread(&nada,1,1);
524         afread(&nada,1,1);
525         afread(&nada,1,1);
526         
527         for(x=0;x<8;x++)
528                 areadupper8of16((int8 *)&CHRBankList[x]);
529         afread(PRGBankList,4,1);
530         for(x=0;x<8;x++)
531                 areadlower8of16((int8 *)&CHRBankList[x]);
532         afread(CHRRAM,1,0x2000);
533         afread(NTARAM,1,0x400);
534         afread(ExtraNTARAM,1,0x400);
535         afread(NTARAM+0x400,1,0x400);
536         afread(ExtraNTARAM+0x400,1,0x400);
537
538         for(x=0;x<0xF00;x++)
539          afread(&nada,1,1);
540         afread(PALRAM,1,0x20);
541         for(x=0;x<256-32;x++)
542          afread(&nada,1,1);
543         for(x=0x00;x<0x20;x++)
544          PALRAM[x]&=0x3f;
545         afread(PPU,1,4);
546         afread(SPRAM,1,0x100);
547         afread(WRAM,1,8192);
548         afread(RAM,1,0x800);
549         aread16((int8 *)&scanline);
550         aread16((int8 *)&RefreshAddr);
551         afread(&VRAMBuffer,1,1);
552         
553         afread(&IRQa,1,1);
554         aread32((int8 *)&IRQCount);
555         aread32((int8 *)&IRQLatch);
556         afread(&Mirroring,1,1);
557         afread(PSG,1,0x17);
558         PSG[0x11]&=0x7F;
559         afread(MapperExRAM,1,193);
560         if(version>=31)
561          PSG[0x17]=MapperExRAM[115];
562         else
563          PSG[0x17]|=0x40;
564         PSG[0x15]&=0xF;
565         sqnon=PSG[0x15];
566
567         X.IRQlow=0;
568         afread(&nada,1,1);
569         afread(&nada,1,1);
570         afread(&nada,1,1);
571         afread(&nada,1,1);
572         afread(&nada,1,1);
573         afread(&nada,1,1);
574         afread(&XOffset,1,1);
575         PPUCHRRAM=0;
576         for(x=0;x<8;x++)
577         {
578          nada=0;
579          afread(&nada,1,1);
580          PPUCHRRAM|=(nada?1:0)<<x;         
581         }
582                         
583          afread(mapbyte1,1,8);
584          afread(mapbyte2,1,8);
585          afread(mapbyte3,1,8);
586          afread(mapbyte4,1,8);
587          for(x=0;x<4;x++)
588           aread16((int8 *)&nada);
589                 
590          PPUNTARAM=0;
591          for(x=0;x<4;x++)
592          {
593           nada=0;
594           aread16((int8 *)&nada);
595           PPUNTARAM|=((nada&0x800)?0:1)<<x;
596          }
597          afread(MapperExRAM,1,32768);
598          afread(&vtoggle,1,1);
599          aread16((int8 *)&TempAddrT);
600          aread16((int8 *)&RefreshAddrT);
601                                 
602          if(GameStateRestore) GameStateRestore(version);
603          free(StateBuffer);
604          FixOldSaveStateSFreq();
605          X.mooPI=X.P;
606          return 1;
607 }
608