Convert the patches code over to use wxStrings.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2139 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
arcum42 2009-11-06 08:55:57 +00:00
parent b687d4a10b
commit 5d5eac8c59
2 changed files with 212 additions and 173 deletions

View File

@ -20,6 +20,8 @@
#include "IopCommon.h" #include "IopCommon.h"
#include "Patch.h" #include "Patch.h"
#include <wx/textfile.h>
IniPatch Patch[ MAX_PATCH ]; IniPatch Patch[ MAX_PATCH ];
u32 SkipCount = 0, IterationCount = 0; u32 SkipCount = 0, IterationCount = 0;
@ -32,63 +34,46 @@ wxString strgametitle;
struct PatchTextTable struct PatchTextTable
{ {
const char *text; wxString text;
int code; int code;
PATCHTABLEFUNC func; PATCHTABLEFUNC func;
}; };
static const PatchTextTable commands[] = static const PatchTextTable commands[] =
{ {
{ "comment", 1, PatchFunc::comment }, { L"comment", 1, PatchFunc::comment },
{ "gametitle", 2, PatchFunc::gametitle }, { L"gametitle", 2, PatchFunc::gametitle },
{ "patch", 3, PatchFunc::patch }, { L"patch", 3, PatchFunc::patch },
{ "fastmemory", 4, NULL }, // enable for faster but bugger mem (mvc2 is faster) { L"fastmemory", 4, NULL }, // enable for faster but bugger mem (mvc2 is faster)
{ "roundmode", 5, PatchFunc::roundmode }, // changes rounding mode for floating point { L"roundmode", 5, PatchFunc::roundmode }, // changes rounding mode for floating point
// syntax: roundmode=X,Y // syntax: roundmode=X,Y
// possible values for X,Y: NEAR, DOWN, UP, CHOP // possible values for X,Y: NEAR, DOWN, UP, CHOP
// X - EE rounding mode (default is NEAR) // X - EE rounding mode (default is NEAR)
// Y - VU rounding mode (default is CHOP) // Y - VU rounding mode (default is CHOP)
{ "zerogs", 6, PatchFunc::zerogs }, // zerogs=hex { L"zerogs", 6, PatchFunc::zerogs }, // zerogs=hex
{ "vunanmode",8, NULL }, { L"vunanmode",8, NULL },
{ "ffxhack",9, NULL}, { L"ffxhack",9, NULL},
{ "xkickdelay",10, NULL}, { L"xkickdelay",10, NULL},
{ "", 0, NULL } { wxEmptyString, 0, NULL }
}; };
static const PatchTextTable dataType[] = static const PatchTextTable dataType[] =
{ {
{ "byte", 1, NULL }, { L"byte", 1, NULL },
{ "short", 2, NULL }, { L"short", 2, NULL },
{ "word", 3, NULL }, { L"word", 3, NULL },
{ "double", 4, NULL }, { L"double", 4, NULL },
{ "extended", 5, NULL }, { L"extended", 5, NULL },
{ "", 0, NULL } { wxEmptyString, 0, NULL }
}; };
static const PatchTextTable cpuCore[] = static const PatchTextTable cpuCore[] =
{ {
{ "EE", 1, NULL }, { L"EE", 1, NULL },
{ "IOP", 2, NULL }, { L"IOP", 2, NULL },
{ "", 0, NULL } { wxEmptyString, 0, NULL }
}; };
static int PatchTableExecute( char* text1, char* text2, const PatchTextTable * Table )
{
int i = 0;
while (Table[i].text[0])
{
if (!strcmp(Table[i].text, text1))
{
if (Table[i].func) Table[i].func(text1, text2);
break;
}
i++;
}
return Table[i].code;
}
void writeCheat() void writeCheat()
{ {
switch (LastType) switch (LastType)
@ -382,76 +367,10 @@ void handle_extended_t( IniPatch *p)
// IniFile Functions. // IniFile Functions.
// This routine is for executing the commands of the ini file.
void inifile_command( char* cmd )
{
int code;
char command[ 256 ];
char parameter[ 256 ];
// extract param part (after '=')
char* pEqual = strchr( cmd, '=' );
if ( ! pEqual ) pEqual = cmd+strlen(cmd); // fastmemory doesn't have =
memzero( command );
memzero( parameter );
strncpy( command, cmd, pEqual - cmd );
strncpy( parameter, pEqual + 1, sizeof( parameter ) );
inifile_trim( command );
inifile_trim( parameter );
code = PatchTableExecute( command, parameter, commands );
}
#define USE_CRAZY_BASHIT_INSANE_TRIM
#ifdef USE_CRAZY_BASHIT_INSANE_TRIM
void inifile_trim( char* buffer )
{
char* pInit = buffer;
char* pEnd = NULL;
while ((*pInit == ' ') || (*pInit == '\t')) //skip space
{
pInit++;
}
if ((pInit[0] == '/') && (pInit[1] == '/')) //remove comment
{
buffer[0] = '\0';
return;
}
pEnd = pInit + strlen(pInit) - 1;
if ( pEnd <= pInit )
{
buffer[0] = '\0';
return;
}
while ((*pEnd == '\r') || (*pEnd == '\n') || (*pEnd == ' ') || (*pEnd == '\t'))
{
pEnd--;
}
if (pEnd <= pInit)
{
buffer[0] = '\0';
return;
}
memmove( buffer, pInit, pEnd - pInit + 1 );
buffer[ pEnd - pInit + 1 ] = '\0';
}
#else
// New version of trim (untested), which I coded but can't use yet because the // New version of trim (untested), which I coded but can't use yet because the
// rest of Patch needs to be more wxString-involved first. // rest of Patch needs to be more wxString-involved first. --Air
// And now it is... --Arcum42
void inifile_trim( wxString& buffer ) void inifile_trim( wxString& buffer )
{ {
buffer.Trim( false ); // trims left side. buffer.Trim( false ); // trims left side.
@ -462,7 +381,7 @@ void inifile_trim( wxString& buffer )
return; return;
} }
if( buffer.Left( 2 ) == "//" ) if( buffer.Left( 2 ) == L"//" )
{ {
buffer.Clear(); buffer.Clear();
return; return;
@ -471,49 +390,87 @@ void inifile_trim( wxString& buffer )
buffer.Trim(true); // trims right side. buffer.Trim(true); // trims right side.
} }
#endif static int PatchTableExecute( wxString text1, wxString text2, const PatchTextTable * Table )
{
int i = 0;
while (Table[i].text[0])
{
if (!text1.Cmp(Table[i].text))
{
if (Table[i].func) Table[i].func(text1, text2);
break;
}
i++;
}
return Table[i].code;
}
// This routine is for executing the commands of the ini file.
void inifile_command( wxString cmd )
{
int code;
wxString command;
wxString parameter;
// extract param part (after '=')
wxString pEqual = cmd.AfterFirst(L'=');
if (pEqual.IsEmpty()) pEqual = cmd;
command = cmd.BeforeFirst(L'=');
parameter = pEqual;
inifile_trim( command );
inifile_trim( parameter );
code = PatchTableExecute( command, parameter, commands );
}
// 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( FILE * f1 ) void inifile_process(wxTextFile &f1 )
{ {
char buffer[ 1024 ]; Console.WriteLn("inifile_process");
while( fgets( buffer, sizeof( buffer ), f1 ) ) for (int i = 0; i < f1.GetLineCount(); i++)
{ {
inifile_trim( buffer ); inifile_trim(f1[i]);
if ( buffer[ 0 ] ) inifile_command( buffer ); if (!f1[i].IsEmpty()) inifile_command(f1[i]);
} }
} }
// This routine creates a pnach filename from the games crc, // This routine creates a pnach filename from the games crc,
// loads it, and passes it to inisection_process to be parsed. // loads it, trims the commands, and sends them to be parsed.
void inifile_read(wxString name ) void inifile_read(wxString name )
{ {
FILE* f1; wxTextFile f1;
wxCharBuffer buffer; wxString buffer;
patchnumber = 0; patchnumber = 0;
buffer = Path::Combine(L"patches", name + L".pnach").ToUTF8(); buffer = Path::Combine(L"patches", name + L".pnach");
f1 = fopen( buffer, "rt" );
#ifndef _WIN32 #ifndef _WIN32
if( !f1 ) if (!f1.Open(buffer))
{ {
name = name.MakeUpper(); name.MakeUpper();
buffer = Path::Combine(L"patches", name + L".pnach").ToUTF8(); buffer = Path::Combine(L"patches", name + L".pnach");
f1 = fopen(buffer, "rt");
} }
#endif #endif
if( !f1 ) if (!f1.Open(buffer))
{ {
Console.WriteLn("No patch found. Resuming execution without a patch (this is NOT an error)." ); Console.WriteLn("No patch found. Resuming execution without a patch (this is NOT an error)." );
return; return;
} }
else
{
Console.WriteLn("Opened!");
}
//inifile_process( f1 );
inifile_process( f1 ); inifile_process( f1 );
fclose( f1 ); f1.Close();
} }
void _ApplyPatch(IniPatch *p) void _ApplyPatch(IniPatch *p)
@ -610,99 +567,157 @@ int AddPatch(int Mode, int Place, int Address, int Size, u64 data)
return patchnumber++; return patchnumber++;
} }
void PrintPatch(int i)
{
Console.WriteLn("Patch[%d]:", i);
if (Patch[i].enabled == 0)
Console.WriteLn("Disabled.");
else
Console.WriteLn("Enabled.");
Console.WriteLn("PlaceToPatch:%d", Patch[i].placetopatch);
switch(Patch[i].cpu)
{
case CPU_EE: Console.WriteLn("Cpu: EE"); break;
case CPU_IOP: Console.WriteLn("Cpu: IOP"); break;
default: Console.WriteLn("Cpu: None"); break;
}
Console.WriteLn("Address: %X", Patch[i].addr);
switch (Patch[i].type)
{
case BYTE_T: Console.WriteLn("Type: Byte"); break;
case SHORT_T: Console.WriteLn("Type: Short"); break;
case WORD_T: Console.WriteLn("Type: Word"); break;
case DOUBLE_T: Console.WriteLn("Type: Double"); break;
case EXTENDED_T: Console.WriteLn("Type: Extended"); break;
default: Console.WriteLn("Type: None"); break;
}
Console.WriteLn("Data: %I64X", Patch[i].data);
}
u32 StrToU32(wxString str, int base = 10)
{
long l;
str.ToLong(&l, base);
return l;
}
u64 StrToU64(wxString str, int base = 10)
{
long long l;
str.ToLongLong(&l, base);
return l;
}
// PatchFunc Functions. // PatchFunc Functions.
namespace PatchFunc namespace PatchFunc
{ {
void comment( char* text1, char* text2 ) void comment( wxString text1, wxString text2 )
{ {
Console.WriteLn( "comment: %s", text2 ); Console.WriteLn( L"comment: " + text2 );
} }
void gametitle( char* text1, char* text2 ) void gametitle( wxString text1, wxString text2 )
{ {
Console.WriteLn( "gametitle: %s", text2 ); Console.WriteLn( L"gametitle: " + text2 );
strgametitle.FromAscii( text2 ); strgametitle = text2;
Console.SetTitle( strgametitle ); Console.SetTitle( strgametitle );
} }
void patch( char* cmd, char* param ) void patch( wxString cmd, wxString param )
{ {
char* pText; DevCon.WriteLn(cmd + L" " + param);
wxString pText;
if ( patchnumber >= MAX_PATCH ) if ( patchnumber >= MAX_PATCH )
{ {
// TODO : Use wxLogError for this, once we have full unicode compliance on cmd/params vars. // TODO : Use wxLogError for this, once we have full unicode compliance on cmd/params vars.
//wxLogError( L"Patch ERROR: Maximum number of patches reached: %s=%s", cmd, param ); //wxLogError( L"Patch ERROR: Maximum number of patches reached: %s=%s", cmd, param );
Console.Error( "Patch ERROR: Maximum number of patches reached: %s=%s", cmd, param ); Console.Error( L"Patch ERROR: Maximum number of patches reached: " + cmd +L"=" + param );
return; return;
} }
// I've just sort of hacked this in place for the moment.
// Using SafeList is probably better, but I'll leave that to Air...
//SafeList<wxString> pieces; //SafeList<wxString> pieces;
//SplitString( pieces, param, "," ); //SplitString( pieces, param, L"," );
pText = strtok( param, "," ); Patch[patchnumber].placetopatch = StrToU32(param.BeforeFirst(L','), 10);
pText = param; param = param.AfterFirst(L',');
pText = param.BeforeFirst(L',');
Patch[ patchnumber ].placetopatch = strtol( pText, (char **)NULL, 0 );
pText = strtok( NULL, "," );
inifile_trim( pText ); inifile_trim( pText );
Patch[ patchnumber ].cpu = (patch_cpu_type)PatchTableExecute( pText, NULL, cpuCore ); Patch[patchnumber].cpu = (patch_cpu_type)PatchTableExecute( pText, wxEmptyString, cpuCore );
if ( Patch[ patchnumber ].cpu == 0 ) if (Patch[patchnumber].cpu == 0)
{ {
Console.Error( "Unrecognized patch '%s'", pText ); Console.Error( L"Unrecognized patch '" + cmd + L"'" );
return; return;
} }
pText = strtok( NULL, "," ); param = param.AfterFirst(L',');
pText = param.BeforeFirst(L',');
inifile_trim( pText ); inifile_trim( pText );
sscanf( pText, "%X", &Patch[ patchnumber ].addr ); Patch[patchnumber].addr = StrToU32(pText, 16);
pText = strtok( NULL, "," ); param = param.AfterFirst(L',');
pText = param.BeforeFirst(L',');
inifile_trim( pText ); inifile_trim( pText );
Patch[ patchnumber ].type = (patch_data_type)PatchTableExecute( pText, NULL, dataType ); Patch[patchnumber].type = (patch_data_type)PatchTableExecute( pText, wxEmptyString, dataType );
if ( Patch[ patchnumber ].type == 0 ) if ( Patch[patchnumber].type == 0 )
{ {
Console.Error( "Unrecognized patch '%s'", pText ); Console.Error( L"Unrecognized patch '" + cmd + L"'" );
return; return;
} }
pText = strtok( NULL, "," ); param = param.AfterFirst(L',');
pText = param.BeforeFirst(L',');
inifile_trim( pText ); inifile_trim( pText );
sscanf( pText, "%I64X", &Patch[ patchnumber ].data );
Patch[ patchnumber ].enabled = 1; Patch[patchnumber].data = StrToU64(pText, 16);
Patch[patchnumber].enabled = 1;
//PrintPatch(patchnumber);
patchnumber++; patchnumber++;
} }
void roundmode( char* cmd, char* param ) void roundmode( wxString cmd, wxString param )
{ {
DevCon.WriteLn(cmd + L" " + param);
int index; int index;
char* pText; wxString pText;
SSE_RoundMode eetype = EmuConfig.Cpu.sseMXCSR.GetRoundMode(); SSE_RoundMode eetype = EmuConfig.Cpu.sseMXCSR.GetRoundMode();
SSE_RoundMode vutype = EmuConfig.Cpu.sseVUMXCSR.GetRoundMode(); SSE_RoundMode vutype = EmuConfig.Cpu.sseVUMXCSR.GetRoundMode();
index = 0; index = 0;
pText = strtok( param, ", " ); param.MakeLower();
while(pText != NULL) pText = param.BeforeFirst(L',');
while(pText != wxEmptyString)
{ {
SSE_RoundMode type; SSE_RoundMode type;
if( stricmp(pText, "near") == 0 ) if (pText.Contains(L"near"))
type = SSEround_Nearest; type = SSEround_Nearest;
else if( stricmp(pText, "down") == 0 ) else if (pText.Contains(L"down"))
type = SSEround_NegInf; type = SSEround_NegInf;
else if( stricmp(pText, "up") == 0 ) else if (pText.Contains(L"up"))
type = SSEround_PosInf; type = SSEround_PosInf;
else if( stricmp(pText, "chop") == 0 ) else if (pText.Contains(L"chop"))
type = SSEround_Chop; type = SSEround_Chop;
else else
{ {
Console.WriteLn("bad argument (%s) to round mode! skipping...\n", pText); Console.WriteLn(L"bad argument (" + pText + L") to round mode! skipping...\n");
break; break;
} }
@ -715,15 +730,37 @@ namespace PatchFunc
break; break;
index++; index++;
pText = strtok(NULL, ", "); pText = param.AfterFirst(L',');
} }
SetRoundMode(eetype,vutype); SetRoundMode(eetype,vutype);
} }
void zerogs(char* cmd, char* param) void zerogs(wxString cmd, wxString param)
{ {
sscanf(param, "%x", &g_ZeroGSOptions); DevCon.WriteLn( cmd + L" " + param);
g_ZeroGSOptions = StrToU32(param, 16);
}
}
void PrintRoundMode(SSE_RoundMode ee, SSE_RoundMode vu)
{
switch(ee)
{
case SSEround_Nearest: DevCon.WriteLn("EE: Near"); break;
case SSEround_NegInf: DevCon.WriteLn("EE: Down"); break;
case SSEround_PosInf: DevCon.WriteLn("EE: Up"); break;
case SSEround_Chop: DevCon.WriteLn("EE: Chop"); break;
default: DevCon.WriteLn("EE: ?"); break;
}
switch(vu)
{
case SSEround_Nearest: DevCon.WriteLn("VU: Near"); break;
case SSEround_NegInf: DevCon.WriteLn("VU: Down"); break;
case SSEround_PosInf: DevCon.WriteLn("VU: Up"); break;
case SSEround_Chop: DevCon.WriteLn("VU: Chop"); break;
default: DevCon.WriteLn("VU: ?"); break;
} }
} }
@ -732,5 +769,6 @@ void SetRoundMode(SSE_RoundMode ee, SSE_RoundMode vu)
SSE_MXCSR mxfpu = EmuConfig.Cpu.sseMXCSR; SSE_MXCSR mxfpu = EmuConfig.Cpu.sseMXCSR;
SSE_MXCSR mxvu = EmuConfig.Cpu.sseVUMXCSR; SSE_MXCSR mxvu = EmuConfig.Cpu.sseVUMXCSR;
//PrintRoundMode(ee,vu);
SetCPUState( mxfpu.SetRoundMode( ee ), mxvu.SetRoundMode( vu ) ); SetCPUState( mxfpu.SetRoundMode( ee ), mxvu.SetRoundMode( vu ) );
} }

