Some progress, I think?

Program crashes when trying to run a game. If you comment out
member.Run(); it will run fine, but cwcheat doesnt work.
This commit is contained in:
Steven Cherry 2013-05-17 23:49:44 -05:00
parent 253493c5ce
commit 446d2930ac
5 changed files with 497 additions and 469 deletions

View File

@ -109,6 +109,7 @@
<FloatingPointModel>Fast</FloatingPointModel> <FloatingPointModel>Fast</FloatingPointModel>
<PreprocessorDefinitions>USE_FFMPEG;_MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions> <PreprocessorDefinitions>USE_FFMPEG;_MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -157,6 +158,7 @@
<ClCompile Include="Core.cpp" /> <ClCompile Include="Core.cpp" />
<ClCompile Include="CoreTiming.cpp" /> <ClCompile Include="CoreTiming.cpp" />
<ClCompile Include="CPU.cpp" /> <ClCompile Include="CPU.cpp" />
<ClCompile Include="Cwcheat.cpp" />
<ClCompile Include="Debugger\Breakpoints.cpp" /> <ClCompile Include="Debugger\Breakpoints.cpp" />
<ClCompile Include="Debugger\SymbolMap.cpp" /> <ClCompile Include="Debugger\SymbolMap.cpp" />
<ClCompile Include="Dialog\PSPDialog.cpp" /> <ClCompile Include="Dialog\PSPDialog.cpp" />
@ -330,6 +332,7 @@
<ClInclude Include="CoreParameter.h" /> <ClInclude Include="CoreParameter.h" />
<ClInclude Include="CoreTiming.h" /> <ClInclude Include="CoreTiming.h" />
<ClInclude Include="CPU.h" /> <ClInclude Include="CPU.h" />
<ClInclude Include="Cwcheat.h" />
<ClInclude Include="Debugger\Breakpoints.h" /> <ClInclude Include="Debugger\Breakpoints.h" />
<ClInclude Include="Debugger\DebugInterface.h" /> <ClInclude Include="Debugger\DebugInterface.h" />
<ClInclude Include="Debugger\SymbolMap.h" /> <ClInclude Include="Debugger\SymbolMap.h" />

View File

@ -417,6 +417,9 @@
<ClCompile Include="FileSystems\tlzrc.cpp"> <ClCompile Include="FileSystems\tlzrc.cpp">
<Filter>FileSystems</Filter> <Filter>FileSystems</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Cwcheat.cpp">
<Filter>Core</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="ELF\ElfReader.h"> <ClInclude Include="ELF\ElfReader.h">
@ -769,6 +772,9 @@
<Filter>HLE\Libraries</Filter> <Filter>HLE\Libraries</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="HLE\sceMp3.h" /> <ClInclude Include="HLE\sceMp3.h" />
<ClInclude Include="Cwcheat.h">
<Filter>Core</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="CMakeLists.txt" /> <None Include="CMakeLists.txt" />

View File

