/[pcsx2_0.9.7]/trunk/pcsx2/DataBase_Loader.h
ViewVC logotype

Annotation of /trunk/pcsx2/DataBase_Loader.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (hide annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (9 years, 9 months ago) by william
File MIME type: text/plain
File size: 12734 byte(s)
committing r3113 initial commit again...
1 william 31 /* 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     #pragma once
17    
18     #include "File_Reader.h"
19     #include "AppConfig.h"
20    
21     struct key_pair {
22     string key;
23     string value;
24    
25     key_pair() {}
26     key_pair(const string& _key, const string& _value)
27     : key(_key) , value(_value) {}
28     string toString() {
29     string t;
30    
31     if (key[0] == '[') {
32     t = key + "\n";
33     t += value;
34    
35     stringstream ss(key);
36     string t2;
37     ss >> t2;
38     t += "[/" + t2.substr(1, t2.length()-1);
39     if (t2.compare(t)) t += "]";
40     }
41     else {
42     t = key;
43     for (int a = 6 - key.length(); a > 0; a--) {
44     t += " "; // Padding for nice formatting on small key-names
45     }
46     t += " = " + value;
47     }
48     return t;
49     }
50     };
51    
52     class Game_Data {
53     public:
54     string id; // Serial Identification Code
55     deque<key_pair> kList; // List of all (key, value) pairs for game data
56     Game_Data(const string& _id)
57     : id(_id) {}
58     };
59    
60     // DataBase_Loader:
61     // Give the starting Key and Value you're looking for,
62     // and it will extract the necessary data from the database.
63     // Example:
64     // ---------------------------------------------
65     // Serial = SLUS-20486
66     // Name = Marvel vs. Capcom 2
67     // Region = NTSC-U
68     // ---------------------------------------------
69     // To Load this game data, use "Serial" as the initial Key
70     // then specify "SLUS-20486" as the value in the constructor.
71     // After the constructor loads the game data, you can use the
72     // DataBase_Loader class's methods to get the other key's values.
73     // Such as dbLoader.getString("Region") returns "NTSC-U"
74    
75     class DataBase_Loader {
76     private:
77     template<class T> string toString(const T& value) {
78     stringstream ss(ios_base::in | ios_base::out);
79     string tString;
80     ss << value;
81     ss >> tString;
82     return tString;
83     }
84     string toLower(const string& s) {
85     string retval( s );
86     for (uint i = 0; i < s.length(); i++) {
87     char& c = retval[i];
88     if (c >= 'A' && c <= 'Z') {
89     c += 'a' - 'A';
90     }
91     }
92     return retval;
93     }
94     bool strCompare(const string& s1, const string& s2) {
95     const string t1( toLower(s1) );
96     const string t2( toLower(s2) );
97     return !t1.compare(t2);
98     }
99     bool isComment(const string& s) {
100     const string sub( s.substr(0, 2) );
101     return (sub.compare("--") == 0) || (sub.compare("//") == 0);
102     }
103     void doError(const string& line, key_pair& keyPair, bool doMsg = false) {
104     if (doMsg) Console.Error("DataBase_Loader: Bad file data [%s]", line.c_str());
105     keyPair.key.clear();
106     }
107     void extractMultiLine(const string& line, key_pair& keyPair, File_Reader& reader, const stringstream& ss) {
108     string t;
109     string endString;
110     endString = "[/" + keyPair.key.substr(1, keyPair.key.length()-1);
111     if (keyPair.key[keyPair.key.length()-1] != ']') {
112     endString += "]";
113     keyPair.key = line;
114     }
115     for(;;) {
116     t = reader.getLine();
117    
118     if (!t.compare(endString)) break;
119     keyPair.value += t + "\n";
120     }
121     }
122     void extract(const string& line, key_pair& keyPair, File_Reader& reader) {
123     stringstream ss(line);
124     string t;
125     keyPair.key.clear();
126     keyPair.value.clear();
127     ss >> keyPair.key;
128     if (!line.length() || isComment(keyPair.key)) {
129     doError(line, keyPair);
130     return;
131     }
132     if (keyPair.key[0] == '[') {
133     extractMultiLine(line, keyPair, reader, ss);
134     return;
135     }
136     ss >> t;
137     if (t.compare("=") != 0) {
138     doError(line, keyPair, true);
139     return;
140     }
141     ss >> t;
142     if (isComment(t)) {
143     doError(line, keyPair, true);
144     return;
145     }
146     keyPair.value = t;
147     while (!ss.eof() && !ss.fail()) {
148     ss >> t;
149     if (isComment(t)) break;
150     keyPair.value += " " + t;
151     }
152     if (ss.fail()) {
153     doError(line, keyPair);
154     return;
155     }
156     }
157     public:
158     deque<Game_Data*> gList; // List of all game data
159     Game_Data* curGame; // Current game data
160     String_Stream header; // Header of the database
161     string baseKey; // Key to separate games by ("Serial")
162    
163     DataBase_Loader(const string& file, const string& key = "Serial", const string& value = "" ) {
164     curGame = NULL;
165     baseKey = key;
166     if (!fileExists(file)) {
167     Console.Error("DataBase_Loader: DataBase Not Found! [%s]", file.c_str());
168     }
169     File_Reader reader(file);
170     key_pair keyPair;
171     string s0;
172     Game_Data* game = NULL;
173     try {
174     for(;;) {
175     for(;;) { // Find first game
176     s0 = reader.getLine();
177     extract(s0, keyPair, reader);
178     if (keyPair.key.compare(key) == 0) break;
179     header.write(s0);
180     header.write("\n");
181     }
182     game = new Game_Data(keyPair.value);
183     game->kList.push_back(keyPair);
184     for (;;) { // Fill game data, find new game, repeat...
185     s0 = reader.getLine();
186     extract(s0, keyPair, reader);
187     if (keyPair.key.compare("") == 0) continue;
188     if (keyPair.key.compare(key) == 0) {
189     gList.push_back(game);
190     game = new Game_Data(keyPair.value);
191     }
192     game->kList.push_back(keyPair);
193     }
194     }
195     }
196     catch(int& i) { // Add Last Game if EOF
197     if (i==1 && game) gList.push_back(game);
198     }
199     if (!value.compare("")) return;
200     if (setGame(value)) Console.WriteLn("DataBase_Loader: Found Game! [%s]", value.c_str());
201     else Console.Warning("DataBase_Loader: Game Not Found! [%s]", value.c_str());
202     }
203    
204     virtual ~DataBase_Loader() throw() {
205     deque<Game_Data*>::iterator it = gList.begin();
206     for ( ; it != gList.end(); ++it) {
207     delete *it;
208     }
209     }
210    
211     // Sets the current game to the one matching the serial id given
212     // Returns true if game found, false if not found...
213     bool setGame(const string& id) {
214     deque<Game_Data*>::iterator it = gList.begin();
215     for ( ; it != gList.end(); ++it) {
216     if (strCompare(it[0]->id, id)) {
217     curGame = it[0];
218     return true;
219     }
220     }
221     curGame = NULL;
222     return false;
223     }
224    
225     // Returns true if a game is currently loaded into the database
226     // Returns false if otherwise (this means you need to call setGame()
227     // or it could mean the game was not found in the database at all...)
228     bool gameLoaded() {
229     return !!curGame;
230     }
231    
232     // Saves changes to the database
233     void saveToFile(const string& file = "DataBase.dbf") {
234     File_Writer writer(file);
235     writer.write(header.toString());
236     deque<Game_Data*>::iterator it = gList.begin();
237     for ( ; it != gList.end(); ++it) {
238     deque<key_pair>::iterator i = it[0]->kList.begin();
239     for ( ; i != it[0]->kList.end(); ++i) {
240     writer.write(i[0].toString() + "\n");
241     }
242     writer.write("---------------------------------------------\n");
243     }
244     }
245    
246     // Adds new game data to the database, and sets curGame to the new game...
247     // If searchDB is true, it searches the database to see if game already exists.
248     void addGame(const string& id, bool searchDB = true) {
249     if (searchDB && setGame(id)) return;
250     Game_Data* game = new Game_Data(id);
251     key_pair kp(baseKey, id);
252     game->kList.push_back(kp);
253     gList.push_back(game);
254     curGame = game;
255     }
256    
257     // Searches the current game's data to see if the given key exists
258     bool keyExists(const string& key) {
259     if (curGame) {
260     deque<key_pair>::iterator it = curGame->kList.begin();
261     for ( ; it != curGame->kList.end(); ++it) {
262     if (strCompare(it[0].key, key)) {
263     return true;
264     }
265     }
266     }
267     else Console.Error("DataBase_Loader: Game not set!");
268     return false;
269     }
270    
271     // Gets a string representation of the 'value' for the given key
272     string getString(const string& key) {
273     if (curGame) {
274     deque<key_pair>::iterator it = curGame->kList.begin();
275     for ( ; it != curGame->kList.end(); ++it) {
276     if (strCompare(it[0].key, key)) {
277     return it[0].value;
278     }
279     }
280     }
281     else Console.Error("DataBase_Loader: Game not set!");
282     return string();
283     }
284    
285     // Gets a wxString representation of the 'value' for the given key
286     wxString getStringWX(const string& key) {
287     return wxString(fromUTF8(getString(key).c_str()));
288     }
289    
290     // Gets a double representation of the 'value' for the given key
291     double getDouble(const string& key) {
292     return atof(getString(key).c_str());
293     }
294    
295     // Gets a float representation of the 'value' for the given key
296     float getFloat(const string& key) {
297     return (float)atof(getString(key).c_str());
298     }
299    
300     // Gets an integer representation of the 'value' for the given key
301     int getInt(const string& key) {
302     return strtoul(getString(key).c_str(), NULL, 0);
303     }
304    
305     // Gets a u8 representation of the 'value' for the given key
306     u8 getU8(const string& key) {
307     return (u8)atoi(getString(key).c_str());
308     }
309    
310     // Gets a bool representation of the 'value' for the given key
311     bool getBool(const string& key) {
312     return !!atoi(getString(key).c_str());
313     }
314    
315     // Write a string value to the specified key
316     void writeString(const string& key, const string& value) {
317     if (curGame) {
318     deque<key_pair>::iterator it = curGame->kList.begin();
319     for ( ; it != curGame->kList.end(); ++it) {
320     if (strCompare(it[0].key, key)) {
321     it[0].value = value;
322     return;
323     }
324     }
325     key_pair tKey(key, value);
326     curGame->kList.push_back(tKey);
327     }
328     else Console.Error("DataBase_Loader: Game not set!");
329     }
330    
331     // Write a wxString value to the specified key
332     void writeStringWX(const string& key, const wxString& value) {
333     writeString(key, value.ToUTF8().data());
334     }
335    
336     // Write a double value to the specified key
337     void writeDouble(const string& key, double value) {
338     writeString(key, toString(value));
339     }
340    
341     // Write a float value to the specified key
342     void writeFloat(const string& key, float value) {
343     writeString(key, toString(value));
344     }
345    
346     // Write an integer value to the specified key
347     void writeInt(const string& key, int value) {
348     writeString(key, toString(value));
349     }
350    
351     // Write a u8 value to the specified key
352     void writeU8(const string& key, u8 value) {
353     writeString(key, toString(value));
354     }
355    
356     // Write a bool value to the specified key
357     void writeBool(const string& key, bool value) {
358     writeString(key, toString(value?1:0));
359     }
360     };
361    
362     static wxString compatToStringWX(int compat) {
363     switch (compat) {
364     case 6: return wxString(L"Perfect");
365     case 5: return wxString(L"Playable");
366     case 4: return wxString(L"In-Game");
367     case 3: return wxString(L"Menu");
368     case 2: return wxString(L"Intro");
369     case 1: return wxString(L"Nothing");
370     default: return wxString(L"Unknown");
371     }
372     }
373    
374     #define checkGamefix(gFix) { \
375     if (gameDB->keyExists(#gFix)) { \
376     SetGameFixConfig().gFix = gameDB->getBool(#gFix); \
377     Console.WriteLn("Loading Gamefix: " #gFix); \
378     gf++; \
379     } \
380     }
381    
382     // Load Game Settings found in database
383     // (game fixes, round modes, clamp modes, etc...)
384     // Returns number of gamefixes set
385     static int loadGameSettings(DataBase_Loader* gameDB) {
386     if (gameDB && gameDB->gameLoaded()) {
387     SSE_MXCSR eeMX = EmuConfig.Cpu.sseMXCSR;
388     SSE_MXCSR vuMX = EmuConfig.Cpu.sseVUMXCSR;
389     int eeRM = eeMX.GetRoundMode();
390     int vuRM = vuMX.GetRoundMode();
391     bool rm = 0;
392     int gf = 0;
393     if (gameDB->keyExists("eeRoundMode")) { eeRM = gameDB->getInt("eeRoundMode"); rm=1; gf++; }
394     if (gameDB->keyExists("vuRoundMode")) { vuRM = gameDB->getInt("vuRoundMode"); rm=1; gf++; }
395     if (rm && eeRM<4 && vuRM<4) {
396     Console.WriteLn("Game DataBase: Changing roundmodes! [ee=%d] [vu=%d]", eeRM, vuRM);
397     SetCPUState(eeMX.SetRoundMode((SSE_RoundMode)eeRM), vuMX.SetRoundMode((SSE_RoundMode)vuRM));
398     }
399     if (gameDB->keyExists("eeClampMode")) {
400     int clampMode = gameDB->getInt("eeClampMode");
401     Console.WriteLn("Game DataBase: Changing EE/FPU clamp mode [mode=%d]", clampMode);
402     SetRecompilerConfig().fpuOverflow = clampMode >= 1;
403     SetRecompilerConfig().fpuExtraOverflow = clampMode >= 2;
404     SetRecompilerConfig().fpuFullMode = clampMode >= 3;
405     gf++;
406     }
407     if (gameDB->keyExists("vuClampMode")) {
408     int clampMode = gameDB->getInt("vuClampMode");
409     Console.WriteLn("Game DataBase: Changing VU0/VU1 clamp mode [mode=%d]", clampMode);
410     SetRecompilerConfig().vuOverflow = clampMode >= 1;
411     SetRecompilerConfig().vuExtraOverflow = clampMode >= 2;
412     SetRecompilerConfig().vuSignOverflow = clampMode >= 3;
413     gf++;
414     }
415     checkGamefix(VuAddSubHack);
416     checkGamefix(VuClipFlagHack);
417     checkGamefix(FpuCompareHack);
418     checkGamefix(FpuMulHack);
419     checkGamefix(FpuNegDivHack);
420     checkGamefix(XgKickHack);
421     checkGamefix(IPUWaitHack);
422     checkGamefix(EETimingHack);
423     return gf;
424     }
425     return 0;
426     }
427    
428     extern ScopedPtr<DataBase_Loader> GameDB;

  ViewVC Help
Powered by ViewVC 1.1.22