View File

@ -34,7 +34,8 @@ enum patch_data_type {
EXTENDED_T EXTENDED_T
}; };
typedef void (*PATCHTABLEFUNC)( char * text1, char * text2 ); //typedef void (*PATCHTABLEFUNC)( char * text1, char * text2 );
typedef void (*PATCHTABLEFUNC)( wxString text1, wxString text2 );
struct IniPatch struct IniPatch
{ {
@ -49,16 +50,16 @@ struct IniPatch
namespace PatchFunc namespace PatchFunc
{ {
void comment( char* text1, char* text2 ); void comment( wxString text1, wxString text2 );
void gametitle( char* text1, char* text2 ); void gametitle( wxString text1, wxString text2 );
void patch( char* text1, char* text2 ); void patch( wxString text1, wxString text2 );
void roundmode( char* text1, char* text2 ); void roundmode( wxString text1, wxString text2 );
void zerogs( char* text1, char* text2 ); void zerogs( wxString text1, wxString text2 );
} }
void inifile_read( const char* name ); void inifile_read( wxString name );
void inifile_command( char* cmd ); void inifile_command( wxString cmd );
void inifile_trim( char* buffer ); void inifile_trim( wxString& buffer );
int AddPatch(int Mode, int Place, int Address, int Size, u64 data); int AddPatch(int Mode, int Place, int Address, int Size, u64 data);
void ApplyPatch( int place = 1); void ApplyPatch( int place = 1);