@ -1,10 +1,471 @@
#include "CwCheat.h" #include "CwCheat.h"
#include "Config.h" #include "../Core/CoreTiming.h"
#include "UI\MenuScreens.cpp" #include "../Core/CoreParameter.h"
using namespace std; using namespace std;
void runCheats() { static int CheatEvent = -1;
CheatsGUI member;
void hleCheat(u64 userdata, int cyclesLate);
void __CheatInit() {
CheatEvent = CoreTiming::RegisterEvent("CheatEvent", &hleCheat);
CoreTiming::ScheduleEvent(msToCycles(66), CheatEvent, 0);
}
void __CheatShutdown() {
member.Exit();
}
void hleCheat(u64 userdata, int cyclesLate) {
CoreTiming::ScheduleEvent(msToCycles(66), CheatEvent, 0);
member.Run();
}
CheatsGUI::CheatsGUI() {
} }
void CheatsGUI::Exit() {
exit2 = true;
}
string CheatsGUI::GetNextCode() {
string code;
string modifier = "_L";
while (true) {
if (currentCode >= codes.size()) {
code.clear();
break;
}
code = codes[currentCode++];
trim2(code);
if (code.substr(0,2) == modifier) {
code = code.substr(3,21);
}
else if (code[0] == '0') {
break;
}
}
return code;
}
void CheatsGUI::skipCodes(int count) {
for (int i = 0; i < count; i ++) {
if (GetNextCode() == "") {
break;
}
}
}
void CheatsGUI::skipAllCodes() {
currentCode = codes.size();
}
int CheatsGUI::getAddress(int value) {
// The User space base address has to be added to given value
return (value + 0x08800000) & 0x3FFFFFFF;
}
void CheatsGUI::AddCheatLine(string& line) {
//Need GUI text area here
string cheatCodes;
if (cheatCodes.length() <= 0) {
cheatCodes = line;
} else {
cheatCodes += "/n" + line;
}
}
inline static long parseHexLong(string s) {
long value = 0;
if (s.substr(0,2) == "0x") {
s = s.substr(2);
}
value = strtol(s.c_str(),NULL, 16);
return value;
}
inline static long parseLong(string s) {
long value = 0;
if (s.substr(0,2) == "0x") {
s = s.substr(2);
value = strtol(s.c_str(),NULL, 16);
} else {
value = strtol(s.c_str(),NULL, 10);
}
return value;
}
inline void trim2(string& str)
{
string::size_type pos = str.find_last_not_of(' ');
if(pos != string::npos) {
str.erase(pos + 1);
pos = str.find_first_not_of(' ');
if(pos != string::npos) str.erase(0, pos);
}
else str.erase(str.begin(), str.end());
}
inline vector<string> makeCodeParts(string l) {
vector<string> parts;
char split_char = '/n';
char empty = ' ';
for (int i=0; i < l.length(); i++) {
if (l[i] == empty) {
l[i] = '\n';
}
}
trim2(l);
istringstream iss (l);
for (std::string each; std::getline(iss, each, split_char);parts.push_back(each))
{}
return parts;
}
vector<string> CheatsGUI::GetCodesList() {
string text = "0x203BFA00 0x05F5E0FF";
vector<string> codeslist;
codeslist = makeCodeParts(text);
trim2(codeslist[0]);
trim2(codeslist[1]);
return codeslist;
}
void CheatsGUI::OnCheatsThreadEnded() {
cheatsThread = false;
}
void CheatsGUI::Dispose() {
}
void CheatsGUI::Run() {
CheatsGUI cheats;
while (!exit2) {
codes = cheats.GetCodesList(); //UI Member
currentCode = 0;
while (true) {
string code = GetNextCode();
vector<string>parts = makeCodeParts(code);
int value;
trim2(parts[0]);
trim2(parts[1]);
int comm = (int)parseHexLong(parts[0]);
int arg = (int)parseHexLong(parts[1]);
int addr = getAddress(comm & 0x0FFFFFFF);
switch (comm >> 28) {
case 0: // 8-bit write.
if (Memory::IsValidAddress(addr)){
Memory::Write_U8((u8) arg, addr);
}
break;
case 0x1: // 16-bit write
if (Memory::IsValidAddress(addr)){
Memory::Write_U16((u16) arg, addr);
}
break;
case 0x2: // 32-bit write
if (Memory::IsValidAddress(addr)){
Memory::Write_U32((u32) arg, addr);
}
break;
case 0x3: // Increment/Decrement
{
addr = getAddress(arg);
value = 0;
int increment = 0;
// Read value from memory
switch ((comm >> 20) & 0xF) {
case 1:
case 2: // 8-bit
value = Memory::Read_U8(addr);
increment = comm & 0xFF;
break;
case 3:
case 4: // 16-bit
value = Memory::Read_U16(addr);
increment = comm & 0xFFFF;
break;
case 5:
case 6: // 32-bit
value = Memory::Read_U32(addr);
code = GetNextCode();
parts = makeCodeParts(code);
trim2(parts[0]);
if ( parts[0] != "") {
increment = (int) parseHexLong(parts[0]);
}
break;
}
// Increment/Decrement value
switch ((comm >> 20) & 0xF) {
case 1:
case 3:
case 5: // increment
value += increment;
break;
case 2:
case 4:
case 6: // Decrement
value -= increment;
break;
}
// Write value back to memory
switch ((comm >> 20) & 0xF) {
case 1:
case 2: // 8-bit
Memory::Write_U8((u8) value, addr);
break;
case 3:
case 4: // 16-bit
Memory::Write_U16((u16) value, addr);
break;
case 5:
case 6: // 32-bit
Memory::Write_U32((u32) value, addr);
break;
}
break; }
case 0x4: // 32-bit patch code
code = GetNextCode();
parts = makeCodeParts(code);
trim2(parts[0]);
trim2(parts[1]);
if (parts[0] != "") {
int data = (int) parseHexLong(parts[0]);
int dataAdd = (int) parseHexLong(parts[1]);
int maxAddr = (arg >> 16) & 0xFFFF;
int stepAddr = (arg & 0xFFFF) * 4;
for (int a = 0; a < maxAddr; a++) {
if (Memory::IsValidAddress(addr)) {
Memory::Write_U32((u32) data, addr);
}
addr += stepAddr;
data += dataAdd;
}
}
break;
case 0x5: // Memcpy command
code = GetNextCode();
parts = makeCodeParts(code);
trim2(parts[0]);
trim2(parts[1]);
if (parts[0] != "") {
int destAddr = (int) parseHexLong(parts[0]);
if (Memory::IsValidAddress(addr) && Memory::IsValidAddress(destAddr)) {
Memory::Memcpy(destAddr, Memory::GetPointer(addr), arg);
}
}
break;
case 0x6: // Pointer commands
code = GetNextCode();
parts = makeCodeParts(code);
trim2(parts[0]);
trim2(parts[1]);
if (parts[0] != "") {
int arg2 = (int) parseHexLong(parts[0]);
int offset = (int) parseHexLong(parts[1]);
int baseOffset = (arg2 >> 20) * 4;
int base = Memory::Read_U32(addr + baseOffset);
int count = arg2 & 0xFFFF;
int type = (arg2 >> 16) & 0xF;
for (int i = 1; i < count; i ++ ) {
if (i+1 < count) {
code = GetNextCode();
parts = makeCodeParts(code);
trim2(parts[0]);
trim2(parts[1]);
int arg3 = (int) parseHexLong(parts[0]);
int arg4 = (int) parseHexLong(parts[1]);
int comm3 = arg3 >> 28;
switch (comm3) {
case 0x1: // type copy byte
{
int srcAddr = Memory::Read_U32(addr) + offset;
int dstAddr = Memory::Read_U16(addr + baseOffset) + (arg3 & 0x0FFFFFFF);
Memory::Memcpy(dstAddr, Memory::GetPointer(srcAddr), arg);
type = -1; //Done
break; }
case 0x2:
case 0x3: // type pointer walk
{
int walkOffset = arg3 & 0x0FFFFFFF;
if (comm3 == 0x3) {
walkOffset = -walkOffset;
}
base = Memory::Read_U32(base + walkOffset);
int comm4 = arg4 >> 28;
switch (comm4) {
case 0x2:
case 0x3: // type pointer walk
walkOffset = arg4 & 0x0FFFFFFF;
if (comm4 == 0x3) {
walkOffset = -walkOffset;
}
base = Memory::Read_U32(base + walkOffset);
break;
}
break; }
case 0x9: // type multi address write
base += arg3 & 0x0FFFFFFF;
arg += arg4;
break;
}
}
}
switch (type) {
case 0: // 8 bit write
Memory::Write_U8((u8) arg, base + offset);
break;
case 1: // 16-bit write
Memory::Write_U16((u16) arg, base + offset);
break;
case 2: // 32-bit write
Memory::Write_U32((u32) arg, base + offset);
break;
case 3: // 8 bit inverse write
Memory::Write_U8((u8) arg, base - offset);
break;
case 4: // 16-bit inverse write
Memory::Write_U16((u16) arg, base - offset);
break;
case 5: // 32-bit inverse write
Memory::Write_U32((u32) arg, base - offset);
break;
case -1: // Operation already performed, nothing to do
break;
}
}
break;
case 0x7: // Boolean commands.
switch (arg >> 16) {
case 0x0000: // 8-bit OR.
if (Memory::IsValidAddress(addr)) {
int val1 = (int) (arg & 0xFF);
int val2 = (int) Memory::Read_U8(addr);
Memory::Write_U8((u8) (val1 | val2), addr);
}
break;
case 0x0002: // 8-bit AND.
if (Memory::IsValidAddress(addr)) {
int val1 = (int) (arg & 0xFF);
int val2 = (int) Memory::Read_U8(addr);
Memory::Write_U8((u8) (val1 & val2), addr);
}
break;
case 0x0004: // 8-bit XOR.
if (Memory::IsValidAddress(addr)) {
int val1 = (int) (arg & 0xFF);
int val2 = (int) Memory::Read_U8(addr);
Memory::Write_U8((u8) (val1 ^ val2), addr);
}
break;
case 0x0001: // 16-bit OR.
if (Memory::IsValidAddress(addr)) {
short val1 = (short) (arg & 0xFFFF);
short val2 = (short) Memory::Read_U16(addr);
Memory::Write_U16((u16) (val1 | val2), addr);
}
break;
case 0x0003: // 16-bit AND.
if (Memory::IsValidAddress(addr)) {
short val1 = (short) (arg & 0xFFFF);
short val2 = (short) Memory::Read_U16(addr);
Memory::Write_U16((u16) (val1 & val2), addr);
}
break;
case 0x0005: // 16-bit OR.
if (Memory::IsValidAddress(addr)) {
short val1 = (short) (arg & 0xFFFF);
short val2 = (short) Memory::Read_U16(addr);
Memory::Write_U16((u16) (val1 ^ val2), addr);
}
break;
}
break;
case 0x8: // 8-bit and 16-bit patch code
code = GetNextCode();
parts = makeCodeParts(code);
trim2(parts[0]);
trim2(parts[1]);
if (parts[0] != "") {
int data = (int) parseHexLong(parts[0]);
int dataAdd = (int) parseHexLong(parts[1]);
bool is8Bit = (data >> 16) == 0x0000;
int maxAddr = (arg >> 16) & 0xFFFF;
int stepAddr = (arg & 0xFFFF) * (is8Bit ? 1 : 2);
for (int a = 0; a < maxAddr; a++) {
if (Memory::IsValidAddress(addr)) {
if (is8Bit) {
Memory::Write_U8((u8) (data & 0xFF), addr);
}
else {
Memory::Write_U16((u16) (data & 0xFFFF), addr);
}
}
addr += stepAddr;
data += dataAdd;
}
}
break;
case 0xB: // Time command (not sure what to do?)
break;
case 0xC: // Code stopper
if (Memory::IsValidAddress(addr)) {
value = Memory::Read_U32(addr);
if (value != arg) {
skipAllCodes();
}
}
break;
case 0xD: // Test commands & Jocker codes ( Someone will have to help me with these)
break;
case 0xE: // Test commands, multiple skip
bool is8Bit = (comm >> 24) == 0x1;
addr = getAddress(arg & 0x0FFFFFFF);
if (Memory::IsValidAddress(addr)) {
int memoryValue = is8Bit ? Memory::Read_U8(addr) : Memory::Read_U16(addr);
int testValue = comm & (is8Bit ? 0xFF : 0xFFFF);
bool executeNextLines = false;
switch ( arg >> 28) {
case 0x0: // Equal
executeNextLines = memoryValue == testValue;
break;
case 0x1: // Not Equal
executeNextLines = memoryValue != testValue;
break;
case 0x2: // Less Than
executeNextLines = memoryValue < testValue;
break;
case 0x3: // Greater Than
executeNextLines = memoryValue > testValue;
break;
}
if (!executeNextLines) {
int skip = (comm >> 16) & (is8Bit ? 0xFF : 0xFFF);
skipCodes(skip);
}
}
break;
}
}
}
// exiting...
cheats.OnCheatsThreadEnded();
}

