mirror of https://github.com/PCSX2/pcsx2.git
353 lines
7.1 KiB
C++
353 lines
7.1 KiB
C++
#include <windows.h>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <vector>
|
|
#include <string>
|
|
using namespace std;
|
|
|
|
#include "tinyxml.h"
|
|
|
|
extern "C" {
|
|
# include "../ps2etypes.h"
|
|
# include "../patch.h"
|
|
|
|
# ifdef __WIN32__
|
|
struct AppData {
|
|
HWND hWnd; // Main window handle
|
|
HINSTANCE hInstance; // Application instance
|
|
HMENU hMenu; // Main window menu
|
|
HANDLE hConsole;
|
|
} extern gApp;
|
|
# endif
|
|
|
|
void SysPrintf(char *fmt, ...);
|
|
int LoadPatch(char *patchfile);
|
|
}
|
|
|
|
#include "../cheatscpp.h"
|
|
|
|
int LoadGroup(TiXmlNode *group, int parent);
|
|
|
|
Group::Group(int nParent,bool nEnabled, string &nTitle):
|
|
parentIndex(nParent),enabled(nEnabled),title(nTitle)
|
|
{
|
|
}
|
|
|
|
Patch::Patch(int patch, int grp, bool en, string &ttl):
|
|
title(ttl),
|
|
group(grp),
|
|
enabled(en),
|
|
patchIndex(patch)
|
|
{
|
|
}
|
|
|
|
Patch Patch::operator =(const Patch&p)
|
|
{
|
|
title.assign(p.title);
|
|
group=p.group;
|
|
enabled=p.enabled;
|
|
patchIndex=p.patchIndex;
|
|
return *this;
|
|
}
|
|
|
|
|
|
vector<Group> groups;
|
|
vector<Patch> patches;
|
|
|
|
int LoadPatch(char *crc)
|
|
{
|
|
char pfile[256];
|
|
sprintf(pfile,"patches\\%s.xml",crc);
|
|
|
|
patchnumber=0;
|
|
|
|
TiXmlDocument doc( pfile );
|
|
bool loadOkay = doc.LoadFile();
|
|
if ( !loadOkay )
|
|
{
|
|
SysPrintf("XML Patch Loader: Could not load file '%s'. Error='%s'.\n", pfile, doc.ErrorDesc() );
|
|
return -1;
|
|
}
|
|
|
|
TiXmlNode *root = doc.FirstChild("GAME");
|
|
if(!root)
|
|
{
|
|
SysPrintf("XML Patch Loader: Root node is not GAME, invalid patch file.\n");
|
|
return -1;
|
|
}
|
|
|
|
TiXmlElement *rootelement = root->ToElement();
|
|
|
|
const char *title=rootelement->Attribute("title");
|
|
if(title)
|
|
SysPrintf("XML Patch Loader: Game Title: %s\n",title);
|
|
|
|
int result=LoadGroup(root,-1);
|
|
if(result) {
|
|
patchnumber=0;
|
|
return result;
|
|
}
|
|
|
|
#ifdef __WIN32__
|
|
if (gApp.hConsole)
|
|
{
|
|
if(title)
|
|
SetConsoleTitle(title);
|
|
else
|
|
SetConsoleTitle("<No Title>");
|
|
}
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int LoadGroup(TiXmlNode *group,int gParent)
|
|
{
|
|
|
|
TiXmlElement *groupelement = group->ToElement();
|
|
|
|
const char *gtitle=groupelement->Attribute("title");
|
|
if(gtitle)
|
|
SysPrintf("XML Patch Loader: Group Title: %s\n",gtitle);
|
|
|
|
const char *enable=groupelement->Attribute("enabled");
|
|
bool gEnabled=true;
|
|
if(enable)
|
|
{
|
|
if(strcmp(enable,"false")==0)
|
|
{
|
|
SysPrintf("XML Patch Loader: Group is disabled.\n");
|
|
gEnabled=false;
|
|
}
|
|
}
|
|
|
|
TiXmlNode *comment = group->FirstChild("COMMENT");
|
|
if(comment)
|
|
{
|
|
TiXmlElement *cmelement = comment->ToElement();
|
|
const char *comment = cmelement->GetText();
|
|
if(comment)
|
|
SysPrintf("XML Patch Loader: Group Comment:\n%s\n---\n",comment);
|
|
}
|
|
|
|
string t;
|
|
|
|
if(gtitle)
|
|
t.assign(gtitle);
|
|
else
|
|
t.clear();
|
|
|
|
Group gp=Group(gParent,gEnabled,t);
|
|
groups.push_back(gp);
|
|
|
|
int gIndex=groups.size()-1;
|
|
|
|
|
|
TiXmlNode *fastmemory=group->FirstChild("FASTMEMORY");
|
|
if(fastmemory!=NULL)
|
|
SetFastMemory(1);
|
|
|
|
TiXmlNode *roundmode=group->FirstChild("ROUNDMODE");
|
|
if(roundmode!=NULL)
|
|
{
|
|
int eetype=0x0000;
|
|
int vutype=0x6000;
|
|
|
|
TiXmlElement *rm=roundmode->ToElement();
|
|
if(rm!=NULL)
|
|
{
|
|
const char *eetext=rm->Attribute("ee");
|
|
const char *vutext=rm->Attribute("vu");
|
|
|
|
if(eetext != NULL) {
|
|
eetype = 0xffff;
|
|
if( stricmp(eetext, "near") == 0 ) {
|
|
eetype = 0x0000;
|
|
}
|
|
else if( stricmp(eetext, "down") == 0 ) {
|
|
eetype = 0x2000;
|
|
}
|
|
else if( stricmp(eetext, "up") == 0 ) {
|
|
eetype = 0x4000;
|
|
}
|
|
else if( stricmp(eetext, "chop") == 0 ) {
|
|
eetype = 0x6000;
|
|
}
|
|
}
|
|
|
|
if(vutext != NULL) {
|
|
vutype = 0xffff;
|
|
if( stricmp(vutext, "near") == 0 ) {
|
|
vutype = 0x0000;
|
|
}
|
|
else if( stricmp(vutext, "down") == 0 ) {
|
|
vutype = 0x2000;
|
|
}
|
|
else if( stricmp(vutext, "up") == 0 ) {
|
|
vutype = 0x4000;
|
|
}
|
|
else if( stricmp(vutext, "chop") == 0 ) {
|
|
vutype = 0x6000;
|
|
}
|
|
}
|
|
}
|
|
if(( eetype == 0xffff )||( vutype == 0xffff )) {
|
|
printf("XML Patch Loader: WARNING: Invalid value in ROUNDMODE.\n");
|
|
}
|
|
else {
|
|
SetRoundMode(eetype,vutype);
|
|
}
|
|
}
|
|
|
|
TiXmlNode *cpatch = group->FirstChild("PATCH");
|
|
while(cpatch)
|
|
{
|
|
TiXmlElement *celement = cpatch->ToElement();
|
|
if(!celement)
|
|
{
|
|
SysPrintf("XML Patch Loader: ERROR: Couldn't convert node to element.\n" );
|
|
return -1;
|
|
}
|
|
|
|
|
|
const char *ptitle=celement->Attribute("title");
|
|
const char *penable=celement->Attribute("enabled");
|
|
const char *applymode=celement->Attribute("applymode");
|
|
const char *place=celement->Attribute("place");
|
|
const char *address=celement->Attribute("address");
|
|
const char *size=celement->Attribute("size");
|
|
const char *value=celement->Attribute("value");
|
|
|
|
if(ptitle) {
|
|
SysPrintf("XML Patch Loader: Patch title: %s\n", ptitle);
|
|
}
|
|
|
|
bool penabled=gEnabled;
|
|
if(penable)
|
|
{
|
|
if(strcmp(penable,"false")==0)
|
|
{
|
|
SysPrintf("XML Patch Loader: Patch is disabled.\n");
|
|
penabled=false;
|
|
}
|
|
}
|
|
|
|
if(!applymode) applymode="frame";
|
|
if(!place) place="EE";
|
|
if(!address) {
|
|
SysPrintf("XML Patch Loader: ERROR: Patch doesn't contain an address.\n");
|
|
return -1;
|
|
}
|
|
if(!value) {
|
|
SysPrintf("XML Patch Loader: ERROR: Patch doesn't contain a value.\n");
|
|
return -1;
|
|
}
|
|
if(!size) {
|
|
SysPrintf("XML Patch Loader: WARNING: Patch doesn't contain the size. Trying to deduce from the value size.\n");
|
|
switch(strlen(value))
|
|
{
|
|
case 8:
|
|
case 7:
|
|
case 6:
|
|
case 5:
|
|
size="32";
|
|
break;
|
|
case 4:
|
|
case 3:
|
|
size="16";
|
|
break;
|
|
case 2:
|
|
case 1:
|
|
size="8";
|
|
break;
|
|
case 0:
|
|
size="0";
|
|
break;
|
|
default:
|
|
size="64";
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(strcmp(applymode,"startup")==0)
|
|
{
|
|
patch[patchnumber].placetopatch=0;
|
|
} else
|
|
if(strcmp(applymode,"vsync")==0)
|
|
{
|
|
patch[patchnumber].placetopatch=1;
|
|
} else
|
|
{
|
|
SysPrintf("XML Patch Loader: ERROR: Invalid applymode attribute.\n");
|
|
patchnumber=0;
|
|
return -1;
|
|
}
|
|
|
|
if(strcmp(place,"EE")==0)
|
|
{
|
|
patch[patchnumber].cpu=1;
|
|
} else
|
|
if(strcmp(place,"IOP")==0)
|
|
{
|
|
patch[patchnumber].cpu=2;
|
|
} else
|
|
{
|
|
SysPrintf("XML Patch Loader: ERROR: Invalid place attribute.\n");
|
|
patchnumber=0;
|
|
return -1;
|
|
}
|
|
|
|
if(strcmp(size,"64")==0)
|
|
{
|
|
patch[patchnumber].type=4;
|
|
} else
|
|
if(strcmp(size,"32")==0)
|
|
{
|
|
patch[patchnumber].type=3;
|
|
} else
|
|
if(strcmp(size,"16")==0)
|
|
{
|
|
patch[patchnumber].type=2;
|
|
} else
|
|
if(strcmp(size,"8")==0)
|
|
{
|
|
patch[patchnumber].type=1;
|
|
} else
|
|
{
|
|
SysPrintf("XML Patch Loader: ERROR: Invalid size attribute.\n");
|
|
patchnumber=0;
|
|
return -1;
|
|
}
|
|
|
|
sscanf( address, "%X", &patch[ patchnumber ].addr );
|
|
sscanf( value, "%I64X", &patch[ patchnumber ].data );
|
|
|
|
patch[patchnumber].enabled=penabled?1:0;
|
|
|
|
string pt;
|
|
|
|
if(ptitle)
|
|
pt.assign(ptitle);
|
|
else
|
|
pt.clear();
|
|
|
|
Patch p=Patch(patchnumber,gIndex,penabled,pt);
|
|
patches.push_back(p);
|
|
|
|
patchnumber++;
|
|
|
|
cpatch = cpatch->NextSibling("PATCH");
|
|
}
|
|
|
|
cpatch = group->FirstChild("GROUP");
|
|
while(cpatch) {
|
|
int result=LoadGroup(cpatch,gIndex);
|
|
if(result) return result;
|
|
cpatch = cpatch->NextSibling("GROUP");
|
|
}
|
|
|
|
return 0;
|
|
}
|