merge x6502 code FCEUX
[fceu.git] / cheat.c
1 /* FCE Ultra - NES/Famicom Emulator
2  *
3  * Copyright notice for this file:
4  *  Copyright (C) 2002 Xodnizel
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 #include <stdlib.h>
22 #include <string.h>
23 #include <stdio.h>
24 #include <ctype.h>
25
26 #include "types.h"
27 #include "x6502.h"
28 #include "cheat.h"
29 #include "fce.h"
30 #include "general.h"
31 #include "cart.h"
32 #include "memory.h"
33
34 #include "file.h"
35 #include "svga.h"
36
37 static uint8 *CheatRPtrs[64];
38
39 void FCEU_CheatResetRAM(void)
40 {
41  int x;
42
43  for(x=0;x<64;x++)
44   CheatRPtrs[x]=0;
45 }
46
47 void FCEU_CheatAddRAM(int s, uint32 A, uint8 *p)
48 {
49  uint32 AB=A>>10;
50  int x;
51
52  for(x=s-1;x>=0;x--)
53   CheatRPtrs[AB+x]=p-A;
54 }
55
56
57 struct CHEATF {
58            struct CHEATF *next;
59            char *name;
60            uint16 addr;
61            uint8 val;
62            int compare; /* -1 for no compare. */
63            int type;    /* 0 for replace, 1 for substitute(GG). */
64            int status;
65 };
66
67 typedef struct {
68         uint16 addr;
69         uint8 val;
70         int compare;
71         readfunc PrevRead;
72 } CHEATF_SUBFAST;
73
74
75 static CHEATF_SUBFAST SubCheats[256];
76 static int numsubcheats=0;
77 struct CHEATF *cheats=0,*cheatsl=0;
78
79
80 #define CHEATC_NONE     0x8000
81 #define CHEATC_EXCLUDED 0x4000
82 #define CHEATC_NOSHOW   0xC000
83
84 static uint16 *CheatComp=0;
85 static int savecheats;
86
87 static DECLFR(SubCheatsRead)
88 {
89  CHEATF_SUBFAST *s=SubCheats;
90  int x=numsubcheats;
91
92  do
93  {
94   if(s->addr==A)
95   {
96    if(s->compare>=0)
97    {
98     uint8 pv=s->PrevRead(A);
99
100     if(pv==s->compare)
101      return(s->val);
102     else return(pv);
103    }
104    else return(s->val);
105   }
106   s++;
107  } while(--x);
108  return(0);     /* We should never get here. */
109 }
110
111 void RebuildSubCheats(void)
112 {
113  int x;
114  struct CHEATF *c=cheats;
115
116  for(x=0;x<numsubcheats;x++)
117   SetReadHandler(SubCheats[x].addr,SubCheats[x].addr,SubCheats[x].PrevRead);
118
119  numsubcheats=0;
120  while(c)
121  {
122   if(c->type==1 && c->status)
123   {
124    if(GetReadHandler(c->addr)==SubCheatsRead)
125    {
126     /* Prevent a catastrophe by this check. */
127     //FCEU_DispMessage("oops");
128    }
129    else
130    {
131     SubCheats[numsubcheats].PrevRead=GetReadHandler(c->addr);
132     SubCheats[numsubcheats].addr=c->addr;
133     SubCheats[numsubcheats].val=c->val;
134     SubCheats[numsubcheats].compare=c->compare;
135     SetReadHandler(c->addr,c->addr,SubCheatsRead);
136     numsubcheats++;
137    }
138   }
139   c=c->next;
140  }
141 }
142
143 void FCEU_PowerCheats()
144 {
145  numsubcheats=0;        /* Quick hack to prevent setting of ancient read addresses. */
146  RebuildSubCheats();
147 }
148
149 static int AddCheatEntry(char *name, uint32 addr, uint8 val, int compare, int status, int type);
150 static void CheatMemErr(void)
151 {
152  FCEUD_PrintError("Error allocating memory for cheat data.");
153 }
154
155 /* This function doesn't allocate any memory for "name" */
156 static int AddCheatEntry(char *name, uint32 addr, uint8 val, int compare, int status, int type)
157 {
158  struct CHEATF *temp;
159  if(!(temp=(struct CHEATF *)malloc(sizeof(struct CHEATF))))
160  {
161   CheatMemErr();
162   return(0);
163  }
164  temp->name=name;
165  temp->addr=addr;
166  temp->val=val;
167  temp->status=status;
168  temp->compare=compare;
169  temp->type=type;
170  temp->next=0;
171
172  if(cheats)
173  {
174   cheatsl->next=temp;
175   cheatsl=temp;
176  }
177  else
178   cheats=cheatsl=temp;
179
180  return(1);
181 }
182
183 void FCEU_LoadGameCheats(FILE *override)
184 {
185  FILE *fp;
186  unsigned int addr;
187  unsigned int val;
188  unsigned int status;
189  unsigned int type;
190  unsigned int compare;
191  int x;
192
193  char linebuf[2048];
194  char *namebuf;
195  int tc=0;
196  char *fn;
197
198  numsubcheats=savecheats=0;
199
200  if(override)
201   fp = override;
202  else
203  {
204   fn=FCEU_MakeFName(FCEUMKF_CHEAT,0,0);
205   fp=FCEUD_UTF8fopen(fn,"rb");
206   free(fn);
207   if(!fp) return;
208  }
209
210  while(fgets(linebuf,2048,fp)>0)
211  {
212   char *tbuf=linebuf;
213   int doc=0;
214
215   addr=val=compare=status=type=0;
216
217   if(tbuf[0]=='S')
218   {
219    tbuf++;
220    type=1;
221   }
222   else type=0;
223
224   if(tbuf[0]=='C')
225   {
226    tbuf++;
227    doc=1;
228   }
229
230   if(tbuf[0]==':')
231   {
232    tbuf++;
233    status=0;
234   }
235   else status=1;
236
237   if(doc)
238   {
239    char *neo=&tbuf[4+2+2+1+1+1];
240    if(sscanf(tbuf,"%04x%*[:]%02x%*[:]%02x",&addr,&val,&compare)!=3)
241     continue;
242    namebuf=malloc(strlen(neo)+1);
243    strcpy(namebuf,neo);
244   }
245   else
246   {
247    char *neo=&tbuf[4+2+1+1];
248    if(sscanf(tbuf,"%04x%*[:]%02x",&addr,&val)!=2)
249     continue;
250    namebuf=malloc(strlen(neo)+1);
251    strcpy(namebuf,neo);
252   }
253
254   for(x=0;x<strlen(namebuf);x++)
255   {
256    if(namebuf[x]==10 || namebuf[x]==13)
257    {
258     namebuf[x]=0;
259     break;
260    }
261    else if(namebuf[x]<0x20) namebuf[x]=' ';
262   }
263
264   AddCheatEntry(namebuf,addr,val,doc?compare:-1,status,type);
265   tc++;
266  }
267  RebuildSubCheats();
268  if(!override)
269   fclose(fp);
270 }
271
272 void FCEU_FlushGameCheats(FILE *override, int nosave)
273 {
274  if(CheatComp)
275  {
276   free(CheatComp);
277   CheatComp=0;
278  }
279  if((!savecheats || nosave) && !override)       /* Always save cheats if we're being overridden. */
280  {
281   if(cheats)
282   {
283    struct CHEATF *next=cheats;
284    for(;;)
285    {
286     struct CHEATF *last=next;
287     next=next->next;
288     free(last->name);
289     free(last);
290     if(!next) break;
291    }
292    cheats=cheatsl=0;
293   }
294  }
295  else
296  {
297   char *fn = 0;
298
299   if(!override)
300    fn = FCEU_MakeFName(FCEUMKF_CHEAT,0,0);
301
302   if(cheats)
303   {
304    struct CHEATF *next=cheats;
305    FILE *fp;
306
307    if(override)
308     fp = override;
309    else
310     fp=FCEUD_UTF8fopen(fn,"wb");
311
312    if(fp)
313    {
314     for(;;)
315     {
316      struct CHEATF *t;
317      if(next->type)
318       fputc('S',fp);
319      if(next->compare>=0)
320       fputc('C',fp);
321
322      if(!next->status)
323       fputc(':',fp);
324
325      if(next->compare>=0)
326       fprintf(fp,"%04x:%02x:%02x:%s\n",next->addr,next->val,next->compare,next->name);
327      else
328       fprintf(fp,"%04x:%02x:%s\n",next->addr,next->val,next->name);
329
330      free(next->name);
331      t=next;
332      next=next->next;
333      free(t);
334      if(!next) break;
335     }
336     if(!override)
337      fclose(fp);
338    }
339    else
340     FCEUD_PrintError("Error saving cheats.");
341    cheats=cheatsl=0;
342   }
343   else if(!override)
344    remove(fn);
345   if(!override)
346    free(fn);
347  }
348
349  RebuildSubCheats();  /* Remove memory handlers. */
350
351 }
352
353
354 int FCEUI_AddCheat(const char *name, uint32 addr, uint8 val, int compare, int type)
355 {
356  char *t;
357
358  if(!(t=(char *)malloc(strlen(name)+1)))
359  {
360   CheatMemErr();
361   return(0);
362  }
363  strcpy(t,name);
364  if(!AddCheatEntry(t,addr,val,compare,1,type))
365  {
366   free(t);
367   return(0);
368  }
369  savecheats=1;
370  RebuildSubCheats();
371  return(1);
372 }
373
374 int FCEUI_DelCheat(uint32 which)
375 {
376  struct CHEATF *prev;
377  struct CHEATF *cur;
378  uint32 x=0;
379
380  for(prev=0,cur=cheats;;)
381  {
382   if(x==which)          // Remove this cheat.
383   {
384    if(prev)             // Update pointer to this cheat.
385    {
386     if(cur->next)       // More cheats.
387      prev->next=cur->next;
388     else                // No more.
389     {
390      prev->next=0;
391      cheatsl=prev;      // Set the previous cheat as the last cheat.
392     }
393    }
394    else                 // This is the first cheat.
395    {
396     if(cur->next)       // More cheats
397      cheats=cur->next;
398     else
399      cheats=cheatsl=0;  // No (more) cheats.
400    }
401    free(cur->name);     // Now that all references to this cheat are removed,
402    free(cur);           // free the memory.
403    break;
404   }                     // *END REMOVE THIS CHEAT*
405
406
407   if(!cur->next)        // No more cheats to go through(this shouldn't ever happen...)
408    return(0);
409   prev=cur;
410   cur=prev->next;
411   x++;
412  }
413
414  savecheats=1;
415  RebuildSubCheats();
416
417  return(1);
418 }
419
420 void FCEU_ApplyPeriodicCheats(void)
421 {
422  struct CHEATF *cur=cheats;
423  if(!cur) return;
424
425  for(;;)
426  {
427   if(cur->status && !(cur->type))
428    if(CheatRPtrs[cur->addr>>10])
429     CheatRPtrs[cur->addr>>10][cur->addr]=cur->val;
430   if(cur->next)
431    cur=cur->next;
432   else
433    break;
434  }
435 }
436
437
438 void FCEUI_ListCheats(int (*callb)(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data), void *data)
439 {
440   struct CHEATF *next=cheats;
441
442   while(next)
443   {
444    if(!callb(next->name,next->addr,next->val,next->compare,next->status,next->type,data)) break;
445    next=next->next;
446   }
447 }
448
449 int FCEUI_GetCheat(uint32 which, char **name, uint32 *a, uint8 *v, int *compare, int *s, int *type)
450 {
451  struct CHEATF *next=cheats;
452  uint32 x=0;
453
454  while(next)
455  {
456   if(x==which)
457   {
458    if(name)
459     *name=next->name;
460    if(a)
461     *a=next->addr;
462    if(v)
463     *v=next->val;
464    if(s)
465     *s=next->status;
466    if(compare)
467     *compare=next->compare;
468    if(type)
469     *type=next->type;
470    return(1);
471   }
472   next=next->next;
473   x++;
474  }
475  return(0);
476 }
477
478 static int GGtobin(char c)
479 {
480  static char lets[16]={'A','P','Z','L','G','I','T','Y','E','O','X','U','K','S','V','N'};
481  int x;
482
483  for(x=0;x<16;x++)
484   if(lets[x] == toupper(c)) return(x);
485  return(0);
486 }
487
488 /* Returns 1 on success, 0 on failure. Sets *a,*v,*c. */
489 int FCEUI_DecodeGG(const char *str, uint16 *a, uint8 *v, int *c)
490 {
491  uint16 A;
492  uint8 V,C;
493  uint8 t;
494  int s;
495
496  A=0x8000;
497  V=0;
498  C=0;
499
500  s=strlen(str);
501  if(s!=6 && s!=8) return(0);
502
503  t=GGtobin(*str++);
504  V|=(t&0x07);
505  V|=(t&0x08)<<4;
506
507  t=GGtobin(*str++);
508  V|=(t&0x07)<<4;
509  A|=(t&0x08)<<4;
510
511  t=GGtobin(*str++);
512  A|=(t&0x07)<<4;
513  //if(t&0x08) return(0);        /* 8-character code?! */
514
515  t=GGtobin(*str++);
516  A|=(t&0x07)<<12;
517  A|=(t&0x08);
518
519  t=GGtobin(*str++);
520  A|=(t&0x07);
521  A|=(t&0x08)<<8;
522
523  if(s==6)
524  {
525   t=GGtobin(*str++);
526   A|=(t&0x07)<<8;
527   V|=(t&0x08);
528
529   *a=A;
530   *v=V;
531   *c=-1;
532   return(1);
533  }
534  else
535  {
536   t=GGtobin(*str++);
537   A|=(t&0x07)<<8;
538   C|=(t&0x08);
539
540   t=GGtobin(*str++);
541   C|=(t&0x07);
542   C|=(t&0x08)<<4;
543
544   t=GGtobin(*str++);
545   C|=(t&0x07)<<4;
546   V|=(t&0x08);
547   *a=A;
548   *v=V;
549   *c=C;
550   return(1);
551  }
552  return(0);
553 }
554
555 int FCEUI_DecodePAR(const char *str, uint16 *a, uint8 *v, int *c, int *type)
556 {
557  int boo[4];
558  if(strlen(str)!=8) return(0);
559
560  sscanf(str,"%02x%02x%02x%02x",boo,boo+1,boo+2,boo+3);
561
562  *c=-1;
563
564  if(1)
565  {
566   *a=(boo[3]<<8)|(boo[2]+0x7F);
567   *v=0;
568  }
569  else
570  {
571   *v=boo[3];
572   *a=boo[2]|(boo[1]<<8);
573  }
574  /* Zero-page addressing modes don't go through the normal read/write handlers in FCEU, so
575     we must do the old hacky method of RAM cheats.
576  */
577  if(*a<0x0100)
578   *type=0;
579  else
580   *type=1;
581  return(1);
582 }
583
584 /* name can be NULL if the name isn't going to be changed. */
585 /* same goes for a, v, and s(except the values of each one must be <0) */
586
587 int FCEUI_SetCheat(uint32 which, const char *name, int32 a, int32 v, int compare,int s, int type)
588 {
589  struct CHEATF *next=cheats;
590  uint32 x=0;
591
592  while(next)
593  {
594   if(x==which)
595   {
596    if(name)
597    {
598     char *t;
599
600     if((t=(char *)realloc(next->name,strlen(name+1))))
601     {
602      next->name=t;
603      strcpy(next->name,name);
604     }
605     else
606      return(0);
607    }
608    if(a>=0)
609     next->addr=a;
610    if(v>=0)
611     next->val=v;
612    if(s>=0)
613     next->status=s;
614    next->compare=compare;
615    next->type=type;
616
617    savecheats=1;
618    RebuildSubCheats();
619
620    return(1);
621   }
622   next=next->next;
623   x++;
624  }
625  return(0);
626 }
627
628 /* Convenience function. */
629 int FCEUI_ToggleCheat(uint32 which)
630 {
631  struct CHEATF *next=cheats;
632  uint32 x=0;
633
634  while(next)
635  {
636   if(x==which)
637   {
638    next->status=!next->status;
639    savecheats=1;
640    RebuildSubCheats();
641    return(next->status);
642   }
643   next=next->next;
644   x++;
645  }
646
647  return(-1);
648 }
649
650 static int InitCheatComp(void)
651 {
652  uint32 x;
653
654  CheatComp=(uint16*)malloc(65536*sizeof(uint16));
655  if(!CheatComp)
656  {
657   CheatMemErr();
658   return(0);
659  }
660  for(x=0;x<65536;x++)
661   CheatComp[x]=CHEATC_NONE;
662
663  return(1);
664 }
665
666 void FCEUI_CheatSearchSetCurrentAsOriginal(void)
667 {
668  uint32 x;
669  for(x=0x000;x<0x10000;x++)
670   if(!(CheatComp[x]&CHEATC_NOSHOW))
671   {
672    if(CheatRPtrs[x>>10])
673     CheatComp[x]=CheatRPtrs[x>>10][x];
674    else
675     CheatComp[x]|=CHEATC_NONE;
676   }
677 }
678
679 void FCEUI_CheatSearchShowExcluded(void)
680 {
681  uint32 x;
682
683  for(x=0x000;x<0x10000;x++)
684   CheatComp[x]&=~CHEATC_EXCLUDED;
685 }
686
687
688 int32 FCEUI_CheatSearchGetCount(void)
689 {
690  uint32 x,c=0;
691
692  if(CheatComp)
693  {
694   for(x=0x0000;x<0x10000;x++)
695    if(!(CheatComp[x]&CHEATC_NOSHOW) && CheatRPtrs[x>>10])
696     c++;
697  }
698
699  return c;
700 }
701 /* This function will give the initial value of the search and the current value at a location. */
702
703 void FCEUI_CheatSearchGet(int (*callb)(uint32 a, uint8 last, uint8 current, void *data),void *data)
704 {
705   uint32 x;
706
707   if(!CheatComp)
708   {
709    if(!InitCheatComp())
710     CheatMemErr();
711    return;
712   }
713
714   for(x=0;x<0x10000;x++)
715    if(!(CheatComp[x]&CHEATC_NOSHOW) && CheatRPtrs[x>>10])
716     if(!callb(x,CheatComp[x],CheatRPtrs[x>>10][x],data))
717      break;
718 }
719
720 void FCEUI_CheatSearchGetRange(uint32 first, uint32 last, int (*callb)(uint32 a, uint8 last, uint8 current))
721 {
722   uint32 x;
723   uint32 in=0;
724
725   if(!CheatComp)
726   {
727    if(!InitCheatComp())
728     CheatMemErr();
729    return;
730   }
731
732   for(x=0;x<0x10000;x++)
733    if(!(CheatComp[x]&CHEATC_NOSHOW) && CheatRPtrs[x>>10])
734    {
735     if(in>=first)
736      if(!callb(x,CheatComp[x],CheatRPtrs[x>>10][x]))
737       break;
738     in++;
739     if(in>last) return;
740    }
741 }
742
743 void FCEUI_CheatSearchBegin(void)
744 {
745  uint32 x;
746
747  if(!CheatComp)
748  {
749   if(!InitCheatComp())
750   {
751    CheatMemErr();
752    return;
753   }
754  }
755  for(x=0;x<0x10000;x++)
756  {
757   if(CheatRPtrs[x>>10])
758    CheatComp[x]=CheatRPtrs[x>>10][x];
759   else
760    CheatComp[x]=CHEATC_NONE;
761  }
762 }
763
764
765 static int INLINE CAbs(int x)
766 {
767  if(x<0)
768   return(0-x);
769  return x;
770 }
771
772 void FCEUI_CheatSearchEnd(int type, uint8 v1, uint8 v2)
773 {
774  uint32 x;
775
776  if(!CheatComp)
777  {
778   if(!InitCheatComp())
779   {
780    CheatMemErr();
781    return;
782   }
783  }
784
785
786  if(!type)      // Change to a specific value.
787  {
788   for(x=0;x<0x10000;x++)
789    if(!(CheatComp[x]&CHEATC_NOSHOW))
790    {
791     if(CheatComp[x]==v1 && CheatRPtrs[x>>10][x]==v2)
792     {
793
794     }
795     else
796      CheatComp[x]|=CHEATC_EXCLUDED;
797    }
798  }
799  else if(type==1)           // Search for relative change(between values).
800  {
801   for(x=0;x<0x10000;x++)
802    if(!(CheatComp[x]&CHEATC_NOSHOW))
803    {
804     if(CheatComp[x]==v1 && CAbs(CheatComp[x]-CheatRPtrs[x>>10][x])==v2)
805     {
806
807     }
808     else
809      CheatComp[x]|=CHEATC_EXCLUDED;
810    }
811  }
812  else if(type==2)                          // Purely relative change.
813  {
814   for(x=0x000;x<0x10000;x++)
815    if(!(CheatComp[x]&CHEATC_NOSHOW))
816    {
817     if(CAbs(CheatComp[x]-CheatRPtrs[x>>10][x])==v2)
818     {
819
820     }
821     else
822      CheatComp[x]|=CHEATC_EXCLUDED;
823    }
824  }
825  else if(type==3)                          // Any change.
826  {
827   for(x=0;x<0x10000;x++)
828    if(!(CheatComp[x]&CHEATC_NOSHOW))
829    {
830     if(CheatComp[x]!=CheatRPtrs[x>>10][x])
831     {
832
833     }
834     else
835      CheatComp[x]|=CHEATC_EXCLUDED;
836    }
837  }
838  else if(type==4)                         // Value decreased.
839  {
840   for(x=0;x<0x10000;x++)
841    if(!(CheatComp[x]&CHEATC_NOSHOW))
842    {
843     if(!(CheatRPtrs[x>>10][x]<CheatComp[x]))
844      CheatComp[x]|=CHEATC_EXCLUDED;
845    }
846  }
847  else if(type==5)                         // Value increased.
848  {
849   for(x=0;x<0x10000;x++)
850    if(!(CheatComp[x]&CHEATC_NOSHOW))
851    {
852     if(!(CheatRPtrs[x>>10][x]>CheatComp[x]))
853      CheatComp[x]|=CHEATC_EXCLUDED;
854    }
855  }
856  if(type>4)
857   FCEUI_CheatSearchSetCurrentAsOriginal();
858 }