View File

@ -1,15 +1,17 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <map>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include "Core\MemMap.h" #include "Core\MemMap.h"
void __CheatInit();
void __CheatShutdown();
//void Register_CwCheat();
using namespace std; using namespace std;
class CheatsThread;
class CheatsGUI;
vector<string> makeCodeParts(string l); vector<string> makeCodeParts(string l);
void trim2(string& str); void trim2(string& str);
static long parseLong(string s); static long parseLong(string s);
@ -18,477 +20,30 @@ static long parseHexLong(string s);
class CheatsGUI { class CheatsGUI {
private: private:
static long const serialVersionUID = 6791588139795694296L; static long const serialVersionUID = 6791588139795694296L;
static long const int cheatsThreadSleepMillis = 5; static long const int cheatsThreadSleepMillis = 5;
bool cheatsOn; bool cheatsOn;
CheatsThread cheatsThread; std::vector<std::string> codes;
int currentCode;
bool exit2;
void skipCodes(int count);
void skipAllCodes();
int getAddress(int value);
bool cheatsThread;
public: public:
CheatsGUI(); CheatsGUI();
string String(); string String();
void addCheatLine(string& line); void AddCheatLine(string& line);
void onCheatsThreadEnded(); void OnCheatsThreadEnded();
void dispose(); void Dispose();
vector<string> getCodesList(); vector<string> GetCodesList();
};
class CheatsThread {
private:
std::vector<std::string> codes;
int currentCode;
CheatsGUI cheats;
bool exit2;
void skipCodes(int count);
void skipAllCodes();
int getAddress(int value);
void Exit();
public: void Run();
CheatsThread(CheatsGUI cheats); string GetNextCode();
void exit();
void run();
string getNextCode();
}; };
CheatsThread::CheatsThread(CheatsGUI cheats){
this->cheats = cheats;
}
void CheatsThread::exit() {
exit2 = true;
}
string CheatsThread::getNextCode() {
string code;
string modifier = "_L";
while (true) {
if (currentCode >= codes.size()) {
code.clear();
break;
}
code = codes[currentCode++];
trim2(code);
if (code.substr(0,2) == modifier) {
code = code.substr(3,21);
}
else if (code[0] == '0') {
break;
}
}
return code;
}
void CheatsThread::skipCodes(int count) {
for (int i = 0; i < count; i ++) {
if (getNextCode() == "") {
break;
}
}
}
void CheatsThread::skipAllCodes() {
currentCode = codes.size();
}
int CheatsThread::getAddress(int value) {
// The User space base address has to be added to given value
return (value + 0x08800000) & 0x3FFFFFFF;
}
void CheatsThread::run() {
while (!exit2) {
codes = cheats.getCodesList(); //UI Member
currentCode = 0;
while (true) {
string code = getNextCode();
vector<string>parts = makeCodeParts(code);
int value;
trim2(parts[0]);
trim2(parts[1]);
int comm = (int)parseHexLong(parts[0]);
int arg = (int)parseHexLong(parts[1]);
int addr = getAddress(comm & 0x0FFFFFFF);
switch (comm >> 28) {
case 0: // 8-bit write.
if (Memory::IsValidAddress(addr)){
Memory::Write_U8((u8) arg, addr);
}
break;
case 0x1: // 16-bit write
if (Memory::IsValidAddress(addr)){
Memory::Write_U16((u16) arg, addr);
}
break;
case 0x2: // 32-bit write
if (Memory::IsValidAddress(addr)){
Memory::Write_U32((u32) arg, addr);
}
break;
case 0x3: // Increment/Decrement
{
addr = getAddress(arg);
value = 0;
int increment = 0;
// Read value from memory
switch ((comm >> 20) & 0xF) {
case 1:
case 2: // 8-bit
value = Memory::Read_U8(addr);
increment = comm & 0xFF;
break;
case 3:
case 4: // 16-bit
value = Memory::Read_U16(addr);
increment = comm & 0xFFFF;
break;
case 5:
case 6: // 32-bit
value = Memory::Read_U32(addr);
code = getNextCode();
parts = makeCodeParts(code);
trim2(parts[0]);
if ( parts[0] != "") {
increment = (int) parseHexLong(parts[0]);
}
break;
}
// Increment/Decrement value
switch ((comm >> 20) & 0xF) {
case 1:
case 3:
case 5: // increment
value += increment;
break;
case 2:
case 4:
case 6: // Decrement
value -= increment;
break;
}
// Write value back to memory
switch ((comm >> 20) & 0xF) {
case 1:
case 2: // 8-bit
Memory::Write_U8((u8) value, addr);
break;
case 3:
case 4: // 16-bit
Memory::Write_U16((u16) value, addr);
break;
case 5:
case 6: // 32-bit
Memory::Write_U32((u32) value, addr);
break;
}
break; }
case 0x4: // 32-bit patch code
code = getNextCode();
parts = makeCodeParts(code);
trim2(parts[0]);
trim2(parts[1]);
if (parts[0] != "") {
int data = (int) parseHexLong(parts[0]);
int dataAdd = (int) parseHexLong(parts[1]);
int maxAddr = (arg >> 16) & 0xFFFF;
int stepAddr = (arg & 0xFFFF) * 4;
for (int a = 0; a < maxAddr; a++) {
if (Memory::IsValidAddress(addr)) {
Memory::Write_U32((u32) data, addr);
}
addr += stepAddr;
data += dataAdd;
}
}
break;
case 0x5: // Memcpy command
code = getNextCode();
parts = makeCodeParts(code);
trim2(parts[0]);
trim2(parts[1]);
if (parts[0] != "") {
int destAddr = (int) parseHexLong(parts[0]);
if (Memory::IsValidAddress(addr) && Memory::IsValidAddress(destAddr)) {
Memory::Memcpy(destAddr, Memory::GetPointer(addr), arg);
}
}
break;
case 0x6: // Pointer commands
code = getNextCode();
parts = makeCodeParts(code);
trim2(parts[0]);
trim2(parts[1]);
if (parts[0] != "") {
int arg2 = (int) parseHexLong(parts[0]);
int offset = (int) parseHexLong(parts[1]);
int baseOffset = (arg2 >> 20) * 4;
int base = Memory::Read_U32(addr + baseOffset);
int count = arg2 & 0xFFFF;
int type = (arg2 >> 16) & 0xF;
for (int i = 1; i < count; i ++ ) {
if (i+1 < count) {
code = getNextCode();
parts = makeCodeParts(code);
trim2(parts[0]);
trim2(parts[1]);
int arg3 = (int) parseHexLong(parts[0]);
int arg4 = (int) parseHexLong(parts[1]);
int comm3 = arg3 >> 28;
switch (comm3) {
case 0x1: // type copy byte
{
int srcAddr = Memory::Read_U32(addr) + offset;
int dstAddr = Memory::Read_U16(addr + baseOffset) + (arg3 & 0x0FFFFFFF);
Memory::Memcpy(dstAddr, Memory::GetPointer(srcAddr), arg);
type = -1; //Done
break; }
case 0x2:
case 0x3: // type pointer walk
{
int walkOffset = arg3 & 0x0FFFFFFF;
if (comm3 == 0x3) {
walkOffset = -walkOffset;
}
base = Memory::Read_U32(base + walkOffset);
int comm4 = arg4 >> 28;
switch (comm4) {
case 0x2:
case 0x3: // type pointer walk
walkOffset = arg4 & 0x0FFFFFFF;
if (comm4 == 0x3) {
walkOffset = -walkOffset;
}
base = Memory::Read_U32(base + walkOffset);
break;
}
break; }
case 0x9: // type multi address write
base += arg3 & 0x0FFFFFFF;
arg += arg4;
break;
}
}
}
switch (type) {
case 0: // 8 bit write
Memory::Write_U8((u8) arg, base + offset);
break;
case 1: // 16-bit write
Memory::Write_U16((u16) arg, base + offset);
break;
case 2: // 32-bit write
Memory::Write_U32((u32) arg, base + offset);
break;
case 3: // 8 bit inverse write
Memory::Write_U8((u8) arg, base - offset);
break;
case 4: // 16-bit inverse write
Memory::Write_U16((u16) arg, base - offset);
break;
case 5: // 32-bit inverse write
Memory::Write_U32((u32) arg, base - offset);
break;
case -1: // Operation already performed, nothing to do
break;
}
}
break;
case 0x7: // Boolean commands.
switch (arg >> 16) {
case 0x0000: // 8-bit OR.
if (Memory::IsValidAddress(addr)) {
int val1 = (int) (arg & 0xFF);
int val2 = (int) Memory::Read_U8(addr);
Memory::Write_U8((u8) (val1 | val2), addr);
}
break;
case 0x0002: // 8-bit AND.
if (Memory::IsValidAddress(addr)) {
int val1 = (int) (arg & 0xFF);
int val2 = (int) Memory::Read_U8(addr);
Memory::Write_U8((u8) (val1 & val2), addr);
}
break;
case 0x0004: // 8-bit XOR.
if (Memory::IsValidAddress(addr)) {
int val1 = (int) (arg & 0xFF);
int val2 = (int) Memory::Read_U8(addr);
Memory::Write_U8((u8) (val1 ^ val2), addr);
}
break;
case 0x0001: // 16-bit OR.
if (Memory::IsValidAddress(addr)) {
short val1 = (short) (arg & 0xFFFF);
short val2 = (short) Memory::Read_U16(addr);
Memory::Write_U16((u16) (val1 | val2), addr);
}
break;
case 0x0003: // 16-bit AND.
if (Memory::IsValidAddress(addr)) {
short val1 = (short) (arg & 0xFFFF);
short val2 = (short) Memory::Read_U16(addr);
Memory::Write_U16((u16) (val1 & val2), addr);
}
break;
case 0x0005: // 16-bit OR.
if (Memory::IsValidAddress(addr)) {
short val1 = (short) (arg & 0xFFFF);
short val2 = (short) Memory::Read_U16(addr);
Memory::Write_U16((u16) (val1 ^ val2), addr);
}
break;
}
break;
case 0x8: // 8-bit and 16-bit patch code
code = getNextCode();
parts = makeCodeParts(code);
trim2(parts[0]);
trim2(parts[1]);
if (parts[0] != "") {
int data = (int) parseHexLong(parts[0]);
int dataAdd = (int) parseHexLong(parts[1]);
bool is8Bit = (data >> 16) == 0x0000;
int maxAddr = (arg >> 16) & 0xFFFF;
int stepAddr = (arg & 0xFFFF) * (is8Bit ? 1 : 2);
for (int a = 0; a < maxAddr; a++) {
if (Memory::IsValidAddress(addr)) {
if (is8Bit) {
Memory::Write_U8((u8) (data & 0xFF), addr);
}
else {
Memory::Write_U16((u16) (data & 0xFFFF), addr);
}
}
addr += stepAddr;
data += dataAdd;
}
}
break;
case 0xB: // Time command (not sure what to do?)
break;
case 0xC: // Code stopper
if (Memory::IsValidAddress(addr)) {
value = Memory::Read_U32(addr);
if (value != arg) {
skipAllCodes();
}
}
break;
case 0xD: // Test commands & Jocker codes ( Someone will have to help me with these)
break;
case 0xE: // Test commands, multiple skip
bool is8Bit = (comm >> 24) == 0x1;
addr = getAddress(arg & 0x0FFFFFFF);
if (Memory::IsValidAddress(addr)) {
int memoryValue = is8Bit ? Memory::Read_U8(addr) : Memory::Read_U16(addr);
int testValue = comm & (is8Bit ? 0xFF : 0xFFFF);
bool executeNextLines = false;
switch ( arg >> 28) {
case 0x0: // Equal
executeNextLines = memoryValue == testValue;
break;
case 0x1: // Not Equal
executeNextLines = memoryValue != testValue;
break;
case 0x2: // Less Than
executeNextLines = memoryValue < testValue;
break;
case 0x3: // Greater Than
executeNextLines = memoryValue > testValue;
break;
}
if (!executeNextLines) {
int skip = (comm >> 16) & (is8Bit ? 0xFF : 0xFFF);
skipCodes(skip);
}
}
break;
}
}
}
// exiting...
cheats.onCheatsThreadEnded();
}
CheatsGUI::CheatsGUI() {
}
void CheatsGUI::addCheatLine(string& line) {
//Need GUI text area here
string cheatCodes;
if (cheatCodes.length() <= 0) {
cheatCodes = line;
} else {
cheatCodes += "/n" + line;
}
}
static long parseHexLong(string s) {
long value = 0;
if (s.substr(0,2) == "0x") {
s = s.substr(2);
}
value = strtol(s.c_str(),NULL, 16);
return value;
}
static long parseLong(string s) {
long value = 0;
if (s.substr(0,2) == "0x") {
s = s.substr(2);
value = strtol(s.c_str(),NULL, 16);
} else {
value = strtol(s.c_str(),NULL, 10);
}
return value;
}
void trim2(string& str)
{
string::size_type pos = str.find_last_not_of(' ');
if(pos != string::npos) {
str.erase(pos + 1);
pos = str.find_first_not_of(' ');
if(pos != string::npos) str.erase(0, pos);
}
else str.erase(str.begin(), str.end());
}
vector<string> makeCodeParts(string l) {
vector<string> parts;
char split_char = '/n';
char empty = ' ';
for (int i=0; i < l.length(); i++) {
if (l[i] == empty) {
l[i] = '\n';
}
}
trim2(l);
istringstream iss (l);
for (std::string each; std::getline(iss, each, split_char);parts.push_back(each))
{}
return parts;
}
vector<string> CheatsGUI::getCodesList() {
string text = "0x203BFA00 0x3B9AC9FF";
vector<string> codes;
trim2(text);
codes = makeCodeParts(text);
return codes;
}
void CheatsGUI::onCheatsThreadEnded() {
cheatsThread = NULL;
}
void CheatsGUI::dispose() {
}

View File

@ -16,6 +16,7 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "Core/Config.h" #include "Core/Config.h"
#include "Core/Cwcheat.h"
#include "Core/HLE/HLE.h" #include "Core/HLE/HLE.h"
#include "Core/MIPS/MIPS.h" #include "Core/MIPS/MIPS.h"
#include "Core/MIPS/MIPSCodeUtils.h" #include "Core/MIPS/MIPSCodeUtils.h"
@ -115,6 +116,7 @@ void __KernelInit()
__UsbInit(); __UsbInit();
__FontInit(); __FontInit();
__NetInit(); __NetInit();
__CheatInit();
SaveState::Init(); // Must be after IO, as it may create a directory SaveState::Init(); // Must be after IO, as it may create a directory
@ -156,6 +158,7 @@ void __KernelShutdown()
__KernelThreadingShutdown(); __KernelThreadingShutdown();
__KernelMemoryShutdown(); __KernelMemoryShutdown();
__InterruptsShutdown(); __InterruptsShutdown();
__CheatShutdown();
CoreTiming::ClearPendingEvents(); CoreTiming::ClearPendingEvents();
CoreTiming::UnregisterAllEvents(); CoreTiming::UnregisterAllEvents();