1 /******************************************************************************/
2 /* Mednafen, Cheat Formats Decoding */
3 /******************************************************************************/
4 /* gb.cpp:
5 ** Copyright (C) 2006-2016 Mednafen Team
6 **
7 ** This program is free software; you can redistribute it and/or
8 ** modify it under the terms of the GNU General Public License
9 ** as published by the Free Software Foundation; either version 2
10 ** of the License, or (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software Foundation, Inc.,
19 ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21
22 #include <mednafen/mednafen.h>
23 #include <mednafen/mempatcher.h>
24
25 #include <trio/trio.h>
26
27 #include "gb.h"
28
29 namespace Mednafen
30 {
31
CharToNibble(char thechar)32 static uint8 CharToNibble(char thechar)
33 {
34 const char lut[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
35
36 thechar = MDFN_azupper(thechar);
37
38 for(int x = 0; x < 16; x++)
39 if(lut[x] == thechar)
40 return(x);
41
42 return(0xFF);
43 }
44
DecodeGG(const std::string & cheat_string,MemoryPatch * patch)45 static bool DecodeGG(const std::string& cheat_string, MemoryPatch* patch)
46 {
47 char str[10];
48 unsigned len;
49
50 memset(str, 0, sizeof(str));
51
52 switch(cheat_string.size())
53 {
54 default:
55 throw(MDFN_Error(0, _("Game Genie code is of an incorrect length.")));
56 break;
57
58 case 6:
59 case 9:
60 strcpy(str, cheat_string.c_str());
61 break;
62
63 case 11:
64 if(cheat_string[7] != '-' && cheat_string[7] != '_' && cheat_string[7] != ' ')
65 throw(MDFN_Error(0, _("Game Genie code is malformed.")));
66
67 str[6] = cheat_string[8];
68 str[7] = cheat_string[9];
69 str[8] = cheat_string[10];
70
71 case 7:
72 if(cheat_string[3] != '-' && cheat_string[3] != '_' && cheat_string[3] != ' ')
73 throw(MDFN_Error(0, _("Game Genie code is malformed.")));
74
75 str[0] = cheat_string[0];
76 str[1] = cheat_string[1];
77 str[2] = cheat_string[2];
78
79 str[3] = cheat_string[4];
80 str[4] = cheat_string[5];
81 str[5] = cheat_string[6];
82 break;
83 }
84
85 len = strlen(str);
86
87 for(unsigned x = 0; x < len; x++)
88 {
89 if(CharToNibble(str[x]) == 0xFF)
90 {
91 if(str[x] & 0x80)
92 throw MDFN_Error(0, _("Invalid character in Game Genie code."));
93 else
94 throw MDFN_Error(0, _("Invalid character in Game Genie code: %c"), str[x]);
95 }
96 }
97
98 uint32 tmp_address;
99 uint8 tmp_value;
100 uint8 tmp_compare = 0;
101
102 tmp_address = (CharToNibble(str[5]) << 12) | (CharToNibble(str[2]) << 8) | (CharToNibble(str[3]) << 4) | (CharToNibble(str[4]) << 0);
103 tmp_address ^= 0xF000;
104 tmp_value = (CharToNibble(str[0]) << 4) | (CharToNibble(str[1]) << 0);
105
106 if(len == 9)
107 {
108 tmp_compare = (CharToNibble(str[6]) << 4) | (CharToNibble(str[8]) << 0);
109 tmp_compare = (tmp_compare >> 2) | ((tmp_compare << 6) & 0xC0);
110 tmp_compare ^= 0xBA;
111 }
112
113 patch->addr = tmp_address;
114 patch->val = tmp_value;
115
116 if(len == 9)
117 {
118 patch->compare = tmp_compare;
119 patch->type = 'C';
120 }
121 else
122 {
123 patch->compare = 0;
124 patch->type = 'S';
125 }
126
127 patch->length = 1;
128
129 return(false);
130 }
131
DecodeGS(const std::string & cheat_string,MemoryPatch * patch)132 static bool DecodeGS(const std::string& cheat_string, MemoryPatch* patch)
133 {
134 if(cheat_string.size() != 8)
135 throw MDFN_Error(0, _("GameShark code is of an incorrect length."));
136
137 for(unsigned x = 0; x < 8; x++)
138 {
139 if(CharToNibble(cheat_string[x]) == 0xFF)
140 {
141 if(cheat_string[x] & 0x80)
142 throw MDFN_Error(0, _("Invalid character in GameShark code."));
143 else
144 throw MDFN_Error(0, _("Invalid character in GameShark code: %c"), cheat_string[x]);
145 }
146 }
147 uint8 bank = 0;
148 uint16 la = 0;
149
150
151 bank = (CharToNibble(cheat_string[0]) << 4) | (CharToNibble(cheat_string[1]) << 0);
152 for(unsigned x = 0; x < 4; x++)
153 la |= CharToNibble(cheat_string[4 + x]) << ((x ^ 1) * 4);
154
155 if(la >= 0xD000 && la <= 0xDFFF)
156 patch->addr = 0x10000 | ((bank & 0x7) << 12) | (la & 0xFFF);
157 else
158 patch->addr = la;
159
160 patch->val = (CharToNibble(cheat_string[2]) << 4) | (CharToNibble(cheat_string[3]) << 0);
161
162 patch->compare = 0;
163 patch->type = 'R';
164 patch->length = 1;
165
166 return(false);
167 }
168
169 const std::vector<CheatFormatStruct> CheatFormats_GB =
170 {
171 { "Game Genie", gettext_noop("Genies will eat your goats."), DecodeGG },
172 { "GameShark", gettext_noop("Sharks in your soup."), DecodeGS },
173 };
174
175 }
176