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;
key_pair(string _key, string _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 {
@ -63,7 +83,21 @@ private:
if (doMsg) Console.Error("DataBase_Loader: Bad file data [%s]", line.c_str());
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");
if (eol != string::npos) line = line.substr(0, eol);
@ -76,6 +110,10 @@ private:
doError(line, keyPair);
return;
}
if (keyPair.key[0] == '[') {
extractMultiLine(line, keyPair, reader, ss);
return;
}
ss >> t;
if (t.compare("=") != 0) {
doError(line, keyPair, true);
@ -90,8 +128,7 @@ private:
while (!ss.eof() && !ss.fail()) {
ss >> t;
if (isComment(t)) break;
keyPair.value += " ";
keyPair.value += t;
keyPair.value += " " + t;
}
if (ss.fail()) {
doError(line, keyPair);
@ -117,7 +154,7 @@ public:
for(;;) {
for(;;) { // Find first game
s0 = reader.getLine();
extract(s0, keyPair);
extract(s0, keyPair, reader);
if (keyPair.key.compare(key) == 0) break;
header.write(s0);
header.write("\n");
@ -126,7 +163,7 @@ public:
game->kList.push_back(keyPair);
for (;;) { // Fill game data, find new game, repeat...
s0 = reader.getLine();
extract(s0, keyPair);
extract(s0, keyPair, reader);
if (keyPair.key.compare("") == 0) continue;
if (keyPair.key.compare(key) == 0) {
gList.push_back(game);
@ -178,13 +215,7 @@ public:
for ( ; it != gList.end(); ++it) {
deque<key_pair>::iterator i = it[0]->kList.begin();
for ( ; i != it[0]->kList.end(); ++i) {
writer.write(i[0].key);
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(i[0].toString() + "\n");
}
writer.write("---------------------------------------------\n");
}
@ -201,6 +232,20 @@ public:
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
string getString(string key) {
if (curGame) {

View File

@ -95,11 +95,16 @@ public:
};
class String_Stream {
private:
char buff[2048];
public:
stringstream* ss;
String_Stream() {
ss = new stringstream(stringstream::in | stringstream::out);
}
String_Stream(string& str) {
ss = new stringstream(str, stringstream::in | stringstream::out);
}
~String_Stream() {
delete ss;
}
@ -112,6 +117,17 @@ public:
string toString() {
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) {

View File

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

View File

@ -589,7 +589,7 @@ void __fastcall eeGameStarting()
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);
if (EmuConfig.EnablePatches) InitPatch(gameCRC);