Last active
May 15, 2016 20:37
-
-
Save Wunkolo/86725141c0fcc35916f1 to your computer and use it in GitHub Desktop.
Action Replay code snippets
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Parse Action Replay DS Code | |
#include <string> | |
#include <vector> | |
#define STR(x) # x | |
enum Button | |
{ | |
A = 0xFFFE, | |
B = 0xFFFD, | |
Select = 0xFFFB, | |
Start = 0xFFF7, | |
Right = 0xFFEF, | |
Left = 0xFFDF, | |
Up = 0xFFBF, | |
Down = 0xFF7F, | |
RT = 0xFEFF, | |
LT = 0xFDFF | |
}; | |
struct ARCode | |
{ | |
ARCode() : | |
Command(0), | |
Parameters(0) | |
{ | |
} | |
unsigned int Command, Parameters; | |
}; | |
bool ParseARLine(const char* str, ARCode& Code) | |
{ | |
const char HexDigits[] = "0123456789ABCDEF"; | |
const char WhiteSpace[] = " \t\n\v\f\r"; | |
ARCode TempCode; | |
//skip whitespace | |
str = strpbrk(str, HexDigits); | |
if( !str ) | |
{ | |
//No Hex Digits found | |
return false; | |
} | |
for( size_t i = 0; i < 8; i++ ) | |
{ | |
if( strchr(HexDigits, *str) ) | |
{ | |
unsigned int Digit; | |
// Parse Hex Digit | |
sscanf(str, "%1x", &Digit); | |
TempCode.Command <<= 4; | |
TempCode.Command |= Digit; | |
str++; | |
} | |
else if( strchr(WhiteSpace, *str) ) | |
{ | |
//Invalid code length | |
return false; | |
} | |
else | |
{ | |
//Invalid hex digit found | |
return false; | |
} | |
} | |
//Parse Parameter | |
//skip whitespace | |
str = strpbrk(str, HexDigits); | |
for( size_t i = 0; i < 8; i++ ) | |
{ | |
if( strchr(HexDigits, *str) ) | |
{ | |
unsigned int Digit; | |
// Parse Hex Digit | |
sscanf(str, "%1x", &Digit); | |
TempCode.Parameters <<= 4; | |
TempCode.Parameters |= Digit; | |
str++; | |
} | |
else if( strchr(WhiteSpace, *str) ) | |
{ | |
//Invalid code length | |
return false; | |
} | |
else | |
{ | |
//Invalid hex digit found | |
return false; | |
} | |
} | |
} | |
int main() | |
{ | |
const char Code1[] = | |
" 94000130 FFFB0000\n" | |
"022340C8 03840074" | |
"022340C8 03840074\n"; | |
const char Code[] = | |
" 94000l30 FFFB0000\n" | |
"022340C8 03840074\n" | |
"022340CC 03840075\n" | |
"022340D0 03840076\n" | |
"022340D4 03840077\n" | |
"02234364 0384023C\n" | |
"02234368 0384023D\n" | |
"0223436C 0384023E\n" | |
"02234370 0384023F\n" | |
"02234374 03840240\n" | |
"02234378 03840241\n" | |
"D2000000 00000000\n" | |
"94000130 FFFB0000\n" | |
"D5000000 03840001\n" | |
"C0000000 0000000F\n" | |
"D6000000 02233FCC\n" | |
"D4000000 00000001\n" | |
"D2000000 00000000\n" | |
"94000130 FFFB0000\n" | |
"D5000000 03840041\n" | |
"C0000000 0000002E\n" | |
"D6000000 0223400C\n" | |
"D4000000 00000001\n" | |
"D2000000 00000000\n" | |
"94000130 FFFB0000\n" | |
"D5000000 03840087\n" | |
"C0000000 0000000C\n" | |
"D6000000 022340D8\n" | |
"D4000000 00000001\n" | |
"D2000000 00000000\n" | |
"94000130 FFFB0000\n" | |
"D5000000 038400D5\n" | |
"C0000000 00000071\n" | |
"D6000000 0223410C\n" | |
"D4000000 00000001\n" | |
"D2000000 00000000\n" | |
"94000130 FFFB0000\n" | |
"D5000000 038401EC\n" | |
"C0000000 00000008\n" | |
"D6000000 022342D4\n" | |
"D4000000 00000001\n" | |
"D2000000 00000000\n" | |
"94000130 FFFB0000\n" | |
"D5000000 03840219\n" | |
"C0000000 0000001A\n" | |
"D6000000 022342F8\n" | |
"D4000000 00000001\n" | |
"D2000000 00000000\n" | |
"94000130 FFFB0000\n" | |
"D5000000 03840244\n" | |
"C0000000 0000000A\n" | |
"D6000000 0223437C\n" | |
"D4000000 00000001\n" | |
"D2000000 00000000\n"; | |
std::vector<ARCode> Codes; | |
std::size_t LineCount = 0; | |
ARCode CheatLine; | |
const char *CurLine; | |
CurLine = Code; | |
//Parse code line by line | |
while( ParseARLine(CurLine, CheatLine) ) | |
{ | |
} | |
do | |
{ | |
LineCount++; | |
//Parse Command | |
Codes.push_back(CheatLine); | |
// Next code pair lead-in | |
CurLine += strspn(CurLine, "\n"); | |
} while( CurLine ); | |
for( ARCode cheat : Codes ) | |
{ | |
printf("-> %08X:%08X | ", cheat.Command, cheat.Parameters); | |
switch( cheat.Command >> 28 ) | |
{ | |
//Constant RAM Writes | |
case 0: | |
{ | |
printf("[%08X + $Off] = %08X", | |
cheat.Command & 0x0FFFFFFF, | |
cheat.Parameters); | |
break; | |
} | |
case 1: | |
{ | |
printf("[%08X + $Off] = %08X", | |
cheat.Command & 0x0FFFFFFF, | |
cheat.Parameters & 0xFFFF); | |
break; | |
} | |
case 2: | |
{ | |
printf("[%08X + $Off] = %08X", | |
cheat.Command & 0x0FFFFFFF, | |
cheat.Parameters & 0xFF); | |
break; | |
} | |
//Conditional 32 bit | |
case 3: | |
{ | |
printf("if ( [%08X] > %08X )", | |
cheat.Command & 0x0FFFFFFF, cheat.Parameters); | |
break; | |
} | |
case 4: | |
{ | |
printf("if ( [%08X] > %08X )", | |
cheat.Command & 0x0FFFFFFF, cheat.Parameters); | |
break; | |
} | |
case 5: | |
{ | |
printf("if ( [%08X] == %08X )", | |
cheat.Command & 0x0FFFFFFF, cheat.Parameters); | |
break; | |
} | |
case 6: | |
{ | |
printf("if ( [%08X] != %08X )", | |
cheat.Command & 0x0FFFFFFF, cheat.Parameters); | |
break; | |
} | |
//Conditional 16 bit | |
case 7: | |
{ | |
printf("if ( [%08X] < %04X & 0x04X )", | |
cheat.Command & 0x0FFFFFFF, cheat.Parameters >> 16, | |
cheat.Parameters & 0xFFFF); | |
break; | |
} | |
case 8: | |
{ | |
printf("if ( [%08X] > %04X & 0x04X )", | |
cheat.Command & 0x0FFFFFFF, cheat.Parameters >> 16, | |
cheat.Parameters & 0xFFFF); | |
break; | |
} | |
case 9: | |
{ | |
printf("if ( [%08X] == %04X )", | |
cheat.Command & 0x0FFFFFFF, cheat.Parameters >> 16); | |
if( (cheat.Command & 0x0FFFFFFF) == 0x04000130 ) | |
{ | |
printf(" Button pressed: "); | |
switch( cheat.Parameters >> 16 ) | |
{ | |
case A: | |
{ | |
printf("A"); | |
break; | |
} | |
case B: | |
{ | |
printf("B"); | |
break; | |
} | |
case Select: | |
{ | |
printf("Select"); | |
break; | |
} | |
case Start: | |
{ | |
printf("Start"); | |
break; | |
} | |
case Right: | |
{ | |
printf("Right"); | |
break; | |
} | |
case Left: | |
{ | |
printf("Left"); | |
break; | |
} | |
case Up: | |
{ | |
printf("Up"); | |
break; | |
} | |
case Down: | |
{ | |
printf("Down"); | |
break; | |
} | |
case RT: | |
{ | |
printf("Right Trigger"); | |
break; | |
} | |
case LT: | |
{ | |
printf("Left Trigger"); | |
break; | |
} | |
default: | |
printf("Unknown Key"); | |
break; | |
} | |
} | |
break; | |
} | |
case 0xA: | |
{ | |
printf("if ( [%08X] != %04X )", | |
cheat.Command & 0x0FFFFFFF, cheat.Parameters >> 16); | |
break; | |
} | |
//Offset Code | |
case 0xB: | |
{ | |
printf("$Off = [%08X + $Off]", | |
cheat.Command & 0x0FFFFFFF); | |
break; | |
} | |
//Loop | |
case 0xC: | |
{ | |
printf("loop ( %08X ) x%u", | |
cheat.Parameters, cheat.Parameters); | |
break; | |
} | |
//Data | |
case 0xD: | |
{ | |
switch( (cheat.Command >> 24) & 0xF ) | |
{ | |
case 0x0: | |
{ | |
printf("Terminate Segment"); | |
break; | |
} | |
case 0x1: | |
{ | |
printf("Loop execute"); | |
break; | |
} | |
case 0x2: | |
{ | |
printf("Segment End"); | |
break; | |
} | |
case 0x3: | |
{ | |
printf("$Off = %08X", cheat.Parameters); | |
break; | |
} | |
case 0x4: | |
{ | |
printf("$Data += %08X", cheat.Parameters); | |
break; | |
} | |
case 0x5: | |
{ | |
printf("$Data = %08X", cheat.Parameters); | |
break; | |
} | |
case 0x6: | |
{ | |
printf("32-bit [%08X + $Off] = $Data. $Off += 4", | |
cheat.Parameters); | |
break; | |
} | |
case 0x7: | |
{ | |
printf("16-bit [%08X + $Off] = $Data. $Off += 2", | |
cheat.Parameters); | |
break; | |
} | |
case 0x8: | |
{ | |
printf("8-bit [%08X + $Off] = $Data. $Off += 1", | |
cheat.Parameters); | |
break; | |
} | |
case 0x9: | |
{ | |
printf("32-bit $Data = [%08X + $Off]", | |
cheat.Parameters); | |
break; | |
} | |
case 0xA: | |
{ | |
printf("16-bit $Data = [%08X + $Off]", | |
cheat.Parameters); | |
break; | |
} | |
case 0xB: | |
{ | |
printf("8-bit $Data = [%08X + $Off] !Bugged!", | |
cheat.Parameters); | |
break; | |
} | |
case 0xC: | |
{ | |
printf("$Off += %08X", cheat.Parameters); | |
break; | |
} | |
default: | |
break; | |
} | |
break; | |
} | |
//Patch Code | |
case 0xE: | |
{ | |
break; | |
} | |
//Memory Copy | |
case 0xF: | |
{ | |
break; | |
} | |
default: | |
{ | |
break; | |
} | |
} | |
printf("\n"); | |
} | |
int _c = getchar(); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <iostream> | |
#include <iomanip> | |
// Encryption seeds for Pro Action Replay V3/4 | |
const uint32_t const Seeds[4] = { | |
0x7AA9648F, | |
0x7FAE6994, | |
0xC0EFAAD5, | |
0x42712C57 }; | |
struct ARInstruction | |
{ | |
uint32_t Opcode; | |
uint32_t Operand; | |
}; | |
ARInstruction Encrypt(ARInstruction Code) | |
{ | |
for( size_t i = 1; i <= 32; i++ ) | |
{ | |
Code.Opcode += (Code.Operand * 16 + Seeds[0]) ^ (Code.Operand + 0x9E3779B9 * i) ^ ((Code.Operand >> 5) + Seeds[1]); | |
Code.Operand += (Code.Opcode * 16 + Seeds[2]) ^ (Code.Opcode + 0x9E3779B9 * i) ^ ((Code.Opcode >> 5) + Seeds[3]); | |
} | |
return Code; | |
} | |
ARInstruction Decrypt(ARInstruction Code) | |
{ | |
for( size_t i = 32; i > 0; i-- ) | |
{ | |
Code.Operand -= (Code.Opcode * 16 + Seeds[2]) ^ (Code.Opcode + 0x9E3779B9 * i) ^ ((Code.Opcode >> 5) + Seeds[3]); | |
Code.Opcode -= (Code.Operand * 16 + Seeds[0]) ^ (Code.Operand + 0x9E3779B9 * i) ^ ((Code.Operand >> 5) + Seeds[1]); | |
} | |
return Code; | |
} | |
int main() | |
{ | |
// The encrypted AR code we're trying to decrypt | |
ARInstruction Code[] = { | |
{ 0xD8BAE4D9, 0x4864DCE5 }, | |
{ 0xA86CDBA5, 0x19BA49B3 }, | |
}; | |
// Decrypt each action replay code-instruction | |
for( size_t i = 0; i < (sizeof(Code) / sizeof(ARInstruction)); i++ ) | |
{ | |
Code[i] = Decrypt(Code[i]); | |
} | |
// Print decrypted code | |
std::cout << std::setfill('0') << std::hex << std::uppercase; | |
for( size_t i = 0; i < (sizeof(Code) / sizeof(ARInstruction)); i++ ) | |
{ | |
std::cout << std::setw(8) << Code[i].Opcode << ' ' << std::setw(8) << Code[i].Operand << std::endl; | |
} | |
std::cin.get(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment