Patches are now part of the game database.

They can be CRC specific, or just based on the game serial.

Examples:
[patches]
	// This patch is loaded regardless of crc
	patch=0,EE,002aa040,word,24020001
[/patches]

[patches = 84993903]
	// Patches go here
	// This is only loaded if crc = 84993903
	patch=0,EE,002bc040,word,24020341
[/patches]


notes:
- pcsx2 only loads the first [patches] block that matches the game.
- The [patches] block based on crc takes priority when pcsx2 searches for patches...
- Everything in-between the patches block gets fed to pcsx2's old patch parser; so currently the patch syntax is the same as before...
- A lot of patches weren't added to the database since they didn't include serial codes in their *.pnach files :/


git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3007 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
cottonvibes 2010-05-15 03:11:00 +00:00
parent 1d534c7481
commit 7abc292cb2
5 changed files with 1184 additions and 43 deletions

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,26 @@ struct key_pair {
string value; string value;
key_pair(string _key, string _value) key_pair(string _key, string _value)
: key(_key) , value(_value) {} : key(_key) , value(_value) {}
string toString() {
string t;
if (key[0] == '[') {
t = key + "\n";
t += value;
stringstream ss(key);
string t2;
ss >> t2;
t += "[/" + t2.substr(1, t2.length()-1);
if (t2.compare(t)) t += "]";
}
else {
t = key;
for (int a = 6 - key.length(); a > 0; a--) {
t += " "; // Padding for nice formatting on small key-names
}
t += " = " + value;
}
return t;
}
}; };
class Game_Data { class Game_Data {
@ -63,7 +83,21 @@ private:
if (doMsg) Console.Error("DataBase_Loader: Bad file data [%s]", line.c_str()); if (doMsg) Console.Error("DataBase_Loader: Bad file data [%s]", line.c_str());
keyPair.key = ""; keyPair.key = "";
} }
void extract(string& line, key_pair& keyPair) { void extractMultiLine(string& line, key_pair& keyPair, File_Reader& reader, stringstream& ss) {
string t = "";
string endString;
endString = "[/" + keyPair.key.substr(1, keyPair.key.length()-1);
if (keyPair.key[keyPair.key.length()-1] != ']') {
endString += "]";
keyPair.key = line;
}
for(;;) {
t = reader.getLine();
if (!t.compare(endString)) break;
keyPair.value += t + "\n";
}
}
void extract(string& line, key_pair& keyPair, File_Reader& reader) {
int eol = line.rfind("\r"); int eol = line.rfind("\r");
if (eol != string::npos) line = line.substr(0, eol); if (eol != string::npos) line = line.substr(0, eol);
@ -76,6 +110,10 @@ private:
doError(line, keyPair); doError(line, keyPair);
return; return;
} }
if (keyPair.key[0] == '[') {
extractMultiLine(line, keyPair, reader, ss);
return;
}
ss >> t; ss >> t;
if (t.compare("=") != 0) { if (t.compare("=") != 0) {
doError(line, keyPair, true); doError(line, keyPair, true);
@ -90,8 +128,7 @@ private:
while (!ss.eof() && !ss.fail()) { while (!ss.eof() && !ss.fail()) {
ss >> t; ss >> t;
if (isComment(t)) break; if (isComment(t)) break;
keyPair.value += " "; keyPair.value += " " + t;
keyPair.value += t;
} }
if (ss.fail()) { if (ss.fail()) {
doError(line, keyPair); doError(line, keyPair);
@ -117,7 +154,7 @@ public:
for(;;) { for(;;) {
for(;;) { // Find first game for(;;) { // Find first game
s0 = reader.getLine(); s0 = reader.getLine();
extract(s0, keyPair); extract(s0, keyPair, reader);
if (keyPair.key.compare(key) == 0) break; if (keyPair.key.compare(key) == 0) break;
header.write(s0); header.write(s0);
header.write("\n"); header.write("\n");
@ -126,7 +163,7 @@ public:
game->kList.push_back(keyPair); game->kList.push_back(keyPair);
for (;;) { // Fill game data, find new game, repeat... for (;;) { // Fill game data, find new game, repeat...
s0 = reader.getLine(); s0 = reader.getLine();
extract(s0, keyPair); extract(s0, keyPair, reader);
if (keyPair.key.compare("") == 0) continue; if (keyPair.key.compare("") == 0) continue;
if (keyPair.key.compare(key) == 0) { if (keyPair.key.compare(key) == 0) {
gList.push_back(game); gList.push_back(game);
@ -178,13 +215,7 @@ public:
for ( ; it != gList.end(); ++it) { for ( ; it != gList.end(); ++it) {
deque<key_pair>::iterator i = it[0]->kList.begin(); deque<key_pair>::iterator i = it[0]->kList.begin();
for ( ; i != it[0]->kList.end(); ++i) { for ( ; i != it[0]->kList.end(); ++i) {
writer.write(i[0].key); writer.write(i[0].toString() + "\n");
for (int a = 6 - i[0].key.length(); a > 0; a--) {
writer.write(" "); // Padding for nice formatting on small key-names
}
writer.write(" = ");
writer.write(i[0].value);
writer.write("\n");
} }
writer.write("---------------------------------------------\n"); writer.write("---------------------------------------------\n");
} }
@ -201,6 +232,20 @@ public:
curGame = game; curGame = game;
} }
// Searches the current game's data to see if the given key exists
bool keyExists(string key) {
if (curGame) {
deque<key_pair>::iterator it = curGame->kList.begin();
for ( ; it != curGame->kList.end(); ++it) {
if (!it[0].key.compare(key)) {
return true;
}
}
}
else Console.Error("DataBase_Loader: Game not set!");
return false;
}
// Gets a string representation of the 'value' for the given key // Gets a string representation of the 'value' for the given key
string getString(string key) { string getString(string key) {
if (curGame) { if (curGame) {

View File

@ -95,11 +95,16 @@ public:
}; };
class String_Stream { class String_Stream {
private:
char buff[2048];
public: public:
stringstream* ss; stringstream* ss;
String_Stream() { String_Stream() {
ss = new stringstream(stringstream::in | stringstream::out); ss = new stringstream(stringstream::in | stringstream::out);
} }
String_Stream(string& str) {
ss = new stringstream(str, stringstream::in | stringstream::out);
}
~String_Stream() { ~String_Stream() {
delete ss; delete ss;
} }
@ -112,6 +117,17 @@ public:
string toString() { string toString() {
return ss->str(); return ss->str();
} }
string getLine() {
ss->getline(buff, sizeof(buff));
return string(buff);
}
wxString getLineWX() {
ss->getline(buff, sizeof(buff));
return wxString(fromAscii(buff));
}
bool finished() {
return ss->eof() || ss->fail();
}
}; };
static bool fileExists(string file) { static bool fileExists(string file) {

View File

@ -19,8 +19,7 @@
#include "IopCommon.h" #include "IopCommon.h"
#include "Patch.h" #include "Patch.h"
#include "DataBase_Loader.h"
#include <wx/textfile.h>
IniPatch Patch[ MAX_PATCH ]; IniPatch Patch[ MAX_PATCH ];
@ -418,12 +417,16 @@ void inifile_command( const wxString& cmd )
// This routine recieves a file from inifile_read, trims it, // This routine recieves a file from inifile_read, trims it,
// Then sends the command to be parsed. // Then sends the command to be parsed.
void inifile_process(wxTextFile &f1 ) void inifile_process(string& s)
{ {
for (uint i = 0; i < f1.GetLineCount(); i++) String_Stream ss(s);
{ wxString buff;
inifile_trim(f1[i]); while (!ss.finished())
if (!f1[i].IsEmpty()) inifile_command(f1[i]); {
buff = ss.getLineWX();
//Console.Error("%s", buff.ToAscii());
inifile_trim(buff);
if (!buff.IsEmpty()) inifile_command(buff);
} }
} }
@ -431,28 +434,27 @@ void inifile_process(wxTextFile &f1 )
// loads it, trims the commands, and sends them to be parsed. // loads it, trims the commands, and sends them to be parsed.
void inifile_read(const wxString& name ) void inifile_read(const wxString& name )
{ {
wxTextFile f1; bool patchFound = false;
wxString buffer; string patch;
string crc = string(name.ToAscii());
patchnumber = 0; patchnumber = 0;
// FIXME : We need to add a 'patches' folder to the AppConfig, and use that instead. --air if (GameDB && GameDB->gameLoaded()) {
if (GameDB->keyExists("[patches = " + crc + "]")) {
buffer = Path::Combine(L"patches", name + L".pnach"); patch = GameDB->getString("[patches = " + crc + "]");
patchFound = true;
if(!f1.Open(buffer) && wxFileName::IsCaseSensitive()) }
{ else if (GameDB->keyExists("[patches]")) {
f1.Open( Path::Combine(L"patches", name.Upper() + L".pnach") ); patch = GameDB->getString("[patches]");
patchFound = true;
}
} }
if(!f1.IsOpened()) if (patchFound) {
{ Console.WriteLn(Color_Green, "Patch found!");
Console.WriteLn( Color_Gray, "No patch found. Resuming execution without a patch (this is NOT an error)." ); inifile_process(patch);
return;
} }
else Console.WriteLn(Color_Gray, "No patch found. Resuming execution without a patch (this is NOT an error).");
Console.WriteLn( Color_Green, "Patch found!");
inifile_process( f1 );
} }
void _ApplyPatch(IniPatch *p) void _ApplyPatch(IniPatch *p)

View File

@ -589,7 +589,7 @@ void __fastcall eeGameStarting()
gameCompat = L" [Status = "+compatToStringWX(compat)+L"]"; gameCompat = L" [Status = "+compatToStringWX(compat)+L"]";
} }
// if patches found the following title will be overwritten // this title can be overwritten by patches if they set the gametitle key
Console.SetTitle(gameName + gameSerial + gameCompat); Console.SetTitle(gameName + gameSerial + gameCompat);
if (EmuConfig.EnablePatches) InitPatch(gameCRC); if (EmuConfig.EnablePatches) InitPatch(gameCRC);