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