1 /* FCE Ultra - NES/Famicom Emulator
3 * Copyright notice for this file:
4 * Copyright (C) 2002 Ben Parnell
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.
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.
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
34 static uint8 *CheatRPtrs[64];
36 void FCEU_CheatResetRAM(void)
44 void FCEU_CheatAddRAM(int s, uint32 A, uint8 *p)
62 struct CHEATF *cheats=0,*cheatsl=0;
65 #define CHEATC_NONE 0x8000
66 #define CHEATC_EXCLUDED 0x4000
67 #define CHEATC_NOSHOW 0xC000
69 static uint16 *CheatComp=0;
70 static int savecheats;
72 static int AddCheatEntry(char *name, uint32 addr, uint8 val, int status);
74 static void CheatMemErr(void)
76 FCEUD_PrintError("Error allocating memory for cheat data.");
79 /* This function doesn't allocate any memory for "name" */
80 static int AddCheatEntry(char *name, uint32 addr, uint8 val, int status)
83 if(!(temp=malloc(sizeof(struct CHEATF))))
106 void LoadGameCheats(void)
115 char linebuf[256+4+2+2+1+1]; /* 256 for name, 4 for address, 2 for value, 2 for semicolons, 1 for status, 1 for null */
120 if(!(fp=fopen(FCEU_MakeFName(FCEUMKF_CHEAT,0,0),"rb")))
123 while(fgets(linebuf,256+4+2+2+1+1,fp)>0)
126 namebuf[0]=0; // If the cheat doesn't have a name...
129 strncpy(namebuf,&linebuf[1+4+2+2],257);
130 if(sscanf(&linebuf[1],"%04x%*[:]%02x",&addr,&val)!=2)
136 strncpy(namebuf,&linebuf[4+2+2],257);
137 if(sscanf(linebuf,"%04x%*[:]%02x",&addr,&val)!=2) continue;
142 if(namebuf[x]==10 || namebuf[x]==13)
149 if(!(name=malloc(strlen(namebuf)+1)))
153 strcpy(name,namebuf);
154 AddCheatEntry(name,addr,val,status);
162 void FlushGameCheats(void)
174 struct CHEATF *next=cheats;
189 struct CHEATF *next=cheats;
191 if((fp=fopen(FCEU_MakeFName(FCEUMKF_CHEAT,0,0),"wb")))
197 fprintf(fp,"%04x:%02x:%s\n",next->addr,next->val,next->name);
199 fprintf(fp,":%04x:%02x:%s\n",next->addr,next->val,next->name);
209 FCEUD_PrintError("Error saving cheats.");
213 remove(FCEU_MakeFName(FCEUMKF_CHEAT,0,0));
218 int FCEUI_AddCheat(char *name, uint32 addr, uint8 val)
222 if(!(t=malloc(strlen(name)+1)))
228 if(!AddCheatEntry(t,addr,val,1))
237 int FCEUI_DelCheat(uint32 which)
243 for(prev=0,cur=cheats;;)
245 if(x==which) // Remove this cheat.
247 if(prev) // Update pointer to this cheat.
249 if(cur->next) // More cheats.
250 prev->next=cur->next;
254 cheatsl=prev; // Set the previous cheat as the last cheat.
257 else // This is the first cheat.
259 if(cur->next) // More cheats
262 cheats=cheatsl=0; // No (more) cheats.
264 free(cur->name); // Now that all references to this cheat are removed,
265 free(cur); // free the memory.
267 } // *END REMOVE THIS CHEAT*
270 if(!cur->next) // No more cheats to go through(this shouldn't ever happen...)
281 void ApplyPeriodicCheats(void)
283 struct CHEATF *cur=cheats;
289 if(CheatRPtrs[cur->addr>>10])
290 CheatRPtrs[cur->addr>>10][cur->addr]=cur->val;
299 void FCEUI_ListCheats(int (*callb)(char *name, uint32 a, uint8 v, int s))
301 struct CHEATF *next=cheats;
305 if(!callb(next->name,next->addr,next->val,next->status)) break;
310 int FCEUI_GetCheat(uint32 which, char **name, uint32 *a, uint8 *v, int *s)
312 struct CHEATF *next=cheats;
336 /* name can be NULL if the name isn't going to be changed. */
337 /* same goes for a, v, and s(except the values of each one must be <0) */
339 int FCEUI_SetCheat(uint32 which, char *name, int32 a, int32 v, int s)
341 struct CHEATF *next=cheats;
352 if((t=realloc(next->name,strlen(name+1))))
355 strcpy(next->name,name);
376 static int InitCheatComp(void)
380 CheatComp=malloc(65536*sizeof(uint16));
387 CheatComp[x]=CHEATC_NONE;
392 void FCEUI_CheatSearchSetCurrentAsOriginal(void)
395 for(x=0x000;x<0x10000;x++)
396 if(!(CheatComp[x]&CHEATC_NOSHOW))
398 if(CheatRPtrs[x>>10])
399 CheatComp[x]=CheatRPtrs[x>>10][x];
401 CheatComp[x]|=CHEATC_NONE;
405 void FCEUI_CheatSearchShowExcluded(void)
409 for(x=0x000;x<0x10000;x++)
410 CheatComp[x]&=~CHEATC_EXCLUDED;
414 int32 FCEUI_CheatSearchGetCount(void)
420 for(x=0x0000;x<0x10000;x++)
421 if(!(CheatComp[x]&CHEATC_NOSHOW) && CheatRPtrs[x>>10])
427 /* This function will give the initial value of the search and the current value at a location. */
429 void FCEUI_CheatSearchGet(int (*callb)(uint32 a, uint8 last, uint8 current))
440 for(x=0;x<0x10000;x++)
441 if(!(CheatComp[x]&CHEATC_NOSHOW) && CheatRPtrs[x>>10])
442 if(!callb(x,CheatComp[x],CheatRPtrs[x>>10][x]))
446 void FCEUI_CheatSearchGetRange(uint32 first, uint32 last, int (*callb)(uint32 a, uint8 last, uint8 current))
458 for(x=0;x<0x10000;x++)
459 if(!(CheatComp[x]&CHEATC_NOSHOW) && CheatRPtrs[x>>10])
462 if(!callb(x,CheatComp[x],CheatRPtrs[x>>10][x]))
469 void FCEUI_CheatSearchBegin(void)
481 for(x=0;x<0x10000;x++)
483 if(CheatRPtrs[x>>10])
484 CheatComp[x]=CheatRPtrs[x>>10][x];
486 CheatComp[x]=CHEATC_NONE;
491 static int INLINE CAbs(int x)
498 void FCEUI_CheatSearchEnd(int type, uint8 v1, uint8 v2)
512 if(!type) // Change to a specific value.
514 for(x=0;x<0x10000;x++)
515 if(!(CheatComp[x]&CHEATC_NOSHOW))
517 if(CheatComp[x]==v1 && CheatRPtrs[x>>10][x]==v2)
522 CheatComp[x]|=CHEATC_EXCLUDED;
525 else if(type==1) // Search for relative change(between values).
527 for(x=0;x<0x10000;x++)
528 if(!(CheatComp[x]&CHEATC_NOSHOW))
530 if(CheatComp[x]==v1 && CAbs(CheatComp[x]-CheatRPtrs[x>>10][x])==v2)
535 CheatComp[x]|=CHEATC_EXCLUDED;
538 else if(type==2) // Purely relative change.
540 for(x=0x000;x<0x10000;x++)
541 if(!(CheatComp[x]&CHEATC_NOSHOW))
543 if(CAbs(CheatComp[x]-CheatRPtrs[x>>10][x])==v2)
548 CheatComp[x]|=CHEATC_EXCLUDED;
551 else if(type==3) // Any change.
553 for(x=0x000;x<0x10000;x++)
554 if(!(CheatComp[x]&CHEATC_NOSHOW))
556 if(CheatComp[x]!=CheatRPtrs[x>>10][x])
561 CheatComp[x]|=CHEATC_EXCLUDED;