2 #include "UI/OnScreenDisplay.h"
3 #include "Common/StringUtils.h"
4 #include "Common/ChunkFile.h"
5 #include "Common/FileUtil.h"
6 #include "Core/CoreTiming.h"
7 #include "Core/CoreParameter.h"
8 #include "Core/CwCheat.h"
9 #include "Core/Config.h"
10 #include "Core/MIPS/MIPS.h"
11 #include "Core/ELF/ParamSFO.h"
12 #include "Core/System.h"
13 #include "Core/HLE/sceCtrl.h"
14 #include "Core/MIPS/JitCommon/NativeJit.h"
16 #if defined(_WIN32) && !defined(__MINGW32__)
17 #include "util/text/utf8.h"
20 static int CheatEvent
= -1;
21 std::string gameTitle
;
22 std::string activeCheatFile
;
23 static CWCheatEngine
*cheatEngine
;
24 static bool cheatsEnabled
;
25 void hleCheat(u64 userdata
, int cyclesLate
);
26 void trim2(std::string
& str
);
28 static void __CheatStop() {
29 if (cheatEngine
!= 0) {
34 cheatsEnabled
= false;
37 static void __CheatStart() {
40 gameTitle
= g_paramSFO
.GetValueString("DISC_ID");
42 activeCheatFile
= GetSysDirectory(DIRECTORY_CHEATS
) + gameTitle
+ ".ini";
43 File::CreateFullPath(GetSysDirectory(DIRECTORY_CHEATS
));
45 if (!File::Exists(activeCheatFile
)) {
46 FILE *f
= File::OpenCFile(activeCheatFile
, "wb");
48 fwrite("\xEF\xBB\xBF", 1, 3, f
);
51 if (!File::Exists(activeCheatFile
)) {
52 I18NCategory
*err
= GetI18NCategory("Error");
53 osm
.Show(err
->T("Unable to create cheat file, disk may be full"));
58 cheatEngine
= new CWCheatEngine();
59 cheatEngine
->CreateCodeList();
60 g_Config
.bReloadCheats
= false;
65 // Always register the event, want savestates to be compatible whether cheats on or off.
66 CheatEvent
= CoreTiming::RegisterEvent("CheatEvent", &hleCheat
);
68 if (g_Config
.bEnableCheats
) {
72 int refresh
= g_Config
.iCwCheatRefreshRate
;
74 // Only check once a second for cheats to be enabled.
75 CoreTiming::ScheduleEvent(msToCycles(cheatsEnabled
? refresh
: 1000), CheatEvent
, 0);
78 void __CheatShutdown() {
82 void __CheatDoState(PointerWrap
&p
) {
83 auto s
= p
.Section("CwCheat", 0, 2);
89 CoreTiming::RestoreRegisterEvent(CheatEvent
, "CheatEvent", &hleCheat
);
91 int refresh
= g_Config
.iCwCheatRefreshRate
;
94 // Before this we didn't have a checkpoint, so reset didn't work.
95 // Let's just force one in.
96 CoreTiming::RemoveEvent(CheatEvent
);
97 CoreTiming::ScheduleEvent(msToCycles(cheatsEnabled
? refresh
: 1000), CheatEvent
, 0);
101 void hleCheat(u64 userdata
, int cyclesLate
) {
102 if (cheatsEnabled
!= g_Config
.bEnableCheats
) {
103 // Okay, let's move to the desired state, then.
104 if (g_Config
.bEnableCheats
) {
111 int refresh
= g_Config
.iCwCheatRefreshRate
;
113 // Only check once a second for cheats to be enabled.
114 CoreTiming::ScheduleEvent(msToCycles(cheatsEnabled
? refresh
: 1000), CheatEvent
, 0);
116 if (!cheatEngine
|| !cheatsEnabled
)
119 if (g_Config
.bReloadCheats
) { //Checks if the "reload cheats" button has been pressed.
120 cheatEngine
->CreateCodeList();
121 g_Config
.bReloadCheats
= false;
126 CWCheatEngine::CWCheatEngine() {
130 void CWCheatEngine::Exit() {
134 // Takes a single code line and creates a two-part vector for each code. Feeds to CreateCodeList
135 static inline std::vector
<std::string
> makeCodeParts(const std::vector
<std::string
>& CodesList
) {
136 std::string currentcode
;
137 std::vector
<std::string
> finalList
;
138 char split_char
= '\n';
140 for (size_t i
= 0; i
< CodesList
.size(); i
++) {
141 currentcode
= CodesList
[i
];
142 for (size_t j
=0; j
< currentcode
.length(); j
++) {
143 if (currentcode
[j
] == empty
) {
144 currentcode
[j
] = '\n';
148 std::istringstream
iss(currentcode
);
150 while (std::getline(iss
, each
, split_char
)) {
151 finalList
.push_back(each
);
157 void CWCheatEngine::CreateCodeList() { //Creates code list to be used in function GetNextCode
158 initialCodesList
= GetCodesList();
159 std::string currentcode
, codename
;
160 std::vector
<std::string
> codelist
;
161 for (size_t i
= 0; i
< initialCodesList
.size(); i
++) {
162 if (initialCodesList
[i
].substr(0,2) == "_S") {
163 continue; //Line indicates Disc ID, not needed for cheats
165 if (initialCodesList
[i
].substr(0,2) == "_G") {
166 continue; //Line indicates game Title, also not needed for cheats
168 if (initialCodesList
[i
].substr(0,2) == "//") {
169 continue; //Line indicates comment, also not needed for cheats.
171 if (initialCodesList
[i
].substr(0,3) == "_C1") {
173 codename
= initialCodesList
[i
];
174 codename
.erase (codename
.begin(), codename
.begin()+4);
175 codeNameList
.push_back(codename
); //Import names for GUI, will be implemented later.
178 if (initialCodesList
[i
].substr(0,2) == "_L") {
179 if (cheatEnabled
== true) {
180 currentcode
= initialCodesList
[i
];
181 currentcode
.erase(currentcode
.begin(), currentcode
.begin() + 3);
182 codelist
.push_back(currentcode
);
186 if (initialCodesList
[i
].substr(0,3) == "_C0") {
187 cheatEnabled
= false;
188 codename
= initialCodesList
[i
];
189 codename
.erase (codename
.begin(), codename
.begin()+4);
190 codeNameList
.push_back(codename
); //Import names for GUI, will be implemented later.
194 parts
= makeCodeParts(codelist
);
197 std::vector
<int> CWCheatEngine::GetNextCode() { // Feeds a size-2 vector of ints to Run() which contains the address and value of one cheat.
200 std::vector
<std::string
> splitCode
;
201 std::vector
<int> finalCode
;
202 std::string modifier2
= "0";
204 if (currentCode
>= parts
.size()) {
209 code1
= parts
[currentCode
++];
211 code2
= parts
[currentCode
++];
213 splitCode
.push_back(code1
);
214 splitCode
.push_back(code2
);
216 int var1
= (int) parseHexLong(splitCode
[0]);
217 int var2
= (int) parseHexLong(splitCode
[1]);
218 finalCode
.push_back(var1
);
219 finalCode
.push_back(var2
);
220 if (splitCode
[0].substr(0,1) == modifier2
) {
227 void CWCheatEngine::SkipCodes(int count
) {
228 for (int i
= 0; i
< count
; i
++) {
229 auto code
= GetNextCode();
232 WARN_LOG(COMMON
, "CWCHEAT: Tried to skip more codes than there are, the cheat is most likely wrong");
241 void CWCheatEngine::SkipAllCodes() {
242 currentCode
= codes
.size() - 1;
245 int CWCheatEngine::GetAddress(int value
) { //Returns static address used by ppsspp. Some games may not like this, and causes cheats to not work without offset
246 int address
= (value
+ 0x08800000) & 0x3FFFFFFF;
247 if (gameTitle
== "ULUS10563" || gameTitle
== "ULJS-00351" || gameTitle
== "NPJH50352" ) //Offset to make God Eater Burst codes work
253 inline void trim2(std::string
& str
) {
254 size_t pos
= str
.find_last_not_of(' ');
255 if(pos
!= std::string::npos
) {
257 pos
= str
.find_first_not_of(' ');
258 if(pos
!= std::string::npos
) str
.erase(0, pos
);
260 else str
.erase(str
.begin(), str
.end());
263 std::vector
<std::string
> CWCheatEngine::GetCodesList() { //Reads the entire cheat list from the appropriate .ini.
265 std::vector
<std::string
> codesList
; // Read from INI here
266 #if defined(_WIN32) && !defined(__MINGW32__)
267 std::ifstream
list(ConvertUTF8ToWString(activeCheatFile
));
269 std::ifstream
list(activeCheatFile
.c_str());
274 for (int i
= 0; !list
.eof(); i
++) {
275 getline(list
, line
, '\n');
276 if (line
.length() > 3 && (line
.substr(0,1) == "_"||line
.substr(0,2) == "//")){
277 codesList
.push_back(line
);
280 for(size_t i
= 0; i
< codesList
.size(); i
++) {
286 void CWCheatEngine::InvalidateICache(u32 addr
, int size
) {
287 currentMIPS
->InvalidateICache(addr
& ~3, size
);
290 void CWCheatEngine::Run() {
296 std::vector
<int> code
= GetNextCode();
297 if (code
.size() < 2) {
303 unsigned int comm
= code
[0];
305 int addr
= GetAddress(comm
& 0x0FFFFFFF);
307 switch (comm
>> 28) {
308 case 0: // 8-bit write.But need more check
309 if (Memory::IsValidAddress(addr
)) {
310 InvalidateICache(addr
& ~3, 4);
311 if (arg
< 0x00000100) // 8-bit
312 Memory::Write_U8((u8
) arg
, addr
);
313 else if (arg
< 0x00010000) // 16-bit
314 Memory::Write_U16((u16
) arg
, addr
);
316 Memory::Write_U32((u32
) arg
, addr
);
319 case 0x1: // 16-bit write
320 if (Memory::IsValidAddress(addr
)) {
321 InvalidateICache(addr
& ~3, 4);
322 Memory::Write_U16((u16
) arg
, addr
);
325 case 0x2: // 32-bit write
326 if (Memory::IsValidAddress(addr
)){
327 InvalidateICache(addr
& ~3, 4);
328 Memory::Write_U32((u32
) arg
, addr
);
331 case 0x3: // Increment/Decrement
333 addr
= GetAddress(arg
& 0x0FFFFFFF);
334 InvalidateICache(addr
& ~3, 4);
337 // Read value from memory
338 switch ((comm
>> 20) & 0xF) {
341 value
= Memory::Read_U8(addr
);
342 increment
= comm
& 0xFF;
346 value
= Memory::Read_U16(addr
);
347 increment
= comm
& 0xFFFF;
351 value
= Memory::Read_U32(addr
);
352 code
= GetNextCode();
358 // Increment/Decrement value
359 switch ((comm
>> 20) & 0xF) {
371 // Write value back to memory
372 switch ((comm
>> 20) & 0xF) {
375 Memory::Write_U8((u8
) value
, addr
);
379 Memory::Write_U16((u16
) value
, addr
);
383 Memory::Write_U32((u32
) value
, addr
);
388 case 0x4: // 32-bit patch code
389 code
= GetNextCode();
392 int dataAdd
= code
[1];
394 int count
= (arg
>> 16) & 0xFFFF;
395 int stepAddr
= (arg
& 0xFFFF) * 4;
397 InvalidateICache(addr
, count
* stepAddr
);
398 for (int a
= 0; a
< count
; a
++) {
399 if (Memory::IsValidAddress(addr
)) {
400 Memory::Write_U32((u32
) data
, addr
);
407 case 0x5: // Memcpy command
408 code
= GetNextCode();
410 int destAddr
= GetAddress(code
[0]);
412 InvalidateICache(destAddr
, len
);
413 if (Memory::IsValidAddress(addr
) && Memory::IsValidAddress(destAddr
)) {
414 Memory::MemcpyUnchecked(destAddr
, addr
, len
);
418 case 0x6: // Pointer commands
419 code
= GetNextCode();
420 if (code
.size() >= 2) {
422 int offset
= code
[1];
423 int baseOffset
= (arg2
>> 20) * 4;
424 InvalidateICache(addr
+ baseOffset
, 4);
425 int base
= Memory::Read_U32(addr
+ baseOffset
);
426 int count
= arg2
& 0xFFFF;
427 int type
= (arg2
>> 16) & 0xF;
428 for (int i
= 1; i
< count
; i
++ ) {
430 code
= GetNextCode();
431 if (code
.size() < 2) {
432 // Code broken. Should warn but would be very spammy...
437 int comm3
= arg3
>> 28;
439 case 0x1: // type copy byte
441 int srcAddr
= Memory::Read_U32(addr
) + offset
;
442 int dstAddr
= Memory::Read_U16(addr
+ baseOffset
) + (arg3
& 0x0FFFFFFF);
443 if (Memory::IsValidAddress(dstAddr
) && Memory::IsValidAddress(srcAddr
)) {
444 Memory::MemcpyUnchecked(dstAddr
, srcAddr
, arg
);
449 case 0x3: // type pointer walk
451 int walkOffset
= arg3
& 0x0FFFFFFF;
453 walkOffset
= -walkOffset
;
455 base
= Memory::Read_U32(base
+ walkOffset
);
456 int comm4
= arg4
>> 28;
459 case 0x3: // type pointer walk
460 walkOffset
= arg4
& 0x0FFFFFFF;
462 walkOffset
= -walkOffset
;
464 base
= Memory::Read_U32(base
+ walkOffset
);
468 case 0x9: // type multi address write
469 base
+= arg3
& 0x0FFFFFFF;
480 case 0: // 8 bit write
481 Memory::Write_U8((u8
) arg
, base
+ offset
);
483 case 1: // 16-bit write
484 Memory::Write_U16((u16
) arg
, base
+ offset
);
486 case 2: // 32-bit write
487 Memory::Write_U32((u32
) arg
, base
+ offset
);
489 case 3: // 8 bit inverse write
490 Memory::Write_U8((u8
) arg
, base
- offset
);
492 case 4: // 16-bit inverse write
493 Memory::Write_U16((u16
) arg
, base
- offset
);
495 case 5: // 32-bit inverse write
496 Memory::Write_U32((u32
) arg
, base
- offset
);
498 case -1: // Operation already performed, nothing to do
503 case 0x7: // Boolean commands.
505 case 0x0000: // 8-bit OR.
506 if (Memory::IsValidAddress(addr
)) {
507 InvalidateICache(addr
& ~3, 4);
508 int val1
= (int) (arg
& 0xFF);
509 int val2
= (int) Memory::Read_U8(addr
);
510 Memory::Write_U8((u8
) (val1
| val2
), addr
);
513 case 0x0002: // 8-bit AND.
514 if (Memory::IsValidAddress(addr
)) {
515 InvalidateICache(addr
& ~3, 4);
516 int val1
= (int) (arg
& 0xFF);
517 int val2
= (int) Memory::Read_U8(addr
);
518 Memory::Write_U8((u8
) (val1
& val2
), addr
);
521 case 0x0004: // 8-bit XOR.
522 if (Memory::IsValidAddress(addr
)) {
523 InvalidateICache(addr
& ~3, 4);
524 int val1
= (int) (arg
& 0xFF);
525 int val2
= (int) Memory::Read_U8(addr
);
526 Memory::Write_U8((u8
) (val1
^ val2
), addr
);
529 case 0x0001: // 16-bit OR.
530 if (Memory::IsValidAddress(addr
)) {
531 InvalidateICache(addr
& ~3, 4);
532 short val1
= (short) (arg
& 0xFFFF);
533 short val2
= (short) Memory::Read_U16(addr
);
534 Memory::Write_U16((u16
) (val1
| val2
), addr
);
537 case 0x0003: // 16-bit AND.
538 if (Memory::IsValidAddress(addr
)) {
539 InvalidateICache(addr
& ~3, 4);
540 short val1
= (short) (arg
& 0xFFFF);
541 short val2
= (short) Memory::Read_U16(addr
);
542 Memory::Write_U16((u16
) (val1
& val2
), addr
);
545 case 0x0005: // 16-bit OR.
546 if (Memory::IsValidAddress(addr
)) {
547 InvalidateICache(addr
& ~3, 4);
548 short val1
= (short) (arg
& 0xFFFF);
549 short val2
= (short) Memory::Read_U16(addr
);
550 Memory::Write_U16((u16
) (val1
^ val2
), addr
);
555 case 0x8: // 8-bit and 16-bit patch code
556 code
= GetNextCode();
557 if (code
.size() >= 2) {
559 int dataAdd
= code
[1];
561 bool is8Bit
= (data
>> 16) == 0x0000;
562 int count
= (arg
>> 16) & 0xFFFF;
563 int stepAddr
= (arg
& 0xFFFF) * (is8Bit
? 1 : 2);
564 InvalidateICache(addr
, count
* stepAddr
);
565 for (int a
= 0; a
< count
; a
++) {
566 if (Memory::IsValidAddress(addr
)) {
568 Memory::Write_U8((u8
) (data
& 0xFF), addr
);
571 Memory::Write_U16((u16
) (data
& 0xFFFF), addr
);
579 case 0xB: // Time command (not sure what to do?)
581 case 0xC: // Code stopper
582 if (Memory::IsValidAddress(addr
)) {
583 InvalidateICache(addr
, 4);
584 value
= Memory::Read_U32(addr
);
585 if ((u32
)value
!= arg
) {
590 case 0xD: // Test commands & Jocker codes
591 if ((arg
>> 28) == 0x0 || (arg
>> 28) == 0x2) { // 8Bit & 16Bit ignore next line cheat code
592 bool is8Bit
= (arg
>> 28) == 0x2;
593 addr
= GetAddress(comm
& 0x0FFFFFFF);
594 if (Memory::IsValidAddress(addr
)) {
595 int memoryValue
= is8Bit
? Memory::Read_U8(addr
) : Memory::Read_U16(addr
);
596 int testValue
= arg
& (is8Bit
? 0xFF : 0xFFFF);
597 bool executeNextLines
= false;
598 switch ((arg
>> 20) & 0xF) {
600 executeNextLines
= memoryValue
== testValue
;
602 case 0x1: // Not Equal
603 executeNextLines
= memoryValue
!= testValue
;
605 case 0x2: // Less Than
606 executeNextLines
= memoryValue
< testValue
;
608 case 0x3: // Greater Than
609 executeNextLines
= memoryValue
> testValue
;
614 if (!executeNextLines
)
619 else if ((arg
>> 28) == 0x1 || (arg
>> 28) == 0x3) { // Buttons dependent ignore cheat code
623 // DPAD UP 0x00000010
624 // DPAD RIGHT 0x00000020
625 // DPAD DOWN 0x00000040
626 // DPAD LEFT 0x00000080
627 // L TRIGGER 0x00000100
628 // R TRIGGER 0x00000200
629 // TRIANGLE 0x00001000
636 // REMOTE HOLD 0x00080000
637 // VOLUME UP 0x00100000
638 // VOLUME DOWN 0x00200000
641 u32 buttonStatus
= __CtrlPeekButtons();
642 int skip
= (comm
& 0xFF) + 1;
643 u32 mask
= arg
& 0x0FFFFFFF;
644 if ((arg
>> 28) == 0x1)
645 // Old, too specific check: if (buttonStatus == (arg & 0x0FFFFFFF)) // cheat code likes: 0xD00000nn 0x1bbbbbbb;
646 if ((buttonStatus
& mask
) == mask
) // cheat code likes: 0xD00000nn 0x1bbbbbbb;
650 else // (arg >> 28) == 2?
651 // Old, too specific check: if (buttonStatus != (arg & 0x0FFFFFFF)) // cheat code likes: 0xD00000nn 0x3bbbbbbb;
652 if ((buttonStatus
& mask
) == mask
) // cheat code likes: 0xD00000nn 0x3bbbbbbb;
658 else if ((arg
>> 28) == 0x4 || (arg
>> 28) == 0x5 || (arg
>> 28) == 0x6 || (arg
>> 28) == 0x7) {
659 int addr1
= GetAddress(comm
& 0x0FFFFFFF);
660 int addr2
= GetAddress(arg
& 0x0FFFFFFF);
661 code
= GetNextCode();
662 if (code
.size() >= 2)
663 if (Memory::IsValidAddress(addr1
) && Memory::IsValidAddress(addr2
)) {
666 int skip
= (comm2
& 0xFFFFFFFF);
667 int memoryValue1
= 0;
668 int memoryValue2
= 0;
669 switch (arg2
& 0xF) {
671 memoryValue1
= Memory::Read_U8(addr1
);
672 memoryValue2
= Memory::Read_U8(addr2
);
675 memoryValue1
= Memory::Read_U16(addr1
);
676 memoryValue2
= Memory::Read_U16(addr2
);
679 memoryValue1
= Memory::Read_U32(addr1
);
680 memoryValue2
= Memory::Read_U32(addr2
);
687 if (memoryValue1
!= memoryValue2
)
690 case 0x5: // Not Equal
691 if (memoryValue1
== memoryValue2
)
694 case 0x6: // Less Than
695 if (memoryValue1
>= memoryValue2
)
698 case 0x7: // Greater Than
699 if (memoryValue1
<= memoryValue2
)
709 case 0xE: // Test commands, multiple skip
711 bool is8Bit
= (comm
>> 24) == 0xE1;
712 addr
= GetAddress(arg
& 0x0FFFFFFF);
713 if (Memory::IsValidAddress(addr
)) {
714 int memoryValue
= is8Bit
? Memory::Read_U8(addr
) : Memory::Read_U16(addr
);
715 int testValue
= comm
& (is8Bit
? 0xFF : 0xFFFF);
716 bool executeNextLines
= false;
717 switch ( arg
>> 28) {
719 executeNextLines
= memoryValue
== testValue
;
721 case 0x1: // Not Equal
722 executeNextLines
= memoryValue
!= testValue
;
724 case 0x2: // Less Than
725 executeNextLines
= memoryValue
< testValue
;
727 case 0x3: // Greater Than
728 executeNextLines
= memoryValue
> testValue
;
731 if (!executeNextLines
) {
732 int skip
= (comm
>> 16) & (is8Bit
? 0xFF : 0xFFF);
749 bool CWCheatEngine::HasCheats() {
750 return !parts
.empty();
753 bool CheatsInEffect() {
754 if (!cheatEngine
|| !cheatsEnabled
)
756 return cheatEngine
->HasCheats();