Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/yabause/src/cheat.c
2 views
1
/* Copyright 2007-2008 Theo Berkau
2
3
This file is part of Yabause.
4
5
Yabause is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; either version 2 of the License, or
8
(at your option) any later version.
9
10
Yabause is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with Yabause; if not, write to the Free Software
17
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
*/
19
20
#include <stdlib.h>
21
#include "cheat.h"
22
#include "memory.h"
23
#include "sh2core.h"
24
25
cheatlist_struct *cheatlist=NULL;
26
int numcheats=0;
27
int cheatsize;
28
29
#define DoubleWordSwap(x) x = (((x & 0xFF000000) >> 24) + \
30
((x & 0x00FF0000) >> 8) + \
31
((x & 0x0000FF00) << 8) + \
32
((x & 0x000000FF) << 24));
33
34
//////////////////////////////////////////////////////////////////////////////
35
36
int CheatInit(void)
37
{
38
cheatsize = 10;
39
if ((cheatlist = (cheatlist_struct *)calloc(cheatsize, sizeof(cheatlist_struct))) == NULL)
40
return -1;
41
cheatlist[0].type = CHEATTYPE_NONE;
42
43
return 0;
44
}
45
46
//////////////////////////////////////////////////////////////////////////////
47
48
void CheatDeInit(void)
49
{
50
if (cheatlist)
51
free(cheatlist);
52
cheatlist = NULL;
53
}
54
55
//////////////////////////////////////////////////////////////////////////////
56
57
int CheatAddCode(int type, u32 addr, u32 val)
58
{
59
cheatlist[numcheats].type = type;
60
cheatlist[numcheats].addr = addr;
61
cheatlist[numcheats].val = val;
62
cheatlist[numcheats].desc = NULL;
63
cheatlist[numcheats].enable = 1;
64
numcheats++;
65
66
// Make sure we still have room
67
if (numcheats >= cheatsize)
68
{
69
cheatlist = realloc(cheatlist, sizeof(cheatlist_struct) * (cheatsize * 2));
70
cheatsize *= 2;
71
}
72
73
cheatlist[numcheats].type = CHEATTYPE_NONE;
74
75
return 0;
76
}
77
78
//////////////////////////////////////////////////////////////////////////////
79
80
int CheatAddARCode(const char *code)
81
{
82
unsigned long addr;
83
unsigned short val;
84
sscanf(code, "%08lX %04hX", &addr, &val);
85
switch (addr >> 28)
86
{
87
case 0x0:
88
// One time word write(fix me)
89
return -1;
90
case 0x1:
91
return CheatAddCode(CHEATTYPE_WORDWRITE, addr & 0x0FFFFFFF, val);
92
case 0x3:
93
return CheatAddCode(CHEATTYPE_BYTEWRITE, addr & 0x0FFFFFFF, val);
94
case 0xD:
95
return CheatAddCode(CHEATTYPE_ENABLE, addr & 0x0FFFFFFF, val);
96
default: return -1;
97
}
98
99
return 0;
100
}
101
102
//////////////////////////////////////////////////////////////////////////////
103
104
static int FindCheat(int type, u32 addr, u32 val)
105
{
106
int i;
107
108
for (i = 0; i < numcheats; i++)
109
{
110
if (cheatlist[i].type == type &&
111
cheatlist[i].addr == addr &&
112
cheatlist[i].val == val)
113
return i;
114
}
115
116
return -1;
117
}
118
119
//////////////////////////////////////////////////////////////////////////////
120
121
int CheatChangeDescription(int type, u32 addr, u32 val, char *desc)
122
{
123
int i;
124
125
if ((i = FindCheat(type, addr, val)) == -1)
126
// There is no matches, so let's bail
127
return -1;
128
129
return CheatChangeDescriptionByIndex(i, desc);
130
}
131
132
//////////////////////////////////////////////////////////////////////////////
133
134
int CheatChangeDescriptionByIndex(int i, char *desc)
135
{
136
// Free old description(if existing)
137
if (cheatlist[i].desc)
138
free(cheatlist[i].desc);
139
140
cheatlist[i].desc = strdup(desc);
141
return 0;
142
}
143
144
//////////////////////////////////////////////////////////////////////////////
145
146
int CheatRemoveCode(int type, u32 addr, u32 val)
147
{
148
int i;
149
150
if ((i = FindCheat(type, addr, val)) == -1)
151
// There is no matches, so let's bail
152
return -1;
153
154
return CheatRemoveCodeByIndex(i);
155
}
156
157
//////////////////////////////////////////////////////////////////////////////
158
159
int CheatRemoveCodeByIndex(int i)
160
{
161
// If there's a description, free the memory.
162
if (cheatlist[i].desc)
163
{
164
free(cheatlist[i].desc);
165
cheatlist[i].desc = NULL;
166
}
167
168
// Move all entries one forward
169
for (; i < numcheats-1; i++)
170
memcpy(&cheatlist[i], &cheatlist[i+1], sizeof(cheatlist_struct));
171
172
numcheats--;
173
174
// Set the last one to type none
175
cheatlist[numcheats].type = CHEATTYPE_NONE;
176
177
return 0;
178
}
179
180
//////////////////////////////////////////////////////////////////////////////
181
182
int CheatRemoveARCode(const char *code)
183
{
184
unsigned long addr;
185
unsigned short val;
186
sscanf(code, "%08lX %04hX", &addr, &val);
187
188
switch (addr >> 28)
189
{
190
case 0x1:
191
return CheatRemoveCode(CHEATTYPE_WORDWRITE, addr & 0x0FFFFFFF, val);
192
case 0x3:
193
return CheatRemoveCode(CHEATTYPE_BYTEWRITE, addr & 0x0FFFFFFF, val);
194
case 0xD:
195
return CheatRemoveCode(CHEATTYPE_ENABLE, addr & 0x0FFFFFFF, val);
196
default: return -1;
197
}
198
}
199
200
//////////////////////////////////////////////////////////////////////////////
201
202
void CheatClearCodes(void)
203
{
204
while (numcheats > 0)
205
CheatRemoveCodeByIndex(numcheats-1);
206
}
207
208
//////////////////////////////////////////////////////////////////////////////
209
210
void CheatEnableCode(int index)
211
{
212
cheatlist[index].enable = 1;
213
}
214
215
//////////////////////////////////////////////////////////////////////////////
216
217
void CheatDisableCode(int index)
218
{
219
cheatlist[index].enable = 0;
220
}
221
222
//////////////////////////////////////////////////////////////////////////////
223
224
void CheatDoPatches(void)
225
{
226
int i;
227
228
for (i = 0; ; i++)
229
{
230
switch (cheatlist[i].type)
231
{
232
case CHEATTYPE_NONE:
233
return;
234
case CHEATTYPE_ENABLE:
235
if (cheatlist[i].enable == 0)
236
continue;
237
if (MappedMemoryReadWord(cheatlist[i].addr) != cheatlist[i].val)
238
return;
239
break;
240
case CHEATTYPE_BYTEWRITE:
241
if (cheatlist[i].enable == 0)
242
continue;
243
MappedMemoryWriteByte(cheatlist[i].addr, (u8)cheatlist[i].val);
244
SH2WriteNotify(cheatlist[i].addr, 1);
245
break;
246
case CHEATTYPE_WORDWRITE:
247
if (cheatlist[i].enable == 0)
248
continue;
249
MappedMemoryWriteWord(cheatlist[i].addr, (u16)cheatlist[i].val);
250
SH2WriteNotify(cheatlist[i].addr, 2);
251
break;
252
case CHEATTYPE_LONGWRITE:
253
if (cheatlist[i].enable == 0)
254
continue;
255
MappedMemoryWriteLong(cheatlist[i].addr, cheatlist[i].val);
256
SH2WriteNotify(cheatlist[i].addr, 4);
257
break;
258
}
259
}
260
}
261
262
//////////////////////////////////////////////////////////////////////////////
263
264
cheatlist_struct *CheatGetList(int *cheatnum)
265
{
266
if (cheatnum == NULL)
267
return NULL;
268
269
*cheatnum = numcheats;
270
return cheatlist;
271
}
272
273
//////////////////////////////////////////////////////////////////////////////
274
275
int CheatSave(const char *filename)
276
{
277
FILE *fp;
278
int i;
279
int num;
280
IOCheck_struct check;
281
282
if (!filename)
283
return -1;
284
285
if ((fp = fopen(filename, "wb")) == NULL)
286
return -1;
287
288
fprintf(fp, "YCHT");
289
num = numcheats;
290
#ifndef WORDS_BIGENDIAN
291
DoubleWordSwap(num);
292
#endif
293
ywrite(&check, (void *)&num, sizeof(int), 1, fp);
294
295
for(i = 0; i < numcheats; i++)
296
{
297
u8 descsize;
298
cheatlist_struct cheat;
299
300
memcpy(&cheat, &cheatlist[i], sizeof(cheatlist_struct));
301
#ifndef WORDS_BIGENDIAN
302
DoubleWordSwap(cheat.type);
303
DoubleWordSwap(cheat.addr);
304
DoubleWordSwap(cheat.val);
305
DoubleWordSwap(cheat.enable);
306
#endif
307
ywrite(&check, (void *)&cheat.type, sizeof(int), 1, fp);
308
ywrite(&check, (void *)&cheat.addr, sizeof(u32), 1, fp);
309
ywrite(&check, (void *)&cheat.val, sizeof(u32), 1, fp);
310
descsize = (u8)strlen(cheatlist[i].desc)+1;
311
ywrite(&check, (void *)&descsize, sizeof(u8), 1, fp);
312
ywrite(&check, (void *)cheatlist[i].desc, sizeof(char), descsize, fp);
313
ywrite(&check, (void *)&cheat.enable, sizeof(int), 1, fp);
314
}
315
316
fclose (fp);
317
318
return 0;
319
}
320
321
//////////////////////////////////////////////////////////////////////////////
322
323
int CheatLoad(const char *filename)
324
{
325
FILE *fp;
326
int i;
327
char id[4];
328
char desc[256];
329
IOCheck_struct check;
330
331
if (!filename)
332
return -1;
333
334
if ((fp = fopen(filename, "rb")) == NULL)
335
return -1;
336
337
yread(&check, (void *)id, 1, 4, fp);
338
if (strncmp(id, "YCHT", 4) != 0)
339
{
340
fclose(fp);
341
return -2;
342
}
343
344
CheatClearCodes();
345
346
yread(&check, (void *)&numcheats, sizeof(int), 1, fp);
347
#ifndef WORDS_BIGENDIAN
348
DoubleWordSwap(numcheats);
349
#endif
350
351
if (numcheats >= cheatsize)
352
{
353
cheatlist = realloc(cheatlist, sizeof(cheatlist_struct) * (cheatsize * 2));
354
memset((void *)cheatlist, 0, sizeof(cheatlist_struct) * (cheatsize * 2));
355
cheatsize *= 2;
356
}
357
358
for(i = 0; i < numcheats; i++)
359
{
360
u8 descsize;
361
362
yread(&check, (void *)&cheatlist[i].type, sizeof(int), 1, fp);
363
yread(&check, (void *)&cheatlist[i].addr, sizeof(u32), 1, fp);
364
yread(&check, (void *)&cheatlist[i].val, sizeof(u32), 1, fp);
365
yread(&check, (void *)&descsize, sizeof(u8), 1, fp);
366
yread(&check, (void *)desc, sizeof(char), descsize, fp);
367
CheatChangeDescriptionByIndex(i, desc);
368
yread(&check, (void *)&cheatlist[i].enable, sizeof(int), 1, fp);
369
#ifndef WORDS_BIGENDIAN
370
DoubleWordSwap(cheatlist[i].type);
371
DoubleWordSwap(cheatlist[i].addr);
372
DoubleWordSwap(cheatlist[i].val);
373
DoubleWordSwap(cheatlist[i].enable);
374
#endif
375
}
376
377
fclose (fp);
378
379
return 0;
380
}
381
382
//////////////////////////////////////////////////////////////////////////////
383
384
385