From 2c837223756de2596931c22c8f4fa2ba4a4237a9 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Tue, 11 Jul 2017 21:09:56 -0400 Subject: Fixed indentation --- .gitignore | 1 + gba/source/gamedata.c | 20 +-- gba/source/link.c | 6 +- gba/source/main.c | 12 +- source/encoding.c | 12 +- source/main.c | 486 +++++++++++++++++++++++++------------------------- 6 files changed, 268 insertions(+), 269 deletions(-) diff --git a/.gitignore b/.gitignore index ac7cf98..9f62bc6 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ data tags *.o *.d +*.swp diff --git a/gba/source/gamedata.c b/gba/source/gamedata.c index 6868b2b..bbcf4dd 100644 --- a/gba/source/gamedata.c +++ b/gba/source/gamedata.c @@ -244,11 +244,11 @@ bool initSaveData( break; } - /// --- FR/LG --- - // In FR/LG, the function that initialises the save-block pointers to - // default does not set up saveblock3. Which will need to be set up before - // loading the save if we want boxed Pokémon to not disappear. Oh, and - // loadsave() offset is different between FR and LG... + /// --- FR/LG --- + // In FR/LG, the function that initialises the save-block pointers to + // default does not set up saveblock3. Which will need to be set up before + // loading the save if we want boxed Pokémon to not disappear. Oh, and + // loadsave() offset is different between FR and LG... case 'DRPB': // FireRed German case 'DGPB': // LeafGreen German @@ -401,11 +401,11 @@ bool initSaveData( break; } - /// --- Emerald --- - // In Emerald, the saveblock pointer that isn't set up is saveblock1 (in - // FR/LG it was saveblock3). The initial save loading code after the - // copyright screen is also updated, now it sets up ASLR/crypto here before - // loading the save. + /// --- Emerald --- + // In Emerald, the saveblock pointer that isn't set up is saveblock1 (in + // FR/LG it was saveblock3). The initial save loading code after the + // copyright screen is also updated, now it sets up ASLR/crypto here before + // loading the save. case 'DEPB': // Emerald German { diff --git a/gba/source/link.c b/gba/source/link.c index c84e44d..acadf3b 100644 --- a/gba/source/link.c +++ b/gba/source/link.c @@ -12,8 +12,8 @@ void initializeLink() { - REG_HS_CTRL |= JOY_RW; - REG_JOYTR = 0; + REG_HS_CTRL |= JOY_RW; + REG_JOYTR = 0; while ((REG_HS_CTRL & JOY_WRITE) == 0); REG_HS_CTRL |= JOY_RW; } @@ -22,7 +22,7 @@ void waitForAck() { while ((REG_HS_CTRL & JOY_WRITE) == 0); REG_HS_CTRL |= JOY_RW; - REG_JOYTR = 0; + REG_JOYTR = 0; while ((REG_HS_CTRL & JOY_WRITE) == 0); REG_HS_CTRL |= JOY_RW; } diff --git a/gba/source/main.c b/gba/source/main.c index 9f97324..6207685 100644 --- a/gba/source/main.c +++ b/gba/source/main.c @@ -10,7 +10,7 @@ int main(void) { - initializeLink(); + initializeLink(); // Identify the host game. if (GAME_RUBY) @@ -30,9 +30,9 @@ int main(void) sendS32(5); } else { sendS32(-1); - waitForAck(); + waitForAck(); - return 0; + return 0; } waitForAck(); @@ -46,9 +46,9 @@ int main(void) { // Unsupported game version. sendS32(-1); - waitForAck(); + waitForAck(); - return 0; + return 0; } sendS32(1); @@ -105,6 +105,4 @@ int main(void) sendU32(tti); waitForAck(); - - // Halt(); } diff --git a/source/encoding.c b/source/encoding.c index 7b70df2..0be1e0b 100644 --- a/source/encoding.c +++ b/source/encoding.c @@ -10,14 +10,14 @@ #include "encoding.h" const char charmap[] = { - ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '?', '.', '-', ' ', - ' ', '\"', '\"', '\'', '\'', '*', '*', ' ', ',', ' ', '/', 'A', 'B', 'C', 'D', 'E', - 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', - 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', - 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', ' ' + ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '?', '.', '-', ' ', + ' ', '\"', '\"', '\'', '\'', '*', '*', ' ', ',', ' ', '/', 'A', 'B', 'C', 'D', 'E', + 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', + 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', + 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', ' ' }; char debugGen3Decode(u8 val) { - return charmap[val - 0xA0]; + return charmap[val - 0xA0]; } diff --git a/source/main.c b/source/main.c index 8a9e672..128feb9 100644 --- a/source/main.c +++ b/source/main.c @@ -27,7 +27,7 @@ void printmain() printf("\x1b[2J"); printf("\x1b[37m"); printf("Pokemon Gen III Data Extractor by hatkirby\n"); - printf("Based on gba-gen3multiboot by slipstream/RoL\n"); + printf("Based on gba-gen3multiboot by slipstream/RoL\n"); printf("Based on GBA Link Cable Dumper v1.6 by FIX94\n"); } @@ -47,21 +47,21 @@ void acb(s32 res, u32 val) unsigned int docrc(u32 crc,u32 val) { - u32 result; - - result = val ^ crc; - for (int i = 0; i < 0x20; i++) - { - if (result & 1) - { - result >>= 1; - result ^= 0xA1C1; - } else { - result >>= 1; - } - } - - return result; + u32 result; + + result = val ^ crc; + for (int i = 0; i < 0x20; i++) + { + if (result & 1) + { + result >>= 1; + result ^= 0xA1C1; + } else { + result >>= 1; + } + } + + return result; } void doreset() @@ -84,7 +84,7 @@ void getstatus() void endproc() { - doreset(); + doreset(); printf("Start pressed, exit\n"); VIDEO_WaitVSync(); VIDEO_WaitVSync(); @@ -98,8 +98,8 @@ u32 recv() transval = 0; SI_Transfer(1, cmdbuf, 1, resbuf, 5, transcb, SI_TRANS_DELAY); - while (transval == 0); - printf("%08lx\n", *(vu32*)resbuf); + while (transval == 0); + printf("%08lx\n", *(vu32*)resbuf); return *(vu32*)resbuf; } @@ -137,113 +137,113 @@ void fatalError(char *msg) u32 genKeyA() { - u32 retries = 0; - - for (;;) - { - u32 key = 0; - - if (retries > 32) - { - key = 0xDD654321; - } else { - key = (rand() & 0x00ffffff) | 0xDD000000; - } - - u32 unk = (key % 2 != 0); - u32 v12 = key; - for (u32 v13 = 1; v13 < 32; v13++) - { - v12 >>= 1; - unk += (v12 % 2 != 0); - } - - if ((unk >= 10 && unk <= 24)) - { - if (retries > 4) - { - printf("KeyA retries = %ld", retries); - } - - printf("KeyA = 0x%08lx\n", key); - - return key; - } - - retries++; - } + u32 retries = 0; + + for (;;) + { + u32 key = 0; + + if (retries > 32) + { + key = 0xDD654321; + } else { + key = (rand() & 0x00ffffff) | 0xDD000000; + } + + u32 unk = (key % 2 != 0); + u32 v12 = key; + for (u32 v13 = 1; v13 < 32; v13++) + { + v12 >>= 1; + unk += (v12 % 2 != 0); + } + + if ((unk >= 10 && unk <= 24)) + { + if (retries > 4) + { + printf("KeyA retries = %ld", retries); + } + + printf("KeyA = 0x%08lx\n", key); + + return key; + } + + retries++; + } } u32 checkKeyB(u32 KeyBRaw) { - if ((KeyBRaw & 0xFF) != 0xEE) - { - printf("Invalid KeyB - lowest 8 bits should be 0xEE, actually 0x%02x\n", - ((u8)(KeyBRaw))); + if ((KeyBRaw & 0xFF) != 0xEE) + { + printf("Invalid KeyB - lowest 8 bits should be 0xEE, actually 0x%02x\n", + ((u8)(KeyBRaw))); - return 0; - } + return 0; + } - u32 KeyB = KeyBRaw & 0xffffff00; - u32 val = KeyB; - u32 unk = (val < 0); - for (u32 i = 1; i < 24; i++) - { - val <<= 1; - unk += (val < 0); - } + u32 KeyB = KeyBRaw & 0xffffff00; + u32 val = KeyB; + u32 unk = (val < 0); + for (u32 i = 1; i < 24; i++) + { + val <<= 1; + unk += (val < 0); + } - if (unk > 14) - { - printf("Invalid KeyB - high 24 bits bad: 0x%08lx\n", KeyB); + if (unk > 14) + { + printf("Invalid KeyB - high 24 bits bad: 0x%08lx\n", KeyB); - return 0; - } + return 0; + } - printf("Valid KeyB: 0x%08lx\n", KeyB); + printf("Valid KeyB: 0x%08lx\n", KeyB); - return KeyB; + return KeyB; } u32 deriveKeyC(u32 keyCderive, u32 kcrc) { - u32 keyc = 0; - u32 keyCi = 0; + u32 keyc = 0; + u32 keyCi = 0; - do - { - u32 v5 = 0x1000000 * keyCi - 1; - u32 keyCattempt = docrc(kcrc,v5); + do + { + u32 v5 = 0x1000000 * keyCi - 1; + u32 keyCattempt = docrc(kcrc,v5); - if (keyCderive == keyCattempt) - { - keyc = v5; + if (keyCderive == keyCattempt) + { + keyc = v5; - printf("Found keyC: %08lx\n",keyc); + printf("Found keyC: %08lx\n",keyc); - return keyc; - } + return keyc; + } - keyCi++; - } while (keyCi < 256); + keyCi++; + } while (keyCi < 256); - return keyc; + return keyc; } u32 getMsg() { u32 val = 0; - while (val == 0) - { - val = __builtin_bswap32(recv()); - sleep(1); - } + while (val == 0) + { + val = __builtin_bswap32(recv()); + sleep(1); + } send(0); - while (recv()!=0) {sleep(1);}; - send(0); + while (recv()!=0) {sleep(1);}; + send(0); - return val; + return val; } int main(int argc, char *argv[]) @@ -272,11 +272,11 @@ int main(int argc, char *argv[]) { printmain(); - printf("Press A to begin, press Start to quit.\n"); - if (waitForButtons(PAD_BUTTON_A | PAD_BUTTON_START) & PAD_BUTTON_START) - { - endproc(); - } + printf("Press A to begin, press Start to quit.\n"); + if (waitForButtons(PAD_BUTTON_A | PAD_BUTTON_START) & PAD_BUTTON_START) + { + endproc(); + } printf("Waiting for a GBA in port 2...\n"); resval = 0; @@ -300,7 +300,7 @@ int main(int argc, char *argv[]) VIDEO_WaitVSync(); if (PAD_ButtonsHeld(0) & PAD_BUTTON_START) { - getstatus(); + getstatus(); endproc(); } } @@ -309,139 +309,139 @@ int main(int argc, char *argv[]) { printf("GBA Found! Waiting on BIOS\n"); - resbuf[2]=0; - - // wait for the BIOS to hand over to the game - do - { - doreset(); - } while (!(resbuf[1] > 4)); - - printf("BIOS handed over to game, waiting on game\n"); - - do - { - doreset(); - } while ((resbuf[0] != 0) || !(resbuf[2] & 0x10)); - - // receive the game-code from GBA side. - u32 gamecode = recv(); - - printf("Ready, sending multiboot ROM\n"); - - unsigned int sendsize = ((gba_mb_gba_size+7)&~7); - - // generate KeyA - unsigned int ourkey = genKeyA(); - - //printf("Our Key: %08x\n", ourkey); - printf("Sending game code that we got: 0x%08lx\n", - __builtin_bswap32(gamecode)); - - // send the game code back, then KeyA. - send(__builtin_bswap32(gamecode)); - send(ourkey); - - // get KeyB from GBA, check it to make sure its valid, then xor with KeyA - // to derive the initial CRC value and the sessionkey. - u32 sessionkeyraw = 0; - do - { - sessionkeyraw = recv(); - } while (sessionkeyraw == gamecode); - - sessionkeyraw = checkKeyB(__builtin_bswap32(sessionkeyraw)); - if (sessionkeyraw == 0) - { - warnError("Cannot continue.\n"); - - continue; - } - - u32 sessionkey = sessionkeyraw ^ ourkey; - u32 kcrc = sessionkey; - printf("start kCRC=%08lx\n",kcrc); - - sessionkey = (sessionkey*0x6177614b)+1; - - // send hacked up send-size in uint32s - u32 hackedupsize = (sendsize >> 3) - 1; - - printf("Sending hacked up size 0x%08lx\n",hackedupsize); - send(hackedupsize); - - //unsigned int fcrc = 0x00bb; - // send over multiboot binary header, in the clear until the end of the - // nintendo logo. GBA checks this, if nintendo logo does not match the - // one in currently inserted cart's ROM, it will not accept any more data. - for (int i = 0; i < 0xA0; i+=4) - { - vu32 rom_dword = *(vu32*)(gba_mb_gba+i); - send(__builtin_bswap32(rom_dword)); - } - - printf("\n"); - printf("Header done! Sending ROM...\n"); - - // Add each uint32 of the multiboot image to the checksum, encrypt the - // uint32 with the session key, increment the session key, send the - // encrypted uint32. - for (int i = 0xA0; i < sendsize; i+=4) - { - u32 dec = ( - (((gba_mb_gba[i+3]) << 24) & 0xff000000) | - (((gba_mb_gba[i+2]) << 16) & 0x00ff0000) | - (((gba_mb_gba[i+1]) << 8) & 0x0000ff00) | - (((gba_mb_gba[i]) << 0) & 0x000000ff) - ); - - u32 enc = (dec - kcrc) ^ sessionkey; - kcrc = docrc(kcrc,dec); - sessionkey = (sessionkey * 0x6177614B) + 1; - //enc^=((~(i+(0x20<<20)))+1); - //enc^=0x6f646573;//0x20796220; - - send(enc); - } - - //fcrc |= (sendsize<<16); - printf("ROM done! CRC: %08lx\n", kcrc); - //get crc back (unused) - - // Get KeyC derivation material from GBA (eventually) - u32 keyCderive = 0; - do - { - keyCderive = recv(); - } while (keyCderive <= 0xfeffffff); - - keyCderive = __builtin_bswap32(keyCderive); - keyCderive >>= 8; - - printf("KeyC derivation material: %08lx\n",keyCderive); - - // (try to) find the KeyC, using the checksum of the multiboot image, and - // the derivation material that GBA sent to us - u32 keyc = deriveKeyC(keyCderive,kcrc); - if (keyc == 0) - { - printf("Could not find keyC - kcrc=0x%08lx\n",kcrc); + resbuf[2]=0; + + // wait for the BIOS to hand over to the game + do + { + doreset(); + } while (!(resbuf[1] > 4)); + + printf("BIOS handed over to game, waiting on game\n"); + + do + { + doreset(); + } while ((resbuf[0] != 0) || !(resbuf[2] & 0x10)); + + // receive the game-code from GBA side. + u32 gamecode = recv(); + + printf("Ready, sending multiboot ROM\n"); + + unsigned int sendsize = ((gba_mb_gba_size+7)&~7); + + // generate KeyA + unsigned int ourkey = genKeyA(); + + //printf("Our Key: %08x\n", ourkey); + printf("Sending game code that we got: 0x%08lx\n", + __builtin_bswap32(gamecode)); + + // send the game code back, then KeyA. + send(__builtin_bswap32(gamecode)); + send(ourkey); + + // get KeyB from GBA, check it to make sure its valid, then xor with KeyA + // to derive the initial CRC value and the sessionkey. + u32 sessionkeyraw = 0; + do + { + sessionkeyraw = recv(); + } while (sessionkeyraw == gamecode); + + sessionkeyraw = checkKeyB(__builtin_bswap32(sessionkeyraw)); + if (sessionkeyraw == 0) + { warnError("Cannot continue.\n"); - continue; - } + continue; + } + + u32 sessionkey = sessionkeyraw ^ ourkey; + u32 kcrc = sessionkey; + printf("start kCRC=%08lx\n",kcrc); + + sessionkey = (sessionkey*0x6177614b)+1; + + // send hacked up send-size in uint32s + u32 hackedupsize = (sendsize >> 3) - 1; + + printf("Sending hacked up size 0x%08lx\n",hackedupsize); + send(hackedupsize); + + //unsigned int fcrc = 0x00bb; + // send over multiboot binary header, in the clear until the end of the + // nintendo logo. GBA checks this, if nintendo logo does not match the + // one in currently inserted cart's ROM, it will not accept any more data. + for (int i = 0; i < 0xA0; i+=4) + { + vu32 rom_dword = *(vu32*)(gba_mb_gba+i); + send(__builtin_bswap32(rom_dword)); + } + + printf("\n"); + printf("Header done! Sending ROM...\n"); - // derive the boot key from the found KeyC, and send to GBA. if this is + // Add each uint32 of the multiboot image to the checksum, encrypt the + // uint32 with the session key, increment the session key, send the + // encrypted uint32. + for (int i = 0xA0; i < sendsize; i+=4) + { + u32 dec = ( + (((gba_mb_gba[i+3]) << 24) & 0xff000000) | + (((gba_mb_gba[i+2]) << 16) & 0x00ff0000) | + (((gba_mb_gba[i+1]) << 8) & 0x0000ff00) | + (((gba_mb_gba[i]) << 0) & 0x000000ff) + ); + + u32 enc = (dec - kcrc) ^ sessionkey; + kcrc = docrc(kcrc,dec); + sessionkey = (sessionkey * 0x6177614B) + 1; + //enc^=((~(i+(0x20<<20)))+1); + //enc^=0x6f646573;//0x20796220; + + send(enc); + } + + //fcrc |= (sendsize<<16); + printf("ROM done! CRC: %08lx\n", kcrc); + //get crc back (unused) + + // Get KeyC derivation material from GBA (eventually) + u32 keyCderive = 0; + do + { + keyCderive = recv(); + } while (keyCderive <= 0xfeffffff); + + keyCderive = __builtin_bswap32(keyCderive); + keyCderive >>= 8; + + printf("KeyC derivation material: %08lx\n",keyCderive); + + // (try to) find the KeyC, using the checksum of the multiboot image, and + // the derivation material that GBA sent to us + u32 keyc = deriveKeyC(keyCderive,kcrc); + if (keyc == 0) + { + printf("Could not find keyC - kcrc=0x%08lx\n",kcrc); + warnError("Cannot continue.\n"); + + continue; + } + + // derive the boot key from the found KeyC, and send to GBA. if this is // not correct, GBA will not jump to the multiboot image it was sent. - u32 bootkey = docrc(0xBB,keyc) | 0xbb000000; - printf("BootKey = 0x%08lx\n",bootkey); + u32 bootkey = docrc(0xBB,keyc) | 0xbb000000; + printf("BootKey = 0x%08lx\n",bootkey); - send(bootkey); - sleep(2); + send(bootkey); + sleep(2); - printf("Waiting for GBA...\n"); - while (recv() != 0) {sleep(1);}; - send(0); + printf("Waiting for GBA...\n"); + while (recv() != 0) {sleep(1);}; + send(0); VIDEO_WaitVSync(); @@ -471,9 +471,9 @@ int main(int argc, char *argv[]) } printf("\n"); - VIDEO_WaitVSync(); + VIDEO_WaitVSync(); - u32 isValid = getMsg(); + u32 isValid = getMsg(); if (isValid == -1) { warnError("ERROR: Unsupported game version inserted!\n"); @@ -501,22 +501,22 @@ int main(int argc, char *argv[]) printf("Trainer: "); - for (int i = 0; i < 8; i++) - { - if (trainerName[i] == 0xFF) - { - break; - } else { - printf("%c", debugGen3Decode(trainerName[i])); - } - } + for (int i = 0; i < 8; i++) + { + if (trainerName[i] == 0xFF) + { + break; + } else { + printf("%c", debugGen3Decode(trainerName[i])); + } + } printf(" (%ld)\n", trainerId); // Wait for confirmation. printf("Press A to import the data from this game.\n"); printf("Press B to cancel.\n"); - VIDEO_WaitVSync(); + VIDEO_WaitVSync(); if (waitForButtons(PAD_BUTTON_A | PAD_BUTTON_B) & PAD_BUTTON_B) { -- cgit 1.4.1