098 video fix, 098 sound integrated
[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 #ifdef GP2X
28 #include <unistd.h>
29 #endif
30
31 #include "types.h"
32 #include "x6502.h"
33 #include "version.h"
34 #include "fce.h"
35 #include "sound.h"
36 #include "sound098.h"
37 #define INESPRIV                // Take this out when old save state support is removed in a future version.
38 #include "ines.h"
39 #include "svga.h"
40 #include "endian.h"
41 #include "fds.h"
42 #include "general.h"
43 #include "state.h"
44 #include "memory.h"
45 #include "ppu.h"
46
47 static void (*SPreSave)(void) = 0;
48 static void (*SPostSave)(void) = 0;
49
50 #define SFMDATA_SIZE (64)
51 static SFORMAT SFMDATA[SFMDATA_SIZE];
52 static int SFEXINDEX;
53 static int stateversion;
54
55 extern SFORMAT FCEUPPU_STATEINFO[];  // 3
56 extern SFORMAT FCEUCTRL_STATEINFO[]; // 4
57
58 SFORMAT SFCPU[]={ // 1
59  { &X.PC, 2|RLSB, "PC\0"},
60  { &X.A, 1, "A\0\0"},
61  { &X.P, 1, "P\0\0"},
62  { &X.X, 1, "X\0\0"},
63  { &X.Y, 1, "Y\0\0"},
64  { &X.S, 1, "S\0\0"},
65  { RAM, 0x800, "RAM"},
66  { 0, }
67 };
68
69 SFORMAT SFCPUC[]={ // 2
70  { &X.jammed, 1, "JAMM"},
71  { &X.IRQlow, 1, "IRQL"},
72  { &X.tcount, 4|RLSB, "ICoa"},
73  { &X.count,  4|RLSB, "ICou"},
74  { &timestamp, 4|RLSB, "TIME"},
75  { &timestampbase, 8|RLSB, "TMEB"},
76  // from 0.98.15
77  { &timestampbase, sizeof(timestampbase) | RLSB, "TSBS"}, // size seems to match?
78  { &X.mooPI, 1, "MooP"}, // alternative to the "quick and dirty hack"
79  // TODO: IQLB?
80  { 0, }
81 };
82
83 extern uint16 TempAddrT,RefreshAddrT;
84
85
86 SFORMAT SFSND[]={
87  { &fhcnt, 4|RLSB,"FHCN"},
88  { &fcnt, 1, "FCNT"},
89  { PSG, 14, "PSG"},
90  { &PSG[0x15], 1, "P15"},
91  { &PSG[0x17], 1, "P17"},
92  { decvolume, 3, "DECV"},
93  { &sqnon, 1, "SQNO"},
94  { &nreg, 2|RLSB, "NREG"},
95  { &trimode, 1, "TRIM"},
96  { &tricoop, 1, "TRIC"},
97  { sweepon, 2, "SWEE"},
98  { &curfreq[0], 4|RLSB,"CRF1"},
99  { &curfreq[1], 4|RLSB,"CRF2"},
100  { SweepCount, 2,"SWCT"},
101  { DecCountTo1, 3,"DCT1"},
102  { &PCMBitIndex, 1,"PBIN"},
103  { &PCMAddressIndex, 4|RLSB, "PAIN"},
104  { &PCMSizeIndex, 4|RLSB, "PSIN"},
105  { 0, }
106 };
107
108 extern SFORMAT FCEUSND_STATEINFO[]; // TODO: unify?
109 #define get_snd_sf() (use098code ? FCEUSND_STATEINFO : SFSND)
110
111
112 static int SubWrite(FILE *st, SFORMAT *sf)
113 {
114  uint32 acc=0;
115
116  while(sf->v)
117  {
118   if(sf->s==~0)         /* Link to another struct.      */
119   {
120    uint32 tmp;
121
122    if(!(tmp=SubWrite(st,(SFORMAT *)sf->v)))
123     return(0);
124    acc+=tmp;
125    sf++;
126    continue;
127   }
128
129   acc+=8;                       /* Description + size */
130   acc+=sf->s&(~RLSB);
131
132   if(st)                        /* Are we writing or calculating the size of this block? */
133   {
134    fwrite(sf->desc,1,4,st);
135    write32le(sf->s&(~RLSB),st);
136
137    #ifndef LSB_FIRST
138    if(sf->s&RLSB)
139     FlipByteOrder(sf->v,sf->s&(~RLSB));
140    #endif
141
142    fwrite((uint8 *)sf->v,1,sf->s&(~RLSB),st);
143    /* Now restore the original byte order. */
144    #ifndef LSB_FIRST
145    if(sf->s&RLSB)
146     FlipByteOrder(sf->v,sf->s&(~RLSB));
147    #endif
148   }
149   sf++;
150  }
151
152  return(acc);
153 }
154
155 static int WriteStateChunk(FILE *st, int type, SFORMAT *sf)
156 {
157  int bsize;
158
159  fputc(type,st);
160
161  bsize=SubWrite(0,sf);
162  write32le(bsize,st);
163
164  if(!SubWrite(st,sf))
165  {
166          return(0);
167  }
168  return (bsize+5);
169 }
170
171 static SFORMAT *CheckS(SFORMAT *sf, uint32 tsize, char *desc)
172 {
173  while(sf->v)
174  {
175   if(sf->s==~0)         /* Link to another SFORMAT structure. */
176   {
177    SFORMAT *tmp;
178    if((tmp= CheckS((SFORMAT *)sf->v, tsize, desc) ))
179     return(tmp);
180    sf++;
181    continue;
182   }
183   if(!memcmp(desc,sf->desc,4))
184   {
185    if(tsize!=(sf->s&(~RLSB)))
186    {
187     printf("ReadStateChunk: sect \"%c%c%c%c\" has wrong size\n", desc[0], desc[1], desc[2], desc[3]);
188     return(0);
189    }
190    return(sf);
191   }
192   sf++;
193  }
194  return(0);
195 }
196
197 static int ReadStateChunk(FILE *st, SFORMAT *sf, int size)
198 {
199  //if(scan_chunks)
200  //  return fseek(st,size,SEEK_CUR) == 0;
201
202  SFORMAT *tmp;
203  int temp;
204  temp=ftell(st);
205
206  while(ftell(st)<temp+size)
207  {
208   uint32 tsize;
209   char toa[4];
210   if(fread(toa,1,4,st)<=0)
211    return 0;
212
213   read32le(&tsize,st);
214
215   if((tmp=CheckS(sf,tsize,toa)))
216   {
217    fread((uint8 *)tmp->v,1,tmp->s&(~RLSB),st);
218
219    #ifndef LSB_FIRST
220    if(tmp->s&RLSB)
221     FlipByteOrder(tmp->v,tmp->s&(~RLSB));
222    #endif
223   }
224   else
225   {
226    fseek(st,tsize,SEEK_CUR);
227    printf("ReadStateChunk: sect \"%c%c%c%c\" not handled\n", toa[0], toa[1], toa[2], toa[3]);
228   }
229  } // while(...)
230  return 1;
231 }
232
233
234 static int ReadStateChunks(FILE *st)
235 {
236  int t;
237  uint32 size;
238  int ret=1;
239
240 for(;;)
241  {
242   t=fgetc(st);
243   if(t==EOF) break;
244   if(!read32(&size,st)) break;
245
246   // printf("ReadStateChunks: chunk %i\n", t);
247   switch(t)
248   {
249    case 1:if(!ReadStateChunk(st,SFCPU,size)) ret=0;
250 #ifdef ASM_6502
251           asmcpu_unpack();
252 #endif
253           break;
254    case 2:if(!ReadStateChunk(st,SFCPUC,size)) ret=0;
255           else
256           {
257            X.mooPI=X.P; // Quick and dirty hack.
258           }
259           break;
260    case 3:if(!ReadStateChunk(st,FCEUPPU_STATEINFO,size)) ret=0;break;
261    case 4:if(!ReadStateChunk(st,FCEUCTRL_STATEINFO,size)) ret=0;break;
262    case 5:if(!ReadStateChunk(st,get_snd_sf(),size)) ret=0;break;
263    case 0x10:if(!ReadStateChunk(st,SFMDATA,size)) ret=0;break;
264    default:printf("ReadStateChunks: unknown chunk: %i\n", t);
265            if(fseek(st,size,SEEK_CUR)<0) goto endo;break;
266   }
267  }
268  endo:
269  return ret;
270 }
271
272
273 int CurrentState=0;
274 extern int geniestage;
275 void SaveState(void)
276 {
277         FILE *st=NULL;
278         char *fname;
279
280         TempAddrT=TempAddr;
281         RefreshAddrT=RefreshAddr;
282
283         if(geniestage==1)
284         {
285          FCEU_DispMessage("Cannot save FCS in GG screen.");
286          return;
287         }
288
289          fname = FCEU_MakeFName(FCEUMKF_STATE,CurrentState,0);
290          st=fopen(fname,"wb");
291          free(fname);
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           FCEUSND_SaveState();
302 #ifdef ASM_6502
303           asmcpu_pack();
304 #endif
305           totalsize=WriteStateChunk(st,1,SFCPU);
306           totalsize+=WriteStateChunk(st,2,SFCPUC);
307           totalsize+=WriteStateChunk(st,3,FCEUPPU_STATEINFO);
308           totalsize+=WriteStateChunk(st,4,FCEUCTRL_STATEINFO);
309           totalsize+=WriteStateChunk(st,5,get_snd_sf());
310
311
312           if(SPreSave) SPreSave();
313           totalsize+=WriteStateChunk(st,0x10,SFMDATA);
314           if(SPostSave) SPostSave();
315
316           fseek(st,4,SEEK_SET);
317           write32(totalsize,st);
318           SaveStateStatus[CurrentState]=1;
319           fclose(st);
320 #ifdef GP2X
321           sync();
322 #endif
323           FCEU_DispMessage("State %d saved.",CurrentState);
324          }
325          else
326           FCEU_DispMessage("State %d save error.",CurrentState);
327 }
328
329 static int LoadStateOld(FILE *st);
330 int FCEUSS_LoadFP(FILE *st, int make_backup)
331 {
332         int x;
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           FCEUSND_LoadState(header[3]);
354           TempAddr=TempAddrT;
355           RefreshAddr=RefreshAddrT;
356
357           SaveStateStatus[CurrentState]=1;
358           FCEU_DispMessage("State %d loaded.",CurrentState);
359           SaveStateStatus[CurrentState]=1;
360          }
361          else
362          {
363           SaveStateStatus[CurrentState]=1;
364           FCEU_DispMessage("Error(s) reading state %d!",CurrentState);
365          }
366         }
367         else
368         {
369          lerror:
370          FCEU_DispMessage("State %d load error.",CurrentState);
371          SaveStateStatus[CurrentState]=0;
372          return 0;
373         }
374         return 1;
375 }
376
377 void LoadState(void)
378 {
379         FILE *st=NULL;
380         char *fname;
381
382         if(geniestage==1)
383         {
384          FCEU_DispMessage("Cannot load FCS in GG screen.");
385          return;
386         }
387
388         fname = FCEU_MakeFName(FCEUMKF_STATE,CurrentState,0);
389         st=fopen(fname,"rb");
390         free(fname);
391
392         if (st)
393         {
394          FCEUSS_LoadFP(st, 0);
395          fclose(st);
396         }
397         else
398         {
399          FCEU_DispMessage("State %d load error (no file).",CurrentState);
400          SaveStateStatus[CurrentState]=0;
401         }
402 }
403
404 char SaveStateStatus[10];
405 #if 0 // leaks memory
406 void CheckStates(void)
407 {
408         FILE *st=NULL;
409         int ssel;
410
411         if(SaveStateStatus[0]==(char)-1)
412          for(ssel=0;ssel<10;ssel++)
413          {
414           st=fopen(FCEU_MakeFName(FCEUMKF_STATE,ssel,0),"rb");
415           if(st)
416           {
417            SaveStateStatus[ssel]=1;
418            fclose(st);
419           }
420           else
421            SaveStateStatus[ssel]=0;
422          }
423 }
424 #endif
425
426 void SaveStateRefresh(void)
427 {
428  SaveStateStatus[0]=-1;
429 }
430
431 void ResetExState(void (*PreSave)(void), void (*PostSave)(void))
432 {
433  int x;
434  for(x=0;x<SFEXINDEX;x++)
435  {
436   if(SFMDATA[x].desc)
437    free(SFMDATA[x].desc);
438  }
439  SPreSave = PreSave;
440  SPostSave = PostSave;
441  SFEXINDEX=0;
442 }
443
444
445 void AddExState(void *v, uint32 s, int type, char *desc)
446 {
447  if(desc)
448  {
449   SFMDATA[SFEXINDEX].desc=(char *)FCEU_malloc(5);
450   strcpy(SFMDATA[SFEXINDEX].desc,desc);
451  }
452  else
453   SFMDATA[SFEXINDEX].desc=0;
454  SFMDATA[SFEXINDEX].v=v;
455  SFMDATA[SFEXINDEX].s=s;
456  if(type) SFMDATA[SFEXINDEX].s|=RLSB;
457  if(SFEXINDEX<SFMDATA_SIZE-1)
458          SFEXINDEX++;
459  else
460  {
461          static int once=1;
462          if(once)
463          {
464                  once=0;
465                  FCEU_PrintError("Error in AddExState: SFEXINDEX overflow.\nSomebody made SFMDATA_SIZE too small.");
466          }
467  }
468  SFMDATA[SFEXINDEX].v=0;                // End marker.
469 }
470
471
472 /* Old state loading code follows */
473
474 uint8 *StateBuffer;
475 unsigned int intostate;
476
477 static void afread(void *ptr, size_t _size, size_t _nelem)
478 {
479         memcpy(ptr,StateBuffer+intostate,_size*_nelem);
480         intostate+=_size*_nelem;
481 }
482
483
484 static void areadlower8of16(int8 *d)
485 {
486 #ifdef LSB_FIRST
487         *d=StateBuffer[intostate++];
488 #else
489         d[1]=StateBuffer[intostate++];
490 #endif
491 }
492
493
494 static void areadupper8of16(int8 *d)
495 {
496 #ifdef LSB_FIRST
497         d[1]=StateBuffer[intostate++];
498 #else
499         *d=StateBuffer[intostate++];
500 #endif
501 }
502
503
504 static void aread16(int8 *d)
505 {
506 #ifdef LSB_FIRST
507         *d=StateBuffer[intostate++];
508         d[1]=StateBuffer[intostate++];
509 #else
510         d[1]=StateBuffer[intostate++];
511         *d=StateBuffer[intostate++];
512 #endif
513 }
514
515
516 static void aread32(int8 *d)
517 {
518 #ifdef LSB_FIRST
519         *d=StateBuffer[intostate++];
520         d[1]=StateBuffer[intostate++];
521         d[2]=StateBuffer[intostate++];
522         d[3]=StateBuffer[intostate++];
523 #else
524         d[3]=StateBuffer[intostate++];
525         d[2]=StateBuffer[intostate++];
526         d[1]=StateBuffer[intostate++];
527         *d=StateBuffer[intostate++];
528 #endif
529 }
530
531 static int LoadStateOld(FILE *st)
532 {
533         int x;
534         int32 nada;
535         uint8 version;
536         nada=0;
537
538         printf("LoadStateOld\n");
539
540         StateBuffer=FCEU_malloc(59999);
541         if(StateBuffer==NULL)
542          return 0;
543         if(!fread(StateBuffer,59999,1,st))
544         {
545             fclose(st);
546             free(StateBuffer);
547             return 0;
548         }
549
550         intostate=0;
551
552         {
553          uint8 a[2];
554          afread(&a[0],1,1);
555          afread(&a[1],1,1);
556          X.PC=a[0]|(a[1]<<8);
557         }
558         afread(&X.A,1,1);
559         afread(&X.P,1,1);
560         afread(&X.X,1,1);
561         afread(&X.Y,1,1);
562         afread(&X.S,1,1);
563         afread(&version,1,1);
564         afread(&nada,1,1);
565         afread(&nada,1,1);
566         afread(&nada,1,1);
567         afread(&nada,1,1);
568         aread32((int8 *)&X.count);
569         afread(&nada,1,1);
570         afread(&nada,1,1);
571         afread(&nada,1,1);
572         afread(&nada,1,1);
573         aread32((int8 *)&nada);
574         afread(&nada,1,1);
575         afread(&nada,1,1);
576         afread(&nada,1,1);
577         afread(&nada,1,1);
578
579         for(x=0;x<8;x++)
580                 areadupper8of16((int8 *)&CHRBankList[x]);
581         afread(PRGBankList,4,1);
582         for(x=0;x<8;x++)
583                 areadlower8of16((int8 *)&CHRBankList[x]);
584         afread(CHRRAM,1,0x2000);
585         afread(NTARAM,1,0x400);
586         afread(ExtraNTARAM,1,0x400);
587         afread(NTARAM+0x400,1,0x400);
588         afread(ExtraNTARAM+0x400,1,0x400);
589
590         for(x=0;x<0xF00;x++)
591          afread(&nada,1,1);
592         afread(PALRAM,1,0x20);
593         for(x=0;x<256-32;x++)
594          afread(&nada,1,1);
595         for(x=0x00;x<0x20;x++)
596          PALRAM[x]&=0x3f;
597         afread(PPU,1,4);
598         afread(SPRAM,1,0x100);
599         afread(WRAM,1,8192);
600         afread(RAM,1,0x800);
601         aread16((int8 *)&scanline);
602         aread16((int8 *)&RefreshAddr);
603         afread(&VRAMBuffer,1,1);
604
605         afread(&IRQa,1,1);
606         aread32((int8 *)&IRQCount);
607         aread32((int8 *)&IRQLatch);
608         afread(&Mirroring,1,1);
609         afread(PSG,1,0x17);
610         PSG[0x11]&=0x7F;
611         afread(MapperExRAM,1,193);
612         if(version>=31)
613          PSG[0x17]=MapperExRAM[115];
614         else
615          PSG[0x17]|=0x40;
616         PSG[0x15]&=0xF;
617         sqnon=PSG[0x15];
618
619         X.IRQlow=0;
620         afread(&nada,1,1);
621         afread(&nada,1,1);
622         afread(&nada,1,1);
623         afread(&nada,1,1);
624         afread(&nada,1,1);
625         afread(&nada,1,1);
626         afread(&XOffset,1,1);
627         PPUCHRRAM=0;
628         for(x=0;x<8;x++)
629         {
630          nada=0;
631          afread(&nada,1,1);
632          PPUCHRRAM|=(nada?1:0)<<x;
633         }
634
635          afread(mapbyte1,1,8);
636          afread(mapbyte2,1,8);
637          afread(mapbyte3,1,8);
638          afread(mapbyte4,1,8);
639          for(x=0;x<4;x++)
640           aread16((int8 *)&nada);
641
642          PPUNTARAM=0;
643          for(x=0;x<4;x++)
644          {
645           nada=0;
646           aread16((int8 *)&nada);
647           PPUNTARAM|=((nada&0x800)?0:1)<<x;
648          }
649          afread(MapperExRAM,1,32768);
650          afread(&vtoggle,1,1);
651          aread16((int8 *)&TempAddrT);
652          aread16((int8 *)&RefreshAddrT);
653
654          if(GameStateRestore) GameStateRestore(version);
655          free(StateBuffer);
656          FixOldSaveStateSFreq();
657          X.mooPI=X.P;
658          return 1;
659 }
660