Cleanup patch.cpp...

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3032 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
cottonvibes 2010-05-17 05:18:11 +00:00
parent b6bc57b9e6
commit 5597a5e575
8 changed files with 566 additions and 558 deletions

View File

@ -15,7 +15,6 @@
#pragma once #pragma once
#include "File_Reader.h" #include "File_Reader.h"
#include "Patch.h"
struct key_pair { struct key_pair {
string key; string key;
@ -386,7 +385,7 @@ static void loadGameSettings(DataBase_Loader* gameDB) {
if (gameDB->keyExists("vuRoundMode")) { vuRM = gameDB->getInt("vuRoundMode"); rm=1; } if (gameDB->keyExists("vuRoundMode")) { vuRM = gameDB->getInt("vuRoundMode"); rm=1; }
if (rm && eeRM<4 && vuRM<4) { if (rm && eeRM<4 && vuRM<4) {
Console.WriteLn("Game DataBase: Changing roundmodes!"); Console.WriteLn("Game DataBase: Changing roundmodes!");
SetRoundMode((SSE_RoundMode)eeRM, (SSE_RoundMode)vuRM); SetCPUState(eeMX.SetRoundMode((SSE_RoundMode)eeRM), vuMX.SetRoundMode((SSE_RoundMode)vuRM));
} }
} }
} }

View File

