mirror of https://github.com/PCSX2/pcsx2.git
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:
parent
1d534c7481
commit
7abc292cb2
1088
bin/DataBase.dbf
1088
bin/DataBase.dbf
File diff suppressed because it is too large
Load Diff
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue