/* * Copyright (C) 2017 hatkirby * Copyright (C) 2017 slipstream/RoL * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ #include "gamedata.h" static void decryptSaveStructures( pSaveBlock1 SaveBlock1, pSaveBlock2 SaveBlock2, pSaveBlock3 SaveBlock3) { if (GAME_RS) { // R/S doesn't have save crypto. return; } u8* sb1raw = (u8*)SaveBlock1; u8* sb2raw = (u8*)SaveBlock2; //u8* sb3raw = (u8*)SaveBlock3; // unused u32* xor_key_ptr = (u32*)(&sb2raw[( GAME_EM ? 0xA8 : 0xF20 )]); u32 xor_key = *xor_key_ptr; u16 xor_key16 = (u16)xor_key; if (!xor_key) { // xor key is zero, nothing needs to be done. return; } u32* ptr_to_xor; u32 save_offset; int i; u32* bag_pocket_offsets; u32* bag_pocket_counts; if (GAME_FRLG) { // loop over and decrypt various things save_offset = 0x3D38 + 4; for (i = 3; i >= 0; i--) { ptr_to_xor = (u32*)(&sb1raw[save_offset]); *ptr_to_xor ^= xor_key; save_offset += 12; } for (i = 0; i <= 0x3f; i++) { save_offset = 0x1200 + (i*sizeof(u32)); ptr_to_xor = (u32*)(&sb1raw[save_offset]); *ptr_to_xor ^= xor_key; } // loop over each of the bag pockets and decrypt decrypt decrypt bag_pocket_offsets = (u32[5]) { 0x310, 0x388, 0x430, 0x464, 0x54C }; bag_pocket_counts = (u32[5]) { 42, 30, 13, 58, 43 }; for (i = 0; i < 5; i++) { for (int bag_i = 0; bag_i < bag_pocket_counts[i]; bag_i++) { save_offset = bag_pocket_offsets[i] + (sizeof(u32) * bag_i) + 2; *(u16*)(&sb1raw[save_offset]) ^= xor_key16; } } // decrypt some more stuff save_offset = 0xaf8; ptr_to_xor = (u32*)(&sb1raw[save_offset]); *ptr_to_xor ^= xor_key; save_offset = 0x290; ptr_to_xor = (u32*)(&sb1raw[save_offset]); *ptr_to_xor ^= xor_key; save_offset = 0x294; *(u16*)(&sb1raw[save_offset]) ^= xor_key16; } else { // Emerald // loop over and decrypt various things for (i = 0; i <= 0x3f; i++) { save_offset = 0x159c + (i*sizeof(u32)); ptr_to_xor = (u32*)(&sb1raw[save_offset]); *ptr_to_xor ^= xor_key; } // loop over each of the bag pockets and decrypt decrypt decrypt bag_pocket_offsets = (u32[5]) { 0x560, 0x5D8, 0x650, 0x690, 0x790 }; bag_pocket_counts = (u32[5]) { 30, 30, 16, 64, 46 }; for (i = 0; i < 5; i++) { for (int bag_i = 0; bag_i < bag_pocket_counts[i]; bag_i++) { save_offset = bag_pocket_offsets[i] + (sizeof(u32) * bag_i) + 2; *(u16*)(&sb1raw[save_offset]) ^= xor_key16; } } // decrypt some more stuff save_offset = 0x1F4; ptr_to_xor = (u32*)(&sb1raw[save_offset]); *ptr_to_xor ^= xor_key; save_offset = 0x490; ptr_to_xor = (u32*)(&sb1raw[save_offset]); *ptr_to_xor ^= xor_key; save_offset = 0x494; *(u16*)(&sb1raw[save_offset]) ^= xor_key16; } *xor_key_ptr = 0; } static void CryptBoxPokemon(struct BoxPokemon* pkm) { for (u32 i = 0; i < 12; i++) { pkm->secure.raw[i] ^= (pkm->otId ^ pkm->personality); } } bool initSaveData(struct GameData* gameData) { // check the ROM code, make sure this game is supported. u8* ROM = (u8*) 0x8000000; u32 gamecode = (*(u32*)(&ROM[0xAC])); void(*loadsave)(char a1); //void(*mainloop)(); //void(*load_pokemon)(); pSaveBlock1 gSaveBlock1; pSaveBlock2 gSaveBlock2; pSaveBlock3 gSaveBlock3; //u32 titlemid = 0; // get the address of the save loading function. switch (gamecode) { // --- R/S --- case 'DVXA': // Ruby German case 'DPXA': // Sapphire German { // TODO: detect debug ROM? gSaveBlock1 = (pSaveBlock1) 0x2025734; gSaveBlock2 = (pSaveBlock2) 0x2024EA4; gSaveBlock3 = (pSaveBlock3) 0x20300A0; loadsave = (void(*)(char)) 0x8126249; // same for v1.0 + v1.1 //mainloop = (void(*)()) 0x80003D9; //load_pokemon = (void(*)()) 0x8047da9; break; } case 'FVXA': // Ruby French case 'FPXA': // Sapphire French { gSaveBlock1 = (pSaveBlock1) 0x2025734; gSaveBlock2 = (pSaveBlock2) 0x2024EA4; gSaveBlock3 = (pSaveBlock3) 0x20300A0; loadsave = (void(*)(char)) 0x8126351; // same for v1.0 + v1.1 //mainloop = (void(*)()) 0x80003D9; //load_pokemon = (void(*)()) 0x8047e95; break; } case 'IVXA': // Ruby Italian case 'IPXA': // Sapphire Italian { gSaveBlock1 = (pSaveBlock1) 0x2025734; gSaveBlock2 = (pSaveBlock2) 0x2024EA4; gSaveBlock3 = (pSaveBlock3) 0x20300A0; loadsave = (void(*)(char)) 0x8126249; // same for v1.0 + v1.1 //mainloop = (void(*)()) 0x80003D9; //load_pokemon = (void(*)()) 0x8047dbd; break; } case 'SVXA': // Ruby Spanish case 'SPXA': // Sapphire Spanish { gSaveBlock1 = (pSaveBlock1) 0x2025734; gSaveBlock2 = (pSaveBlock2) 0x2024EA4; gSaveBlock3 = (pSaveBlock3) 0x20300A0; loadsave = (void(*)(char)) 0x8126349; // same for v1.0 + v1.1 //mainloop = (void(*)()) 0x80003D9; //load_pokemon = (void(*)()) 0x8047ea5; break; } case 'EVXA': // Ruby English case 'EPXA': // Sapphire English {
name: "First Second Room"
panels {
name: "FIRS"
path: "Panels/First Second/panel"
clue: "firs"
answer: "first"
symbols: SPARKLES
}
panels {
name: "INITIAL"
path: "Panels/First Second/panel2"
clue: "initial"
answer: "first"
symbols: SUN
}
panels {
name: "MINUTE (1)"
path: "Panels/First Second/panel3"
clue: "minute"
answer: "second"
symbols: EXAMPLE
}
panels {
name: "MINUTE (2)"
path: "Panels/First Second/panel4"
clue: "minute"
answer: "second"
symbols: BOXES
}
ports {
name: "GREAT"
path: "Components/Warps/worldport"
}
ports {
name: "TTD"
path: "Components/Warps/worldport2"
}