@ -23,12 +23,10 @@
#include <wx/textfile.h> #include <wx/textfile.h>
IniPatch Patch[ MAX_PATCH ]; IniPatch Patch[ MAX_PATCH ];
IniPatch Cheat[ MAX_CHEAT ];
u32 SkipCount = 0, IterationCount = 0;
u32 IterationIncrement = 0, ValueIncrement = 0;
u32 PrevCheatType = 0, PrevCheatAddr = 0,LastType = 0;
int patchnumber; int patchnumber;
int cheatnumber;
wxString strgametitle; wxString strgametitle;
@ -39,17 +37,18 @@ struct PatchTextTable
PATCHTABLEFUNC* func; PATCHTABLEFUNC* func;
}; };
static const PatchTextTable commands[] = static const PatchTextTable commands_patch[] =
{ {
{ 1, L"comment", PatchFunc::comment }, { 1, L"comment", PatchFunc::comment },
{ 2, L"gametitle", PatchFunc::gametitle }, { 2, L"patch", PatchFunc::patch },
{ 3, L"patch", PatchFunc::patch }, { 0, wxEmptyString, NULL } // Array Terminator
{ 4, L"roundmode", PatchFunc::roundmode }, // changes rounding mode for floating point };
// syntax: roundmode=X,Y
// possible values for X,Y: NEAR, DOWN, UP, CHOP static const PatchTextTable commands_cheat[] =
// X - EE rounding mode (default is NEAR) {
// Y - VU rounding mode (default is CHOP) { 1, L"comment", PatchFunc::comment },
{ 0, wxEmptyString, NULL } // Array Terminator { 2, L"patch", PatchFunc::cheat },
{ 0, wxEmptyString, NULL } // Array Terminator
}; };
static const PatchTextTable dataType[] = static const PatchTextTable dataType[] =
@ -69,297 +68,6 @@ static const PatchTextTable cpuCore[] =
{ 0, wxEmptyString, NULL } { 0, wxEmptyString, NULL }
}; };
void writeCheat()
{
switch (LastType)
{
case 0x0:
memWrite8(PrevCheatAddr,IterationIncrement & 0xFF);
break;
case 0x1:
memWrite16(PrevCheatAddr,IterationIncrement & 0xFFFF);
break;
case 0x2:
memWrite32(PrevCheatAddr,IterationIncrement);
break;
default:
break;
}
}
void handle_extended_t( IniPatch *p)
{
if (SkipCount > 0)
{
SkipCount--;
}
else switch (PrevCheatType)
{
case 0x3040: // vvvvvvvv 00000000 Inc
{
u32 mem = memRead32(PrevCheatAddr);
memWrite32(PrevCheatAddr, mem + (p->addr));
PrevCheatType = 0;
break;
}
case 0x3050: // vvvvvvvv 00000000 Dec
{
u32 mem = memRead32(PrevCheatAddr);
memWrite32(PrevCheatAddr, mem - (p->addr));
PrevCheatType = 0;
break;
}
case 0x4000: // vvvvvvvv iiiiiiii
for(u32 i = 0; i < IterationCount; i++)
{
memWrite32((u32)(PrevCheatAddr + (i * IterationIncrement)),(u32)(p->addr + ((u32)p->data * i)));
}
PrevCheatType = 0;
break;
case 0x5000: // dddddddd iiiiiiii
for(u32 i = 0; i < IterationCount; i++)
{
u8 mem = memRead8(PrevCheatAddr + i);
memWrite8(((u32)p->data) + i, mem);
}
PrevCheatType = 0;
break;
case 0x6000: // 000Xnnnn iiiiiiii
if (IterationIncrement == 0x0)
{
//LastType = ((u32)p->addr & 0x000F0000) >> 16;
u32 mem = memRead32(PrevCheatAddr);
if ((u32)p->addr < 0x100)
{
LastType = 0x0;
PrevCheatAddr = mem + ((u32)p->addr);
}
else if ((u32)p->addr < 0x1000)
{
LastType = 0x1;
PrevCheatAddr = mem + ((u32)p->addr * 2);
}
else
{
LastType = 0x2;
PrevCheatAddr = mem + ((u32)p->addr * 4);
}
// Check if needed to read another pointer
PrevCheatType = 0;
if (((mem & 0x0FFFFFFF) & 0x3FFFFFFC) != 0)
{
switch(LastType)
{
case 0x0:
memWrite8(PrevCheatAddr,(u8)p->data & 0xFF);
break;
case 0x1:
memWrite16(PrevCheatAddr,(u16)p->data & 0x0FFFF);
break;
case 0x2:
memWrite32(PrevCheatAddr,(u32)p->data);
break;
default:
break;
}
}
}
else
{
// Get Number of pointers
if (((u32)p->addr & 0x0000FFFF) == 0)
IterationCount = 1;
else
IterationCount = (u32)p->addr & 0x0000FFFF;
// Read first pointer
LastType = ((u32)p->addr & 0x000F0000) >> 16;
u32 mem = memRead32(PrevCheatAddr);
PrevCheatAddr = mem + (u32)p->data;
IterationCount--;
// Check if needed to read another pointer
if (IterationCount == 0)
{
PrevCheatType = 0;
if (((mem & 0x0FFFFFFF) & 0x3FFFFFFC) != 0) writeCheat();
}
else
{
if (((mem & 0x0FFFFFFF) & 0x3FFFFFFC) != 0)
PrevCheatType = 0;
else
PrevCheatType = 0x6001;
}
}
break;
case 0x6001: // 000Xnnnn iiiiiiii
{
// Read first pointer
u32 mem = memRead32(PrevCheatAddr & 0x0FFFFFFF);
PrevCheatAddr = mem + (u32)p->addr;
IterationCount--;
// Check if needed to read another pointer
if (IterationCount == 0)
{
PrevCheatType = 0;
if (((mem & 0x0FFFFFFF) & 0x3FFFFFFC) != 0) writeCheat();
}
else
{
mem = memRead32(PrevCheatAddr);
PrevCheatAddr = mem + (u32)p->data;
IterationCount--;
if (IterationCount == 0)
{
PrevCheatType = 0;
if (((mem & 0x0FFFFFFF) & 0x3FFFFFFC) != 0) writeCheat();
}
}
}
break;
default:
if ((p->addr & 0xF0000000) == 0x00000000) // 0aaaaaaa 0000000vv
{
memWrite8(p->addr & 0x0FFFFFFF, (u8)p->data & 0x000000FF);
PrevCheatType = 0;
}
else if ((p->addr & 0xF0000000) == 0x10000000) // 0aaaaaaa 0000vvvv
{
memWrite16(p->addr & 0x0FFFFFFF, (u16)p->data & 0x0000FFFF);
PrevCheatType = 0;
}
else if ((p->addr & 0xF0000000) == 0x20000000) // 0aaaaaaa vvvvvvvv
{
memWrite32(p->addr & 0x0FFFFFFF, (u32)p->data);
PrevCheatType = 0;
}
else if ((p->addr & 0xFFFF0000) == 0x30000000) // 300000vv 0aaaaaaa Inc
{
u8 mem = memRead8((u32)p->data);
memWrite8((u32)p->data, mem + (p->addr & 0x000000FF));
PrevCheatType = 0;
}
else if ((p->addr & 0xFFFF0000) == 0x30100000) // 301000vv 0aaaaaaa Dec
{
u8 mem = memRead8((u32)p->data);
memWrite8((u32)p->data, mem - (p->addr & 0x000000FF));
PrevCheatType = 0;
}
else if ((p->addr & 0xFFFF0000) == 0x30200000) // 3020vvvv 0aaaaaaa Inc
{
u16 mem = memRead16((u32)p->data);
memWrite16((u32)p->data, mem + (p->addr & 0x0000FFFF));
PrevCheatType = 0;
}
else if ((p->addr & 0xFFFF0000) == 0x30300000) // 3030vvvv 0aaaaaaa Dec
{
u16 mem = memRead16((u32)p->data);
memWrite16((u32)p->data, mem - (p->addr & 0x0000FFFF));
PrevCheatType = 0;
}
else if ((p->addr & 0xFFFF0000) == 0x30400000) // 30400000 0aaaaaaa Inc + Another line
{
PrevCheatType = 0x3040;
PrevCheatAddr = (u32)p->data;
}
else if ((p->addr & 0xFFFF0000) == 0x30500000) // 30500000 0aaaaaaa Inc + Another line
{
PrevCheatType = 0x3050;
PrevCheatAddr = (u32)p->data;
}
else if ((p->addr & 0xF0000000) == 0x40000000) // 4aaaaaaa nnnnssss + Another line
{
IterationCount = ((u32)p->data & 0xFFFF0000) / 0x10000;
IterationIncrement = ((u32)p->data & 0x0000FFFF) * 4;
PrevCheatAddr = (u32)p->addr & 0x0FFFFFFF;
PrevCheatType = 0x4000;
}
else if ((p->addr & 0xF0000000) == 0x50000000) // 5sssssss nnnnnnnn + Another line
{
PrevCheatAddr = (u32)p->addr & 0x0FFFFFFF;
IterationCount = ((u32)p->data);
PrevCheatType = 0x5000;
}
else if ((p->addr & 0xF0000000) == 0x60000000) // 6aaaaaaa 000000vv + Another line/s
{
PrevCheatAddr = (u32)p->addr & 0x0FFFFFFF;
IterationIncrement = ((u32)p->data);
IterationCount = 0;
PrevCheatType = 0x6000;
}
else if ((p->addr & 0xF0000000) == 0x70000000)
{
if ((p->data & 0x00F00000) == 0x00000000) // 7aaaaaaa 000000vv
{
u8 mem = memRead8((u32)p->addr & 0x0FFFFFFF);
memWrite8((u32)p->addr & 0x0FFFFFFF,(u8)(mem | (p->data & 0x000000FF)));
}
else if ((p->data & 0x00F00000) == 0x00100000) // 7aaaaaaa 0010vvvv
{
u16 mem = memRead16((u32)p->addr & 0x0FFFFFFF);
memWrite16((u32)p->addr & 0x0FFFFFFF,(u16)(mem | (p->data & 0x0000FFFF)));
}
else if ((p->data & 0x00F00000) == 0x00200000) // 7aaaaaaa 002000vv
{
u8 mem = memRead8((u32)p->addr&0x0FFFFFFF);
memWrite8((u32)p->addr & 0x0FFFFFFF,(u8)(mem & (p->data & 0x000000FF)));
}
else if ((p->data & 0x00F00000) == 0x00300000) // 7aaaaaaa 0030vvvv
{
u16 mem = memRead16((u32)p->addr & 0x0FFFFFFF);
memWrite16((u32)p->addr & 0x0FFFFFFF,(u16)(mem & (p->data & 0x0000FFFF)));
}
else if ((p->data & 0x00F00000) == 0x00400000) // 7aaaaaaa 004000vv
{
u8 mem = memRead8((u32)p->addr & 0x0FFFFFFF);
memWrite8((u32)p->addr & 0x0FFFFFFF,(u8)(mem ^ (p->data & 0x000000FF)));
}
else if ((p->data & 0x00F00000) == 0x00500000) // 7aaaaaaa 0050vvvv
{
u16 mem = memRead16((u32)p->addr & 0x0FFFFFFF);
memWrite16((u32)p->addr & 0x0FFFFFFF,(u16)(mem ^ (p->data & 0x0000FFFF)));
}
}
else if (p->addr < 0xE0000000)
{
if ((((u32)p->data & 0xFFFF0000) == 0x00000000) ||
(((u32)p->data & 0xFFFF0000) == 0x00100000) ||
(((u32)p->data & 0xFFFF0000) == 0x00200000) ||
(((u32)p->data & 0xFFFF0000) == 0x00300000))
{
u16 mem = memRead16((u32)p->addr & 0x0FFFFFFF);
if (mem != (0x0000FFFF & (u32)p->data)) SkipCount = 1;
PrevCheatType = 0;
}
}
else if (p->addr < 0xF0000000)
{
if (((u32)p->data & 0xC0000000) == 0x00000000)
if ((((u32)p->data & 0xF0000000) == 0x00000000) ||
(((u32)p->data & 0xF0000000) == 0x10000000) ||
(((u32)p->data & 0xF0000000) == 0x20000000) ||
(((u32)p->data & 0xF0000000) == 0x30000000))
{
u16 mem = memRead16((u32)p->data & 0x0FFFFFFF);
if (mem != (0x0000FFFF & (u32)p->addr)) SkipCount = ((u32)p->addr & 0xFFF0000) / 0x10000;
PrevCheatType = 0;
}
}
}
}
// IniFile Functions. // IniFile Functions.
void inifile_trim( wxString& buffer ) void inifile_trim( wxString& buffer )
@ -399,7 +107,7 @@ static int PatchTableExecute( const ParsedAssignmentString& set, const PatchText
} }
// This routine is for executing the commands of the ini file. // This routine is for executing the commands of the ini file.
void inifile_command( const wxString& cmd ) void inifile_command(bool isCheat, const wxString& cmd)
{ {
ParsedAssignmentString set( cmd ); ParsedAssignmentString set( cmd );
@ -407,7 +115,7 @@ void inifile_command( const wxString& cmd )
// would make more sense... --air // would make more sense... --air
if (set.rvalue.IsEmpty()) set.rvalue = set.lvalue; if (set.rvalue.IsEmpty()) set.rvalue = set.lvalue;
int code = PatchTableExecute( set, commands ); int code = PatchTableExecute(set, isCheat ? commands_cheat : commands_patch);
} }
// This routine receives a string containing patches, trims it, // This routine receives a string containing patches, trims it,
@ -419,7 +127,7 @@ void TrimPatches(string& s)
while (!ss.finished()) { while (!ss.finished()) {
buff = ss.getLineWX(); buff = ss.getLineWX();
inifile_trim(buff); inifile_trim(buff);
if (!buff.IsEmpty()) inifile_command(buff); if (!buff.IsEmpty()) inifile_command(0, buff);
} }
} }
@ -460,7 +168,7 @@ void inifile_process(wxTextFile &f1 )
for (uint i = 0; i < f1.GetLineCount(); i++) for (uint i = 0; i < f1.GetLineCount(); i++)
{ {
inifile_trim(f1[i]); inifile_trim(f1[i]);
if (!f1[i].IsEmpty()) inifile_command(f1[i]); if (!f1[i].IsEmpty()) inifile_command(1, f1[i]);
} }
} }
@ -471,7 +179,7 @@ int InitCheats(const wxString& name)
{ {
wxTextFile f1; wxTextFile f1;
wxString buffer; wxString buffer;
int cheatsNumber = patchnumber; cheatnumber = 0;
// FIXME : We need to add a 'cheats' folder to the AppConfig, and use that instead. --air // FIXME : We need to add a 'cheats' folder to the AppConfig, and use that instead. --air
@ -491,138 +199,8 @@ int InitCheats(const wxString& name)
Console.WriteLn( Color_Green, "Cheats found!"); Console.WriteLn( Color_Green, "Cheats found!");
inifile_process( f1 ); inifile_process( f1 );
cheatsNumber = patchnumber - cheatsNumber; Console.WriteLn("Cheats Loaded: %d", cheatnumber);
Console.WriteLn("Cheats Loaded: %d", cheatsNumber); return cheatnumber;
return cheatsNumber;
}
void _ApplyPatch(IniPatch *p)
{
if (p->enabled == 0) return;
switch (p->cpu)
{
case CPU_EE:
switch (p->type)
{
case BYTE_T:
if (memRead8(p->addr) != (u8)p->data)
memWrite8(p->addr, (u8)p->data);
break;
case SHORT_T:
if (memRead16(p->addr) != (u16)p->data)
memWrite16(p->addr, (u16)p->data);
break;
case WORD_T:
if (memRead32(p->addr) != (u32)p->data)
memWrite32(p->addr, (u32)p->data);
break;
case DOUBLE_T:
u64 mem;
memRead64(p->addr, &mem);
if (mem != p->data)
memWrite64(p->addr, &p->data);
break;
case EXTENDED_T:
handle_extended_t(p);
break;
default:
break;
}
break;
case CPU_IOP:
switch (p->type)
{
case BYTE_T:
if (iopMemRead8(p->addr) != (u8)p->data)
iopMemWrite8(p->addr, (u8)p->data);
break;
case SHORT_T:
if (iopMemRead16(p->addr) != (u16)p->data)
iopMemWrite16(p->addr, (u16)p->data);
break;
case WORD_T:
if (iopMemRead32(p->addr) != (u32)p->data)
iopMemWrite32(p->addr, (u32)p->data);
break;
default:
break;
}
break;
default:
break;
}
}
//this is for applying patches directly to memory
void ApplyPatch(int place)
{
for (int i = 0; i < patchnumber; i++)
{
if (Patch[i].placetopatch == place)
_ApplyPatch(&Patch[i]);
}
}
void ResetPatch( void )
{
patchnumber = 0;
}
int AddPatch(int Mode, int Place, int Address, int Size, u64 data)
{
if ( patchnumber >= MAX_PATCH )
{
Console.Error( "Patch ERROR: Maximum number of patches reached.");
return -1;
}
Patch[patchnumber].placetopatch = Mode;
Patch[patchnumber].cpu = (patch_cpu_type)Place;
Patch[patchnumber].addr = Address;
Patch[patchnumber].type = (patch_data_type)Size;
Patch[patchnumber].data = data;
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);
} }
static u32 StrToU32(const wxString& str, int base = 10) static u32 StrToU32(const wxString& str, int base = 10)
@ -647,15 +225,6 @@ namespace PatchFunc
Console.WriteLn( L"comment: " + text2 ); Console.WriteLn( L"comment: " + text2 );
} }
void gametitle( const wxString& text1, const wxString& text2 )
{
// Setting Game Title through patches is obsolete now
// Use database instead!
//Console.WriteLn( L"gametitle: " + text2 );
//strgametitle = text2;
//Console.SetTitle( strgametitle );
}
struct PatchPieces struct PatchPieces
{ {
wxArrayString m_pieces; wxArrayString m_pieces;
@ -674,8 +243,8 @@ namespace PatchFunc
const wxString& WriteValue() const { return m_pieces[4]; } const wxString& WriteValue() const { return m_pieces[4]; }
}; };
void patch( const wxString& cmd, const wxString& param ) template<bool isCheat>
{ void patchHelper(const wxString& cmd, const wxString& param) {
// Error Handling Note: I just throw simple wxStrings here, and then catch them below and // Error Handling Note: I just throw simple wxStrings here, and then catch them below and
// format them into more detailed cmd+data+error printouts. If we want to add user-friendly // format them into more detailed cmd+data+error printouts. If we want to add user-friendly
// (translated) messages for display in a popup window then we'll have to upgrade the // (translated) messages for display in a popup window then we'll have to upgrade the
@ -685,108 +254,59 @@ namespace PatchFunc
try try
{ {
if ( patchnumber >= MAX_PATCH ) if (isCheat && cheatnumber >= MAX_CHEAT)
throw wxString( L"Maximum number of cheats reached" );
if(!isCheat && patchnumber >= MAX_PATCH)
throw wxString( L"Maximum number of patches reached" ); throw wxString( L"Maximum number of patches reached" );
Patch[patchnumber].enabled = 0; IniPatch& iPatch = isCheat ? Cheat[cheatnumber] : Patch[patchnumber];
PatchPieces pieces( param ); PatchPieces pieces(param);
Patch[patchnumber].placetopatch = StrToU32(pieces.PlaceToPatch(), 10); iPatch.enabled = 0;
Patch[patchnumber].cpu = (patch_cpu_type)PatchTableExecute( pieces.CpuType(), cpuCore );
Patch[patchnumber].addr = StrToU32(pieces.MemAddr(), 16);
Patch[patchnumber].type = (patch_data_type)PatchTableExecute( pieces.OperandSize(), dataType );
Patch[patchnumber].data = StrToU64( pieces.WriteValue(), 16 );
if (Patch[patchnumber].cpu == 0) iPatch.placetopatch = StrToU32(pieces.PlaceToPatch(), 10);
throw wxsFormat( L"Unrecognized CPU Target: '%s'", pieces.CpuType().c_str() ); iPatch.cpu = (patch_cpu_type)PatchTableExecute(pieces.CpuType(), cpuCore);
iPatch.addr = StrToU32(pieces.MemAddr(), 16);
iPatch.type = (patch_data_type)PatchTableExecute(pieces.OperandSize(), dataType);
iPatch.data = StrToU64(pieces.WriteValue(), 16);
if (Patch[patchnumber].type == 0) if (iPatch.cpu == 0)
throw wxsFormat( L"Unrecognized Operand Size: '%s'", pieces.OperandSize().c_str() ); throw wxsFormat(L"Unrecognized CPU Target: '%s'", pieces.CpuType().c_str());
Patch[patchnumber].enabled = 1; // omg success!! if (iPatch.type == 0)
throw wxsFormat(L"Unrecognized Operand Size: '%s'", pieces.OperandSize().c_str());
//PrintPatch(patchnumber); iPatch.enabled = 1; // omg success!!
patchnumber++;
if (isCheat) cheatnumber++;
else patchnumber++;
} }
catch( wxString& exmsg ) catch( wxString& exmsg )
{ {
Console.Error( L"(Patch) Error Parsing: %s=%s", cmd.c_str(), param.c_str() ); Console.Error(L"(Patch) Error Parsing: %s=%s", cmd.c_str(), param.c_str());
Console.Indent().Error( exmsg ); Console.Indent().Error( exmsg );
} }
} }
void patch(const wxString& cmd, const wxString& param) { patchHelper<0>(cmd, param); }
void roundmode( const wxString& cmd, const wxString& param ) void cheat(const wxString& cmd, const wxString& param) { patchHelper<1>(cmd, param); }
{
DevCon.WriteLn(cmd + L" " + param);
int index;
wxString pText;
SSE_RoundMode eetype = EmuConfig.Cpu.sseMXCSR.GetRoundMode();
SSE_RoundMode vutype = EmuConfig.Cpu.sseVUMXCSR.GetRoundMode();
index = 0;
pText = param.Lower().BeforeFirst(L',');
while(pText != wxEmptyString)
{
SSE_RoundMode type;
if (pText.Contains(L"near"))
type = SSEround_Nearest;
else if (pText.Contains(L"down"))
type = SSEround_NegInf;
else if (pText.Contains(L"up"))
type = SSEround_PosInf;
else if (pText.Contains(L"chop"))
type = SSEround_Chop;
else
{
Console.WriteLn(L"bad argument (" + pText + L") to round mode! skipping...\n");
break;
}
if( index == 0 )
eetype = type;
else
vutype = type;
if( index == 1 )
break;
index++;
pText = param.AfterFirst(L',');
}
SetRoundMode(eetype,vutype);
}
} }
void PrintRoundMode(SSE_RoundMode ee, SSE_RoundMode vu) // This is for applying patches directly to memory
void ApplyPatch(int place)
{ {
switch(ee) for (int i = 0; i < patchnumber; i++)
{ {
case SSEround_Nearest: DevCon.WriteLn("EE: Near"); break; if (Patch[i].placetopatch == place)
case SSEround_NegInf: DevCon.WriteLn("EE: Down"); break; _ApplyPatch(&Patch[i]);
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;
}
} }
void SetRoundMode(SSE_RoundMode ee, SSE_RoundMode vu) // This is for applying cheats directly to memory
void ApplyCheat(int place)
{ {
SSE_MXCSR mxfpu = EmuConfig.Cpu.sseMXCSR; for (int i = 0; i < cheatnumber; i++)
SSE_MXCSR mxvu = EmuConfig.Cpu.sseVUMXCSR; {
if (Cheat[i].placetopatch == place)
//PrintRoundMode(ee,vu); _ApplyPatch(&Cheat[i]);
SetCPUState( mxfpu.SetRoundMode( ee ), mxvu.SetRoundMode( vu ) ); }
} }

View File

@ -17,7 +17,8 @@
#include "Pcsx2Defs.h" #include "Pcsx2Defs.h"
#define MAX_PATCH 1024 #define MAX_PATCH 512
#define MAX_CHEAT 1024
enum patch_cpu_type { enum patch_cpu_type {
NO_CPU, NO_CPU,
@ -50,21 +51,21 @@ struct IniPatch
namespace PatchFunc namespace PatchFunc
{ {
PATCHTABLEFUNC comment; PATCHTABLEFUNC comment;
PATCHTABLEFUNC gametitle; PATCHTABLEFUNC gametitle;
PATCHTABLEFUNC patch; PATCHTABLEFUNC patch;
PATCHTABLEFUNC roundmode; PATCHTABLEFUNC cheat;
} }
int InitCheats(const wxString& name); int InitCheats(const wxString& name);
void inifile_command(const wxString& cmd); void inifile_command(bool isCheat, const wxString& cmd);
void inifile_trim(wxString& buffer); void inifile_trim(wxString& buffer);
int InitPatches(const wxString& name); int InitPatches(const wxString& name);
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 ResetPatch(void);
void ResetPatch( void ); void ApplyPatch(int place = 1);
void ApplyCheat(int place = 1);
void SetRoundMode(SSE_RoundMode ee, SSE_RoundMode vu); void _ApplyPatch(IniPatch *p);
#endif /* __PATCH_H__ */ #endif /* __PATCH_H__ */

381
pcsx2/Patch_Memory.cpp Normal file
View File

@ -0,0 +1,381 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#define _PC_ // disables MIPS opcode macros.
#include "IopCommon.h"
#include "Patch.h"
u32 SkipCount = 0, IterationCount = 0;
u32 IterationIncrement = 0, ValueIncrement = 0;
u32 PrevCheatType = 0, PrevCheatAddr = 0,LastType = 0;
void writeCheat()
{
switch (LastType)
{
case 0x0:
memWrite8(PrevCheatAddr,IterationIncrement & 0xFF);
break;
case 0x1:
memWrite16(PrevCheatAddr,IterationIncrement & 0xFFFF);
break;
case 0x2:
memWrite32(PrevCheatAddr,IterationIncrement);
break;
default:
break;
}
}
void handle_extended_t( IniPatch *p)
{
if (SkipCount > 0)
{
SkipCount--;
}
else switch (PrevCheatType)
{
case 0x3040: // vvvvvvvv 00000000 Inc
{
u32 mem = memRead32(PrevCheatAddr);
memWrite32(PrevCheatAddr, mem + (p->addr));
PrevCheatType = 0;
break;
}
case 0x3050: // vvvvvvvv 00000000 Dec
{
u32 mem = memRead32(PrevCheatAddr);
memWrite32(PrevCheatAddr, mem - (p->addr));
PrevCheatType = 0;
break;
}
case 0x4000: // vvvvvvvv iiiiiiii
for(u32 i = 0; i < IterationCount; i++)
{
memWrite32((u32)(PrevCheatAddr + (i * IterationIncrement)),(u32)(p->addr + ((u32)p->data * i)));
}
PrevCheatType = 0;
break;
case 0x5000: // dddddddd iiiiiiii
for(u32 i = 0; i < IterationCount; i++)
{
u8 mem = memRead8(PrevCheatAddr + i);
memWrite8(((u32)p->data) + i, mem);
}
PrevCheatType = 0;
break;
case 0x6000: // 000Xnnnn iiiiiiii
if (IterationIncrement == 0x0)
{
//LastType = ((u32)p->addr & 0x000F0000) >> 16;
u32 mem = memRead32(PrevCheatAddr);
if ((u32)p->addr < 0x100)
{
LastType = 0x0;
PrevCheatAddr = mem + ((u32)p->addr);
}
else if ((u32)p->addr < 0x1000)
{
LastType = 0x1;
PrevCheatAddr = mem + ((u32)p->addr * 2);
}
else
{
LastType = 0x2;
PrevCheatAddr = mem + ((u32)p->addr * 4);
}
// Check if needed to read another pointer
PrevCheatType = 0;
if (((mem & 0x0FFFFFFF) & 0x3FFFFFFC) != 0)
{
switch(LastType)
{
case 0x0:
memWrite8(PrevCheatAddr,(u8)p->data & 0xFF);
break;
case 0x1:
memWrite16(PrevCheatAddr,(u16)p->data & 0x0FFFF);
break;
case 0x2:
memWrite32(PrevCheatAddr,(u32)p->data);
break;
default:
break;
}
}
}
else
{
// Get Number of pointers
if (((u32)p->addr & 0x0000FFFF) == 0)
IterationCount = 1;
else
IterationCount = (u32)p->addr & 0x0000FFFF;
// Read first pointer
LastType = ((u32)p->addr & 0x000F0000) >> 16;
u32 mem = memRead32(PrevCheatAddr);
PrevCheatAddr = mem + (u32)p->data;
IterationCount--;
// Check if needed to read another pointer
if (IterationCount == 0)
{
PrevCheatType = 0;
if (((mem & 0x0FFFFFFF) & 0x3FFFFFFC) != 0) writeCheat();
}
else
{
if (((mem & 0x0FFFFFFF) & 0x3FFFFFFC) != 0)
PrevCheatType = 0;
else
PrevCheatType = 0x6001;
}
}
break;
case 0x6001: // 000Xnnnn iiiiiiii
{
// Read first pointer
u32 mem = memRead32(PrevCheatAddr & 0x0FFFFFFF);
PrevCheatAddr = mem + (u32)p->addr;
IterationCount--;
// Check if needed to read another pointer
if (IterationCount == 0)
{
PrevCheatType = 0;
if (((mem & 0x0FFFFFFF) & 0x3FFFFFFC) != 0) writeCheat();
}
else
{
mem = memRead32(PrevCheatAddr);
PrevCheatAddr = mem + (u32)p->data;
IterationCount--;
if (IterationCount == 0)
{
PrevCheatType = 0;
if (((mem & 0x0FFFFFFF) & 0x3FFFFFFC) != 0) writeCheat();
}
}
}
break;
default:
if ((p->addr & 0xF0000000) == 0x00000000) // 0aaaaaaa 0000000vv
{
memWrite8(p->addr & 0x0FFFFFFF, (u8)p->data & 0x000000FF);
PrevCheatType = 0;
}
else if ((p->addr & 0xF0000000) == 0x10000000) // 0aaaaaaa 0000vvvv
{
memWrite16(p->addr & 0x0FFFFFFF, (u16)p->data & 0x0000FFFF);
PrevCheatType = 0;
}
else if ((p->addr & 0xF0000000) == 0x20000000) // 0aaaaaaa vvvvvvvv
{
memWrite32(p->addr & 0x0FFFFFFF, (u32)p->data);
PrevCheatType = 0;
}
else if ((p->addr & 0xFFFF0000) == 0x30000000) // 300000vv 0aaaaaaa Inc
{
u8 mem = memRead8((u32)p->data);
memWrite8((u32)p->data, mem + (p->addr & 0x000000FF));
PrevCheatType = 0;
}
else if ((p->addr & 0xFFFF0000) == 0x30100000) // 301000vv 0aaaaaaa Dec
{
u8 mem = memRead8((u32)p->data);
memWrite8((u32)p->data, mem - (p->addr & 0x000000FF));
PrevCheatType = 0;
}
else if ((p->addr & 0xFFFF0000) == 0x30200000) // 3020vvvv 0aaaaaaa Inc
{
u16 mem = memRead16((u32)p->data);
memWrite16((u32)p->data, mem + (p->addr & 0x0000FFFF));
PrevCheatType = 0;
}
else if ((p->addr & 0xFFFF0000) == 0x30300000) // 3030vvvv 0aaaaaaa Dec
{
u16 mem = memRead16((u32)p->data);
memWrite16((u32)p->data, mem - (p->addr & 0x0000FFFF));
PrevCheatType = 0;
}
else if ((p->addr & 0xFFFF0000) == 0x30400000) // 30400000 0aaaaaaa Inc + Another line
{
PrevCheatType = 0x3040;
PrevCheatAddr = (u32)p->data;
}
else if ((p->addr & 0xFFFF0000) == 0x30500000) // 30500000 0aaaaaaa Inc + Another line
{
PrevCheatType = 0x3050;
PrevCheatAddr = (u32)p->data;
}
else if ((p->addr & 0xF0000000) == 0x40000000) // 4aaaaaaa nnnnssss + Another line
{
IterationCount = ((u32)p->data & 0xFFFF0000) / 0x10000;
IterationIncrement = ((u32)p->data & 0x0000FFFF) * 4;
PrevCheatAddr = (u32)p->addr & 0x0FFFFFFF;
PrevCheatType = 0x4000;
}
else if ((p->addr & 0xF0000000) == 0x50000000) // 5sssssss nnnnnnnn + Another line
{
PrevCheatAddr = (u32)p->addr & 0x0FFFFFFF;
IterationCount = ((u32)p->data);
PrevCheatType = 0x5000;
}
else if ((p->addr & 0xF0000000) == 0x60000000) // 6aaaaaaa 000000vv + Another line/s
{
PrevCheatAddr = (u32)p->addr & 0x0FFFFFFF;
IterationIncrement = ((u32)p->data);
IterationCount = 0;
PrevCheatType = 0x6000;
}
else if ((p->addr & 0xF0000000) == 0x70000000)
{
if ((p->data & 0x00F00000) == 0x00000000) // 7aaaaaaa 000000vv
{
u8 mem = memRead8((u32)p->addr & 0x0FFFFFFF);
memWrite8((u32)p->addr & 0x0FFFFFFF,(u8)(mem | (p->data & 0x000000FF)));
}
else if ((p->data & 0x00F00000) == 0x00100000) // 7aaaaaaa 0010vvvv
{
u16 mem = memRead16((u32)p->addr & 0x0FFFFFFF);
memWrite16((u32)p->addr & 0x0FFFFFFF,(u16)(mem | (p->data & 0x0000FFFF)));
}
else if ((p->data & 0x00F00000) == 0x00200000) // 7aaaaaaa 002000vv
{
u8 mem = memRead8((u32)p->addr&0x0FFFFFFF);
memWrite8((u32)p->addr & 0x0FFFFFFF,(u8)(mem & (p->data & 0x000000FF)));
}
else if ((p->data & 0x00F00000) == 0x00300000) // 7aaaaaaa 0030vvvv
{
u16 mem = memRead16((u32)p->addr & 0x0FFFFFFF);
memWrite16((u32)p->addr & 0x0FFFFFFF,(u16)(mem & (p->data & 0x0000FFFF)));
}
else if ((p->data & 0x00F00000) == 0x00400000) // 7aaaaaaa 004000vv
{
u8 mem = memRead8((u32)p->addr & 0x0FFFFFFF);
memWrite8((u32)p->addr & 0x0FFFFFFF,(u8)(mem ^ (p->data & 0x000000FF)));
}
else if ((p->data & 0x00F00000) == 0x00500000) // 7aaaaaaa 0050vvvv
{
u16 mem = memRead16((u32)p->addr & 0x0FFFFFFF);
memWrite16((u32)p->addr & 0x0FFFFFFF,(u16)(mem ^ (p->data & 0x0000FFFF)));
}
}
else if (p->addr < 0xE0000000)
{
if ((((u32)p->data & 0xFFFF0000) == 0x00000000) ||
(((u32)p->data & 0xFFFF0000) == 0x00100000) ||
(((u32)p->data & 0xFFFF0000) == 0x00200000) ||
(((u32)p->data & 0xFFFF0000) == 0x00300000))
{
u16 mem = memRead16((u32)p->addr & 0x0FFFFFFF);
if (mem != (0x0000FFFF & (u32)p->data)) SkipCount = 1;
PrevCheatType = 0;
}
}
else if (p->addr < 0xF0000000)
{
if (((u32)p->data & 0xC0000000) == 0x00000000)
if ((((u32)p->data & 0xF0000000) == 0x00000000) ||
(((u32)p->data & 0xF0000000) == 0x10000000) ||
(((u32)p->data & 0xF0000000) == 0x20000000) ||
(((u32)p->data & 0xF0000000) == 0x30000000))
{
u16 mem = memRead16((u32)p->data & 0x0FFFFFFF);
if (mem != (0x0000FFFF & (u32)p->addr)) SkipCount = ((u32)p->addr & 0xFFF0000) / 0x10000;
PrevCheatType = 0;
}
}
}
}
void _ApplyPatch(IniPatch *p)
{
if (p->enabled == 0) return;
switch (p->cpu)
{
case CPU_EE:
switch (p->type)
{
case BYTE_T:
if (memRead8(p->addr) != (u8)p->data)
memWrite8(p->addr, (u8)p->data);
break;
case SHORT_T:
if (memRead16(p->addr) != (u16)p->data)
memWrite16(p->addr, (u16)p->data);
break;
case WORD_T:
if (memRead32(p->addr) != (u32)p->data)
memWrite32(p->addr, (u32)p->data);
break;
case DOUBLE_T:
u64 mem;
memRead64(p->addr, &mem);
if (mem != p->data)
memWrite64(p->addr, &p->data);
break;
case EXTENDED_T:
handle_extended_t(p);
break;
default:
break;
}
break;
case CPU_IOP:
switch (p->type)
{
case BYTE_T:
if (iopMemRead8(p->addr) != (u8)p->data)
iopMemWrite8(p->addr, (u8)p->data);
break;
case SHORT_T:
if (iopMemRead16(p->addr) != (u16)p->data)
iopMemWrite16(p->addr, (u16)p->data);
break;
case WORD_T:
if (iopMemRead32(p->addr) != (u32)p->data)
iopMemWrite32(p->addr, (u32)p->data);
break;
default:
break;
}
break;
default:
break;
}
}

93
pcsx2/Patch_Obsolete.h Normal file
View File

@ -0,0 +1,93 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
// Old Patching functions that are currently not used
// so out-sourced them to this header file that isn't referenced...
// Obsolete code used by old cheats-gui code...
int AddPatch(int Mode, int Place, int Address, int Size, u64 data)
{
if ( patchnumber >= MAX_PATCH )
{
Console.Error( "Patch ERROR: Maximum number of patches reached.");
return -1;
}
Patch[patchnumber].placetopatch = Mode;
Patch[patchnumber].cpu = (patch_cpu_type)Place;
Patch[patchnumber].addr = Address;
Patch[patchnumber].type = (patch_data_type)Size;
Patch[patchnumber].data = data;
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);
}
void ResetPatch( void )
{
patchnumber = 0;
}
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;
}
}

View File

@ -616,6 +616,7 @@ void __fastcall eeGameStarting()
} }
ApplyPatch(0); ApplyPatch(0);
ApplyCheat(0);
} }
void __fastcall eeloadReplaceOSDSYS() void __fastcall eeloadReplaceOSDSYS()

View File

@ -199,6 +199,7 @@ void SysCoreThread::VsyncInThread()
{ {
PostVsyncToUI(); PostVsyncToUI();
if (EmuConfig.EnablePatches) ApplyPatch(); if (EmuConfig.EnablePatches) ApplyPatch();
if (EmuConfig.EnablePatches) ApplyCheat(); // ToDo: EnableCheats Option...
} }
void SysCoreThread::StateCheckInThread() void SysCoreThread::StateCheckInThread()

View File

@ -260,14 +260,6 @@
RelativePath="..\..\Utilities\folderdesc.txt" RelativePath="..\..\Utilities\folderdesc.txt"
> >
</File> </File>
<File
RelativePath="..\..\Patch.cpp"
>
</File>
<File
RelativePath="..\..\Patch.h"
>
</File>
<File <File
RelativePath="..\..\PrecompiledHeader.cpp" RelativePath="..\..\PrecompiledHeader.cpp"
> >
@ -332,6 +324,26 @@
> >
</File> </File>
</Filter> </Filter>
<Filter
Name="Patch"
>
<File
RelativePath="..\..\Patch.cpp"
>
</File>
<File
RelativePath="..\..\Patch.h"
>
</File>
<File
RelativePath="..\..\Patch_Memory.cpp"
>
</File>
<File
RelativePath="..\..\Patch_Obsolete.h"
>
</File>
</Filter>
</Filter> </Filter>
<Filter <Filter
Name="Docs" Name="Docs"