/[pcsx2_0.9.7]/trunk/pcsx2/Patch.cpp
ViewVC logotype

Contents of /trunk/pcsx2/Patch.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 62 - (show annotations) (download)
Tue Sep 7 11:08:22 2010 UTC (10 years, 1 month ago) by william
File size: 7840 byte(s)
Auto Commited Import of: pcsx2-0.9.7-r3738-debug in ./trunk
1 /* PCSX2 - PS2 Emulator for PCs
2 * Copyright (C) 2002-2010 PCSX2 Dev Team
3 *
4 * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5 * of the GNU Lesser General Public License as published by the Free Software Found-
6 * ation, either version 3 of the License, or (at your option) any later version.
7 *
8 * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 * PURPOSE. See the GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License along with PCSX2.
13 * If not, see <http://www.gnu.org/licenses/>.
14 */
15
16 #include "PrecompiledHeader.h"
17
18 #define _PC_ // disables MIPS opcode macros.
19
20 #include "IopCommon.h"
21 #include "Patch.h"
22 #include "GameDatabase.h"
23 #include <wx/textfile.h>
24
25 IniPatch Patch[ MAX_PATCH ];
26 IniPatch Cheat[ MAX_CHEAT ];
27
28 int patchnumber = 0;
29 int cheatnumber = 0;
30
31 wxString strgametitle;
32
33 struct PatchTextTable
34 {
35 int code;
36 const wxChar* text;
37 PATCHTABLEFUNC* func;
38 };
39
40 static const PatchTextTable commands_patch[] =
41 {
42 { 1, L"comment", PatchFunc::comment },
43 { 2, L"patch", PatchFunc::patch },
44 { 0, wxEmptyString, NULL } // Array Terminator
45 };
46
47 static const PatchTextTable commands_cheat[] =
48 {
49 { 1, L"comment", PatchFunc::comment },
50 { 2, L"patch", PatchFunc::cheat },
51 { 0, wxEmptyString, NULL } // Array Terminator
52 };
53
54 static const PatchTextTable dataType[] =
55 {
56 { 1, L"byte", NULL },
57 { 2, L"short", NULL },
58 { 3, L"word", NULL },
59 { 4, L"double", NULL },
60 { 5, L"extended", NULL },
61 { 0, wxEmptyString, NULL }
62 };
63
64 static const PatchTextTable cpuCore[] =
65 {
66 { 1, L"EE", NULL },
67 { 2, L"IOP", NULL },
68 { 0, wxEmptyString, NULL }
69 };
70
71 // IniFile Functions.
72
73 void inifile_trim( wxString& buffer )
74 {
75 buffer.Trim(false); // trims left side.
76
77 if( buffer.Length() <= 1 ) // this I'm not sure about... - air
78 {
79 buffer.Empty();
80 return;
81 }
82
83 if( buffer.Left( 2 ) == L"//" )
84 {
85 buffer.Empty();
86 return;
87 }
88
89 buffer.Trim(true); // trims right side.
90 }
91
92 static int PatchTableExecute( const ParsedAssignmentString& set, const PatchTextTable * Table )
93 {
94 int i = 0;
95
96 while (Table[i].text[0])
97 {
98 if (!set.lvalue.Cmp(Table[i].text))
99 {
100 if (Table[i].func) Table[i].func(set.lvalue, set.rvalue);
101 break;
102 }
103 i++;
104 }
105
106 return Table[i].code;
107 }
108
109 // This routine is for executing the commands of the ini file.
110 void inifile_command(bool isCheat, const wxString& cmd)
111 {
112 ParsedAssignmentString set( cmd );
113
114 // Is this really what we want to be doing here? Seems like just leaving it empty/blank
115 // would make more sense... --air
116 if (set.rvalue.IsEmpty()) set.rvalue = set.lvalue;
117
118 int code = PatchTableExecute(set, isCheat ? commands_cheat : commands_patch);
119 }
120
121 // This routine receives a string containing patches, trims it,
122 // Then sends the command to be parsed.
123 void TrimPatches(wxString& s)
124 {
125 wxStringTokenizer tkn( s, L"\n" );
126
127 while(tkn.HasMoreTokens()) {
128 inifile_command(0, tkn.GetNextToken());
129 }
130 }
131
132 // This routine loads patches from the game database
133 // Returns number of patches loaded
134 int InitPatches(const wxString& crc, const Game_Data& game)
135 {
136 bool patchFound = false;
137 wxString patch;
138 patchnumber = 0;
139
140 if (game.IsOk())
141 {
142 if (game.sectionExists(L"patches", crc)) {
143 patch = game.getSection(L"patches", crc);
144 patchFound = true;
145 }
146 else if (game.keyExists(L"[patches]")) {
147 patch = game.getString(L"[patches]");
148 patchFound = true;
149 }
150 }
151
152 if (patchFound) TrimPatches(patch);
153
154 return patchnumber;
155 }
156
157 // This routine receives a file from inifile_read, trims it,
158 // Then sends the command to be parsed.
159 void inifile_process(wxTextFile &f1 )
160 {
161 for (uint i = 0; i < f1.GetLineCount(); i++)
162 {
163 inifile_trim(f1[i]);
164 if (!f1[i].IsEmpty()) inifile_command(1, f1[i]);
165 }
166 }
167
168 // This routine loads cheats from *.pnach files
169 // Returns number of cheats loaded
170 // Note: Should be called after InitPatches()
171 int InitCheats(const wxString& name)
172 {
173 wxTextFile f1;
174 wxString buffer;
175 cheatnumber = 0;
176
177 // FIXME : We need to add a 'cheats' folder to the AppConfig, and use that instead. --air
178
179 buffer = Path::Combine(L"cheats", name + L".pnach");
180
181 if(!f1.Open(buffer) && wxFileName::IsCaseSensitive())
182 {
183 f1.Open( Path::Combine(L"cheats", name.Upper() + L".pnach") );
184 }
185
186 if(!f1.IsOpened())
187 {
188 Console.WriteLn( Color_Gray, "No cheats found. Resuming execution without cheats..." );
189 return 0;
190 }
191
192 Console.WriteLn( Color_Green, "Cheats found!");
193 inifile_process( f1 );
194
195 Console.WriteLn("Cheats Loaded: %d", cheatnumber);
196 return cheatnumber;
197 }
198
199 static u32 StrToU32(const wxString& str, int base = 10)
200 {
201 unsigned long l;
202 str.ToULong(&l, base);
203 return l;
204 }
205
206 static u64 StrToU64(const wxString& str, int base = 10)
207 {
208 wxULongLong_t l;
209 str.ToULongLong(&l, base);
210 return l;
211 }
212
213 // PatchFunc Functions.
214 namespace PatchFunc
215 {
216 void comment( const wxString& text1, const wxString& text2 )
217 {
218 Console.WriteLn( L"comment: " + text2 );
219 }
220
221 struct PatchPieces
222 {
223 wxArrayString m_pieces;
224
225 PatchPieces( const wxString& param )
226 {
227 SplitString( m_pieces, param, L"," );
228 if( m_pieces.Count() < 5 )
229 throw wxsFormat( L"Expected 5 data parameters; only found %d", m_pieces.Count() );
230 }
231
232 const wxString& PlaceToPatch() const { return m_pieces[0]; }
233 const wxString& CpuType() const { return m_pieces[1]; }
234 const wxString& MemAddr() const { return m_pieces[2]; }
235 const wxString& OperandSize() const { return m_pieces[3]; }
236 const wxString& WriteValue() const { return m_pieces[4]; }
237 };
238
239 template<bool isCheat>
240 void patchHelper(const wxString& cmd, const wxString& param) {
241 // Error Handling Note: I just throw simple wxStrings here, and then catch them below and
242 // format them into more detailed cmd+data+error printouts. If we want to add user-friendly
243 // (translated) messages for display in a popup window then we'll have to upgrade the
244 // exception a little bit.
245
246 DevCon.WriteLn(cmd + L" " + param);
247
248 try
249 {
250 if (isCheat && cheatnumber >= MAX_CHEAT)
251 throw wxString( L"Maximum number of cheats reached" );
252 if(!isCheat && patchnumber >= MAX_PATCH)
253 throw wxString( L"Maximum number of patches reached" );
254
255 IniPatch& iPatch = isCheat ? Cheat[cheatnumber] : Patch[patchnumber];
256 PatchPieces pieces(param);
257
258 iPatch.enabled = 0;
259
260 iPatch.placetopatch = StrToU32(pieces.PlaceToPatch(), 10);
261 iPatch.cpu = (patch_cpu_type)PatchTableExecute(pieces.CpuType(), cpuCore);
262 iPatch.addr = StrToU32(pieces.MemAddr(), 16);
263 iPatch.type = (patch_data_type)PatchTableExecute(pieces.OperandSize(), dataType);
264 iPatch.data = StrToU64(pieces.WriteValue(), 16);
265
266 if (iPatch.cpu == 0)
267 throw wxsFormat(L"Unrecognized CPU Target: '%s'", pieces.CpuType().c_str());
268
269 if (iPatch.type == 0)
270 throw wxsFormat(L"Unrecognized Operand Size: '%s'", pieces.OperandSize().c_str());
271
272 iPatch.enabled = 1; // omg success!!
273
274 if (isCheat) cheatnumber++;
275 else patchnumber++;
276 }
277 catch( wxString& exmsg )
278 {
279 Console.Error(L"(Patch) Error Parsing: %s=%s", cmd.c_str(), param.c_str());
280 Console.Indent().Error( exmsg );
281 }
282 }
283 void patch(const wxString& cmd, const wxString& param) { patchHelper<0>(cmd, param); }
284 void cheat(const wxString& cmd, const wxString& param) { patchHelper<1>(cmd, param); }
285 }
286
287 // This is for applying patches directly to memory
288 void ApplyPatch(int place)
289 {
290 for (int i = 0; i < patchnumber; i++)
291 {
292 if (Patch[i].placetopatch == place)
293 _ApplyPatch(&Patch[i]);
294 }
295 }
296
297 // This is for applying cheats directly to memory
298 void ApplyCheat(int place)
299 {
300 for (int i = 0; i < cheatnumber; i++)
301 {
302 if (Cheat[i].placetopatch == place)
303 _ApplyPatch(&Cheat[i]);
304 }
305 }

  ViewVC Help
Powered by ViewVC 1.1.22