about summary refs log tree commit diff stats
path: root/source
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2017-07-11 19:19:49 -0400
committerKelly Rauchenberger <fefferburbia@gmail.com>2017-07-11 19:19:49 -0400
commitd4eb5af332ce518baa552c886caa0bf3b2864f75 (patch)
tree469b3881a6fae4a203d97a4a00fec3b6b0f1d6ef /source
parentec66a022a8879a5300f2ae64cd86a5d8cfbd1a36 (diff)
downloadgen3uploader-d4eb5af332ce518baa552c886caa0bf3b2864f75.tar.gz
gen3uploader-d4eb5af332ce518baa552c886caa0bf3b2864f75.tar.bz2
gen3uploader-d4eb5af332ce518baa552c886caa0bf3b2864f75.zip
Major reformatting, cleaning up black magic
Diffstat (limited to 'source')
-rw-r--r--source/encoding.c9
-rw-r--r--source/encoding.h6
-rw-r--r--source/link.c6
-rw-r--r--source/link.h6
-rw-r--r--source/main.c825
5 files changed, 227 insertions, 625 deletions
diff --git a/source/encoding.c b/source/encoding.c index a69fc7e..7b70df2 100644 --- a/source/encoding.c +++ b/source/encoding.c
@@ -1,3 +1,12 @@
1/*
2 * Copyright (C) 2017 hatkirby
3 *
4 * This software may be modified and distributed under the terms
5 * of the MIT license. See the LICENSE file for details.
6 *
7 * Gen 3 proprietary encoding information from Bulbapedia:
8 * https://bulbapedia.bulbagarden.net/wiki/Character_encoding_in_Generation_III
9 */
1#include "encoding.h" 10#include "encoding.h"
2 11
3const char charmap[] = { 12const char charmap[] = {
diff --git a/source/encoding.h b/source/encoding.h index be99895..4dc3b1f 100644 --- a/source/encoding.h +++ b/source/encoding.h
@@ -1,3 +1,9 @@
1/*
2 * Copyright (C) 2017 hatkirby
3 *
4 * This software may be modified and distributed under the terms
5 * of the MIT license. See the LICENSE file for details.
6 */
1#ifndef ENCODING_H_95547384 7#ifndef ENCODING_H_95547384
2#define ENCODING_H_95547384 8#define ENCODING_H_95547384
3 9
diff --git a/source/link.c b/source/link.c index 7229191..4178293 100644 --- a/source/link.c +++ b/source/link.c
@@ -1,3 +1,9 @@
1/*
2 * Copyright (C) 2017 hatkirby
3 *
4 * This software may be modified and distributed under the terms
5 * of the MIT license. See the LICENSE file for details.
6 */
1#include "link.h" 7#include "link.h"
2 8
3u32 waitForButtons(u32 mask) 9u32 waitForButtons(u32 mask)
diff --git a/source/link.h b/source/link.h index 4e536b4..24a60b5 100644 --- a/source/link.h +++ b/source/link.h
@@ -1,3 +1,9 @@
1/*
2 * Copyright (C) 2017 hatkirby
3 *
4 * This software may be modified and distributed under the terms
5 * of the MIT license. See the LICENSE file for details.
6 */
1#ifndef _LINK_H_ 7#ifndef _LINK_H_
2#define _LINK_H_ 8#define _LINK_H_
3 9
diff --git a/source/main.c b/source/main.c index dfcdc3b..8a9e672 100644 --- a/source/main.c +++ b/source/main.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (C) 2017 hatkirby 2 * Copyright (C) 2017 hatkirby
3 * Copyright (C) 2017 slipstream/RoL
3 * Copyright (C) 2016 FIX94 4 * Copyright (C) 2016 FIX94
4 * 5 *
5 * This software may be modified and distributed under the terms 6 * This software may be modified and distributed under the terms
@@ -7,15 +8,10 @@
7 */ 8 */
8#include <gccore.h> 9#include <gccore.h>
9#include <stdio.h> 10#include <stdio.h>
10#include <malloc.h> 11#include <stdlib.h>
11#include <unistd.h> 12#include <unistd.h>
12#include <string.h> 13#include <string.h>
13#include <stdlib.h> 14#include <malloc.h>
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <fcntl.h>
17#include <dirent.h>
18#include <fat.h>
19#include "link.h" 15#include "link.h"
20#include "encoding.h" 16#include "encoding.h"
21 17
@@ -31,9 +27,8 @@ void printmain()
31 printf("\x1b[2J"); 27 printf("\x1b[2J");
32 printf("\x1b[37m"); 28 printf("\x1b[37m");
33 printf("Pokemon Gen III Data Extractor by hatkirby\n"); 29 printf("Pokemon Gen III Data Extractor by hatkirby\n");
30 printf("Based on gba-gen3multiboot by slipstream/RoL\n");
34 printf("Based on GBA Link Cable Dumper v1.6 by FIX94\n"); 31 printf("Based on GBA Link Cable Dumper v1.6 by FIX94\n");
35 printf("Save Support based on SendSave by Chishm\n");
36 printf("Save Structure based on gba-gen3multiboot by slipstream/RoL\n");
37} 32}
38 33
39u8 *resbuf,*cmdbuf; 34u8 *resbuf,*cmdbuf;
@@ -49,98 +44,24 @@ void acb(s32 res, u32 val)
49{ 44{
50 resval = val; 45 resval = val;
51} 46}
52/*
53unsigned int docrc(u32 crc, u32 val)
54{
55 int i;
56 for (i = 0; i < 0x20; i++)
57 {
58 if ((crc ^ val) & 1)
59 {
60 crc>>=1;
61 crc^=0xa1c1;
62 } else {
63 crc>>=1;
64 }
65
66 val>>=1;
67 }
68 47
69 return crc; 48unsigned int docrc(u32 crc,u32 val)
70}*/ 49{
71unsigned int docrc(u32 crc,u32 val) {
72 u32 result; 50 u32 result;
73 51
74 result = val ^ crc; 52 result = val ^ crc;
75 for (int i = 0; i < 0x20; i++) { 53 for (int i = 0; i < 0x20; i++)
76 if (result & 1) { 54 {
55 if (result & 1)
56 {
77 result >>= 1; 57 result >>= 1;
78 result ^= 0xA1C1; 58 result ^= 0xA1C1;
79 } else result >>= 1; 59 } else {
60 result >>= 1;
61 }
80 } 62 }
81 return result;
82}
83
84void fixFName(char *str)
85{
86 u8 i = 0;
87 for (i = 0; i < strlen(str); ++i)
88 {
89 if (str[i] < 0x20 || str[i] > 0x7F)
90 {
91 str[i] = '_';
92 } else {
93 switch (str[i])
94 {
95 case '\\':
96 case '/':
97 case ':':
98 case '*':
99 case '?':
100 case '\"':
101 case '<':
102 case '>':
103 case '|':
104 str[i] = '_';
105 break;
106 default:
107 break;
108 }
109 }
110 }
111}
112
113unsigned int calckey(unsigned int size)
114{
115 unsigned int ret = 0;
116 size= (size - 0x200) >> 3;
117 int res1 = (size & 0x3F80) << 1;
118 res1 |= (size & 0x4000) << 2;
119 res1 |= (size & 0x7F);
120 res1 |= 0x380000;
121 int res2 = res1;
122 res1 = res2 >> 0x10;
123 int res3 = res2 >> 8;
124 res3 += res1;
125 res3 += res2;
126 res3 <<= 24;
127 res3 |= res2;
128 res3 |= 0x80808080;
129
130 if ((res3 & 0x200) == 0)
131 {
132 ret |= (((res3) & 0xFF) ^ 0x4B) << 24;
133 ret |= (((res3>>8) & 0xFF) ^ 0x61) << 16;
134 ret |= (((res3>>16) & 0xFF) ^ 0x77) << 8;
135 ret |= (((res3>>24) & 0xFF) ^ 0x61);
136 } else {
137 ret |= (((res3) & 0xFF) ^ 0x73) << 24;
138 ret |= (((res3>>8) & 0xFF) ^ 0x65) << 16;
139 ret |= (((res3>>16) & 0xFF) ^ 0x64) << 8;
140 ret |= (((res3>>24) & 0xFF) ^ 0x6F);
141 }
142 63
143 return ret; 64 return result;
144} 65}
145 66
146void doreset() 67void doreset()
@@ -170,17 +91,6 @@ void endproc()
170 exit(0); 91 exit(0);
171} 92}
172 93
173void fsleep(int i)
174{
175 sleep(i);
176 /*PAD_ScanPads();
177 if (PAD_ButtonsDown(0) & PAD_BUTTON_START)
178 {
179 getstatus();
180 endproc();
181 }*/
182}
183
184u32 recv() 94u32 recv()
185{ 95{
186 memset(resbuf,0,32); 96 memset(resbuf,0,32);
@@ -208,29 +118,6 @@ void send(u32 msg)
208 while (transval == 0); 118 while (transval == 0);
209} 119}
210 120
211bool dirExists(const char *path)
212{
213 DIR *dir = opendir(path);
214 if (dir)
215 {
216 closedir(dir);
217
218 return true;
219 }
220
221 return false;
222}
223
224void createFile(const char *path, size_t size)
225{
226 int fd = open(path, O_WRONLY | O_CREAT);
227 if (fd >= 0)
228 {
229 ftruncate(fd, size);
230 close(fd);
231 }
232}
233
234void warnError(char *msg) 121void warnError(char *msg)
235{ 122{
236 puts(msg); 123 puts(msg);
@@ -248,64 +135,98 @@ void fatalError(char *msg)
248 exit(0); 135 exit(0);
249} 136}
250 137
251u32 genKeyA() { 138u32 genKeyA()
139{
252 u32 retries = 0; 140 u32 retries = 0;
253 while (true) { 141
142 for (;;)
143 {
254 u32 key = 0; 144 u32 key = 0;
255 if (retries > 32) { 145
146 if (retries > 32)
147 {
256 key = 0xDD654321; 148 key = 0xDD654321;
257 } else { 149 } else {
258 key = (rand() & 0x00ffffff) | 0xDD000000; 150 key = (rand() & 0x00ffffff) | 0xDD000000;
259 } 151 }
152
260 u32 unk = (key % 2 != 0); 153 u32 unk = (key % 2 != 0);
261 u32 v12 = key; 154 u32 v12 = key;
262 for (u32 v13 = 1; v13 < 32; v13++) { 155 for (u32 v13 = 1; v13 < 32; v13++)
156 {
263 v12 >>= 1; 157 v12 >>= 1;
264 unk += (v12 % 2 != 0); 158 unk += (v12 % 2 != 0);
265 } 159 }
266 if ((unk >= 10 && unk <= 24)) { 160
267 if (retries > 4) printf("KeyA retries = %ld",retries); 161 if ((unk >= 10 && unk <= 24))
268 printf("KeyA = 0x%08lx\n",key); 162 {
163 if (retries > 4)
164 {
165 printf("KeyA retries = %ld", retries);
166 }
167
168 printf("KeyA = 0x%08lx\n", key);
169
269 return key; 170 return key;
270 } 171 }
172
271 retries++; 173 retries++;
272 } 174 }
273} 175}
274 176
275u32 checkKeyB(u32 KeyBRaw) { 177u32 checkKeyB(u32 KeyBRaw)
276 if ((KeyBRaw & 0xFF) != 0xEE) { 178{
277 printf("Invalid KeyB - lowest 8 bits should be 0xEE, actually 0x%02x\n",((u8)(KeyBRaw))); 179 if ((KeyBRaw & 0xFF) != 0xEE)
180 {
181 printf("Invalid KeyB - lowest 8 bits should be 0xEE, actually 0x%02x\n",
182 ((u8)(KeyBRaw)));
183
278 return 0; 184 return 0;
279 } 185 }
186
280 u32 KeyB = KeyBRaw & 0xffffff00; 187 u32 KeyB = KeyBRaw & 0xffffff00;
281 u32 val = KeyB; 188 u32 val = KeyB;
282 u32 unk = (val < 0); 189 u32 unk = (val < 0);
283 for (u32 i = 1; i < 24; i++) { 190 for (u32 i = 1; i < 24; i++)
191 {
284 val <<= 1; 192 val <<= 1;
285 unk += (val < 0); 193 unk += (val < 0);
286 } 194 }
287 if (unk > 14) { 195
288 printf("Invalid KeyB - high 24 bits bad: 0x%08lx\n",KeyB); 196 if (unk > 14)
197 {
198 printf("Invalid KeyB - high 24 bits bad: 0x%08lx\n", KeyB);
199
289 return 0; 200 return 0;
290 } 201 }
291 printf("Valid KeyB: 0x%08lx\n",KeyB); 202
203 printf("Valid KeyB: 0x%08lx\n", KeyB);
204
292 return KeyB; 205 return KeyB;
293} 206}
294 207
295u32 deriveKeyC(u32 keyCderive, u32 kcrc) { 208u32 deriveKeyC(u32 keyCderive, u32 kcrc)
209{
296 u32 keyc = 0; 210 u32 keyc = 0;
297 u32 keyCi = 0; 211 u32 keyCi = 0;
298 do { 212
213 do
214 {
299 u32 v5 = 0x1000000 * keyCi - 1; 215 u32 v5 = 0x1000000 * keyCi - 1;
300 u32 keyCattempt = docrc(kcrc,v5); 216 u32 keyCattempt = docrc(kcrc,v5);
301 //printf("i = %d; keyCderive = %08x; keyCattempt = %08x\n",keyCi,keyCderive,keyCattempt); 217
302 if (keyCderive == keyCattempt) { 218 if (keyCderive == keyCattempt)
219 {
303 keyc = v5; 220 keyc = v5;
221
304 printf("Found keyC: %08lx\n",keyc); 222 printf("Found keyC: %08lx\n",keyc);
223
305 return keyc; 224 return keyc;
306 } 225 }
226
307 keyCi++; 227 keyCi++;
308 } while (keyCi < 256); 228 } while (keyCi < 256);
229
309 return keyc; 230 return keyc;
310} 231}
311 232
@@ -315,12 +236,13 @@ u32 getMsg()
315 while (val == 0) 236 while (val == 0)
316 { 237 {
317 val = __builtin_bswap32(recv()); 238 val = __builtin_bswap32(recv());
318 fsleep(1); 239 sleep(1);
319 } 240 }
241
320 send(0); 242 send(0);
321 while (recv()!=0) {fsleep(1);}; 243 while (recv()!=0) {sleep(1);};
322 send(0); 244 send(0);
323 245
324 return val; 246 return val;
325} 247}
326 248
@@ -345,33 +267,17 @@ int main(int argc, char *argv[])
345 PAD_Init(); 267 PAD_Init();
346 cmdbuf = memalign(32,32); 268 cmdbuf = memalign(32,32);
347 resbuf = memalign(32,32); 269 resbuf = memalign(32,32);
348 u8 *testdump = memalign(32,0x400000);
349 if(!testdump) return 0;
350 270
351 /*if (!fatInitDefault()) 271 for (;;)
352 { 272 {
353 printmain(); 273 printmain();
354 fatalError("ERROR: No usable device found to write dumped files to!");
355 }
356 274
357 mkdir("/dumps", S_IREAD | S_IWRITE);
358 if (!dirExists("/dumps"))
359 {
360 printmain();
361 fatalError("ERROR: Could not create dumps folder, make sure you have a supported device connected!");
362 }*/
363
364 int i;
365 while(1)
366 {
367 printmain();
368
369 printf("Press A to begin, press Start to quit.\n"); 275 printf("Press A to begin, press Start to quit.\n");
370 if (waitForButtons(PAD_BUTTON_A | PAD_BUTTON_START) & PAD_BUTTON_START) 276 if (waitForButtons(PAD_BUTTON_A | PAD_BUTTON_START) & PAD_BUTTON_START)
371 { 277 {
372 endproc(); 278 endproc();
373 } 279 }
374 280
375 printf("Waiting for a GBA in port 2...\n"); 281 printf("Waiting for a GBA in port 2...\n");
376 resval = 0; 282 resval = 0;
377 283
@@ -401,63 +307,86 @@ int main(int argc, char *argv[])
401 307
402 if (resval & SI_GBA) 308 if (resval & SI_GBA)
403 { 309 {
404 printf("GBA Found! Waiting on BIOS\n"); 310 printf("GBA Found! Waiting on BIOS\n");
311
405 resbuf[2]=0; 312 resbuf[2]=0;
406 //u32 oldresult = 0; 313
407 //u32 newresult = 0;
408 // wait for the BIOS to hand over to the game 314 // wait for the BIOS to hand over to the game
409 do { 315 do
316 {
410 doreset(); 317 doreset();
411
412 } while (!(resbuf[1] > 4)); 318 } while (!(resbuf[1] > 4));
319
413 printf("BIOS handed over to game, waiting on game\n"); 320 printf("BIOS handed over to game, waiting on game\n");
321
414 do 322 do
415 { 323 {
416 doreset(); 324 doreset();
417 } while((resbuf[0] != 0) || !(resbuf[2]&0x10)); 325 } while ((resbuf[0] != 0) || !(resbuf[2] & 0x10));
326
418 // receive the game-code from GBA side. 327 // receive the game-code from GBA side.
419 u32 gamecode = recv(); 328 u32 gamecode = recv();
329
420 printf("Ready, sending multiboot ROM\n"); 330 printf("Ready, sending multiboot ROM\n");
331
421 unsigned int sendsize = ((gba_mb_gba_size+7)&~7); 332 unsigned int sendsize = ((gba_mb_gba_size+7)&~7);
333
422 // generate KeyA 334 // generate KeyA
423 unsigned int ourkey = genKeyA(); 335 unsigned int ourkey = genKeyA();
336
424 //printf("Our Key: %08x\n", ourkey); 337 //printf("Our Key: %08x\n", ourkey);
425 printf("Sending game code that we got: 0x%08lx\n",__builtin_bswap32(gamecode)); 338 printf("Sending game code that we got: 0x%08lx\n",
339 __builtin_bswap32(gamecode));
340
426 // send the game code back, then KeyA. 341 // send the game code back, then KeyA.
427 send(__builtin_bswap32(gamecode)); 342 send(__builtin_bswap32(gamecode));
428 send(ourkey); 343 send(ourkey);
429 // get KeyB from GBA, check it to make sure its valid, then xor with KeyA to derive the initial CRC value and the sessionkey. 344
345 // get KeyB from GBA, check it to make sure its valid, then xor with KeyA
346 // to derive the initial CRC value and the sessionkey.
430 u32 sessionkeyraw = 0; 347 u32 sessionkeyraw = 0;
431 do { 348 do
349 {
432 sessionkeyraw = recv(); 350 sessionkeyraw = recv();
433 } while (sessionkeyraw == gamecode); 351 } while (sessionkeyraw == gamecode);
352
434 sessionkeyraw = checkKeyB(__builtin_bswap32(sessionkeyraw)); 353 sessionkeyraw = checkKeyB(__builtin_bswap32(sessionkeyraw));
435 if (sessionkeyraw == 0) 354 if (sessionkeyraw == 0)
436 { 355 {
437 warnError("Cannot continue.\n"); 356 warnError("Cannot continue.\n");
438 357
439 continue; 358 continue;
440 } 359 }
441 360
442 u32 sessionkey = sessionkeyraw ^ ourkey; 361 u32 sessionkey = sessionkeyraw ^ ourkey;
443 u32 kcrc = sessionkey; 362 u32 kcrc = sessionkey;
444 printf("start kCRC=%08lx\n",kcrc); 363 printf("start kCRC=%08lx\n",kcrc);
364
445 sessionkey = (sessionkey*0x6177614b)+1; 365 sessionkey = (sessionkey*0x6177614b)+1;
366
446 // send hacked up send-size in uint32s 367 // send hacked up send-size in uint32s
447 u32 hackedupsize = (sendsize >> 3) - 1; 368 u32 hackedupsize = (sendsize >> 3) - 1;
369
448 printf("Sending hacked up size 0x%08lx\n",hackedupsize); 370 printf("Sending hacked up size 0x%08lx\n",hackedupsize);
449 send(hackedupsize); 371 send(hackedupsize);
372
450 //unsigned int fcrc = 0x00bb; 373 //unsigned int fcrc = 0x00bb;
451 // send over multiboot binary header, in the clear until the end of the nintendo logo. 374 // send over multiboot binary header, in the clear until the end of the
452 // GBA checks this, if nintendo logo does not match the one in currently inserted cart's ROM, it will not accept any more data. 375 // nintendo logo. GBA checks this, if nintendo logo does not match the
453 for(i = 0; i < 0xA0; i+=4) { 376 // one in currently inserted cart's ROM, it will not accept any more data.
377 for (int i = 0; i < 0xA0; i+=4)
378 {
454 vu32 rom_dword = *(vu32*)(gba_mb_gba+i); 379 vu32 rom_dword = *(vu32*)(gba_mb_gba+i);
455 send(__builtin_bswap32(rom_dword)); 380 send(__builtin_bswap32(rom_dword));
456 } 381 }
382
457 printf("\n"); 383 printf("\n");
458 printf("Header done! Sending ROM...\n"); 384 printf("Header done! Sending ROM...\n");
459 // 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. 385
460 for(i = 0xA0; i < sendsize; i+=4) 386 // Add each uint32 of the multiboot image to the checksum, encrypt the
387 // uint32 with the session key, increment the session key, send the
388 // encrypted uint32.
389 for (int i = 0xA0; i < sendsize; i+=4)
461 { 390 {
462 u32 dec = ( 391 u32 dec = (
463 (((gba_mb_gba[i+3]) << 24) & 0xff000000) | 392 (((gba_mb_gba[i+3]) << 24) & 0xff000000) |
@@ -465,490 +394,136 @@ int main(int argc, char *argv[])
465 (((gba_mb_gba[i+1]) << 8) & 0x0000ff00) | 394 (((gba_mb_gba[i+1]) << 8) & 0x0000ff00) |
466 (((gba_mb_gba[i]) << 0) & 0x000000ff) 395 (((gba_mb_gba[i]) << 0) & 0x000000ff)
467 ); 396 );
397
468 u32 enc = (dec - kcrc) ^ sessionkey; 398 u32 enc = (dec - kcrc) ^ sessionkey;
469 kcrc=docrc(kcrc,dec); 399 kcrc = docrc(kcrc,dec);
470 sessionkey = (sessionkey*0x6177614B)+1; 400 sessionkey = (sessionkey * 0x6177614B) + 1;
471 //enc^=((~(i+(0x20<<20)))+1); 401 //enc^=((~(i+(0x20<<20)))+1);
472 //enc^=0x6f646573;//0x20796220; 402 //enc^=0x6f646573;//0x20796220;
403
473 send(enc); 404 send(enc);
474 } 405 }
406
475 //fcrc |= (sendsize<<16); 407 //fcrc |= (sendsize<<16);
476 printf("ROM done! CRC: %08lx\n", kcrc); 408 printf("ROM done! CRC: %08lx\n", kcrc);
477 //get crc back (unused) 409 //get crc back (unused)
410
478 // Get KeyC derivation material from GBA (eventually) 411 // Get KeyC derivation material from GBA (eventually)
479 u32 keyCderive = 0; 412 u32 keyCderive = 0;
480 do { 413 do
414 {
481 keyCderive = recv(); 415 keyCderive = recv();
482 } while (keyCderive <= 0xfeffffff); 416 } while (keyCderive <= 0xfeffffff);
417
483 keyCderive = __builtin_bswap32(keyCderive); 418 keyCderive = __builtin_bswap32(keyCderive);
484 keyCderive >>= 8; 419 keyCderive >>= 8;
485 printf("KeyC derivation material: %08lx\n",keyCderive);
486 420
487 // (try to) find the KeyC, using the checksum of the multiboot image, and the derivation material that GBA sent to us 421 printf("KeyC derivation material: %08lx\n",keyCderive);
488 422
423 // (try to) find the KeyC, using the checksum of the multiboot image, and
424 // the derivation material that GBA sent to us
489 u32 keyc = deriveKeyC(keyCderive,kcrc); 425 u32 keyc = deriveKeyC(keyCderive,kcrc);
490 if (keyc == 0) 426 if (keyc == 0)
491 { 427 {
492 printf("Could not find keyC - kcrc=0x%08lx\n",kcrc); 428 printf("Could not find keyC - kcrc=0x%08lx\n",kcrc);
493 warnError("Cannot continue.\n"); 429 warnError("Cannot continue.\n");
494 continue;
495 }
496 430
497 // 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. 431 continue;
432 }
433
434 // derive the boot key from the found KeyC, and send to GBA. if this is
435 // not correct, GBA will not jump to the multiboot image it was sent.
498 u32 bootkey = docrc(0xBB,keyc) | 0xbb000000; 436 u32 bootkey = docrc(0xBB,keyc) | 0xbb000000;
499 printf("BootKey = 0x%08lx\n",bootkey); 437 printf("BootKey = 0x%08lx\n",bootkey);
500 send(bootkey);
501 /*
502 printf("GBA Found! Waiting on BIOS...\n");
503 438
504 resbuf[2]=0; 439 send(bootkey);
505 while (!(resbuf[2] & 0x10)) 440 sleep(2);
506 {
507 doreset();
508 getstatus();
509 }
510 441
511 printf("Ready, sending extractor.\n"); 442 printf("Waiting for GBA...\n");
443 while (recv() != 0) {sleep(1);};
444 send(0);
512 445
513 unsigned int sendsize = ((gba_mb_gba_size + 7) & ~7); 446 VIDEO_WaitVSync();
514 unsigned int ourkey = calckey(sendsize);
515 447
516 //get current sessionkey 448 // Get game
517 u32 sessionkeyraw = recv(); 449 // -1 - unsupported game
518 u32 sessionkey = __builtin_bswap32(sessionkeyraw ^ 0x7365646F); 450 // 1 - Ruby
451 // 2 - Sapphire
452 // 3 - FireRed
453 // 4 - LeafGreen
454 // 5 - Emerald
455 u32 gameId = getMsg();
456 if (gameId == -1)
457 {
458 warnError("ERROR: Unsupported GBA game inserted!\n");
519 459
520 //send over our own key 460 continue;
521 send(__builtin_bswap32(ourkey)); 461 }
522 unsigned int fcrc = 0x15a0;
523 462
524 //send over gba header 463 printf("\nPokemon ");
525 for(i = 0; i < 0xC0; i+=4) 464 switch (gameId)
526 { 465 {
527 send(__builtin_bswap32(*(vu32*)(gba_mb_gba+i))); 466 case 1: printf("Ruby"); break;
467 case 2: printf("Sapphire"); break;
468 case 3: printf("FireRed"); break;
469 case 4: printf("LeafGreen"); break;
470 case 5: printf("Emerald"); break;
528 } 471 }
529 472
530 for (i = 0xC0; i < sendsize; i+=4) 473 printf("\n");
474 VIDEO_WaitVSync();
475
476 u32 isValid = getMsg();
477 if (isValid == -1)
531 { 478 {
532 u32 enc = ( 479 warnError("ERROR: Unsupported game version inserted!\n");
533 (gba_mb_gba[i+3] << 24)
534 | (gba_mb_gba[i+2] << 16)
535 | (gba_mb_gba[i+1] << 8)
536 | (gba_mb_gba[i]));
537
538 fcrc = docrc(fcrc,enc);
539 sessionkey = (sessionkey * 0x6177614B) + 1;
540 enc ^= sessionkey;
541 enc ^= ((~(i + (0x20 << 20))) + 1);
542 enc ^= 0x20796220;
543
544 send(enc);
545 }
546 480
547 fcrc |= (sendsize<<16); 481 continue;
482 }
548 483
549 //send over CRC 484 // Get trainer name
550 sessionkey = (sessionkey * 0x6177614B) + 1; 485 u8 trainerName[8];
551 fcrc ^= sessionkey;
552 fcrc ^= ((~(i + (0x20 << 20))) + 1);
553 fcrc ^= 0x20796220;
554 486
555 send(fcrc); 487 u32 tnd = getMsg();
488 trainerName[0] = (tnd & 0xFF000000) >> 24;
489 trainerName[1] = (tnd & 0x00FF0000) >> 16;
490 trainerName[2] = (tnd & 0x0000FF00) >> 8;
491 trainerName[3] = (tnd & 0x000000FF);
556 492
557 //get crc back (unused) 493 tnd = getMsg();
558 recv(); 494 trainerName[4] = (tnd & 0xFF000000) >> 24;
559 printf("Done!\n"); 495 trainerName[5] = (tnd & 0x00FF0000) >> 16;
560 sleep(2); 496 trainerName[6] = (tnd & 0x0000FF00) >> 8;
497 trainerName[7] = (tnd & 0x000000FF);
561 498
562 //hm 499 // Get trainer ID
563 while (1) 500 u32 trainerId = getMsg();
564 {
565 printmain();
566 printf("Press A once you have a GBA Game inserted.\n \n");
567 501
568 PAD_ScanPads(); 502 printf("Trainer: ");
569 VIDEO_WaitVSync();
570 u32 btns = PAD_ButtonsDown(0);
571 if (btns & PAD_BUTTON_START)
572 {
573 endproc();
574 } else if (btns & PAD_BUTTON_A)
575 {*/
576 sleep(2);
577 //recv();
578
579 //if (recv() == 0) //ready
580 //{
581 {{
582 printf("Waiting for GBA...\n");
583 while (recv() != 0) {fsleep(1);};
584 send(0);
585
586 VIDEO_WaitVSync();
587
588 /*int gbasize = 0;
589 while(gbasize == 0)
590 {
591 gbasize = __builtin_bswap32(recv());
592 }
593
594 send(0); //got gbasize
595 while (recv()!=0) {sleep(1);};
596
597 //u32 savesize = __builtin_bswap32(recv());
598 //send(0); //got savesize
599
600 if (gbasize == -1)
601 {
602 warnError("ERROR: No (Valid) GBA Card inserted!\n");
603
604 continue;
605 }*/
606
607 // Get game
608 // -1 - unsupported game
609 // 1 - Ruby
610 // 2 - Sapphire
611 // 3 - FireRed
612 // 4 - LeafGreen
613 // 5 - Emerald
614 u32 gameId = 0;
615 while (gameId == 0)
616 {
617 gameId = __builtin_bswap32(recv());
618 fsleep(1);
619 }
620
621 send(0);
622 while (recv()!=0) {fsleep(1);};
623 send(0);
624 //sleep(1);
625
626 if (gameId == -1)
627 {
628 warnError("ERROR: Unsupported GBA game inserted!\n");
629
630 continue;
631 }
632
633 printf("\nPokemon ");
634 switch (gameId)
635 {
636 case 1: printf("Ruby"); break;
637 case 2: printf("Sapphire"); break;
638 case 3: printf("FireRed"); break;
639 case 4: printf("LeafGreen"); break;
640 case 5: printf("Emerald"); break;
641 }
642
643 printf("\n");
644 VIDEO_WaitVSync();
645
646 u32 isValid = 0;
647 while (isValid == 0)
648 {
649 isValid = __builtin_bswap32(recv());
650 fsleep(1);
651 }
652
653 if (isValid == -1)
654 {
655 //send(0);
656
657 warnError("ERROR: Unsupported game version inserted!\n");
658
659 continue;
660 }
661
662 send(0);
663 while (recv()!=0) {fsleep(1);};
664 send(0);
665 //sleep(1);
666
667 // Get trainer name
668 u8 trainerName[8];
669
670 u32 tnd = getMsg();
671 //send(0);
672 trainerName[0] = (tnd & 0xFF000000) >> 24;
673 trainerName[1] = (tnd & 0x00FF0000) >> 16;
674 trainerName[2] = (tnd & 0x0000FF00) >> 8;
675 trainerName[3] = (tnd & 0x000000FF);
676
677 tnd = getMsg();
678 //send(0);
679 trainerName[4] = (tnd & 0xFF000000) >> 24;
680 trainerName[5] = (tnd & 0x00FF0000) >> 16;
681 trainerName[6] = (tnd & 0x0000FF00) >> 8;
682 trainerName[7] = (tnd & 0x000000FF);
683
684 // Get trainer ID
685 u32 trainerId = 0;
686 while (trainerId == 0)
687 {
688 trainerId = __builtin_bswap32(recv());
689 fsleep(1);
690 }
691 send(0);
692 while (recv()!=0) {fsleep(1);};
693 send(0);
694 //sleep(1);
695
696 printf("Trainer: ");
697
698 for (int i = 0; i < 8; i++)
699 {
700 if (trainerName[i] == 0xFF)
701 {
702 break;
703 } else {
704 printf("%c", debugGen3Decode(trainerName[i]));
705 }
706 }
707
708 printf(" (%ld)\n", trainerId);
709
710 //continue;
711
712 // Wait for confirmation.
713 printf("Press A to import the data from this game.\n");
714 printf("Press B to cancel.\n");
715 VIDEO_WaitVSync();
716
717 if (waitForButtons(PAD_BUTTON_A | PAD_BUTTON_B) & PAD_BUTTON_B)
718 {
719 continue;
720 }
721 503
504 for (int i = 0; i < 8; i++)
505 {
506 if (trainerName[i] == 0xFF)
507 {
508 break;
509 } else {
510 printf("%c", debugGen3Decode(trainerName[i]));
511 }
512 }
722 513
514 printf(" (%ld)\n", trainerId);
723 515
516 // Wait for confirmation.
517 printf("Press A to import the data from this game.\n");
518 printf("Press B to cancel.\n");
519 VIDEO_WaitVSync();
724 520
725/* 521 if (waitForButtons(PAD_BUTTON_A | PAD_BUTTON_B) & PAD_BUTTON_B)
726 //get rom header 522 {
727 for(i = 0; i < 0xC0; i+=4) 523 continue;
728 *(vu32*)(testdump+i) = recv(); 524 }
729 //print out all the info from the game 525 }
730 printf("Game Name: %.12s\n",(char*)(testdump+0xA0));
731 printf("Game ID: %.4s\n",(char*)(testdump+0xAC));
732 printf("Company ID: %.2s\n",(char*)(testdump+0xB0));
733 printf("ROM Size: %02.02f MB\n",((float)(gbasize/1024))/1024.f);
734 if(savesize > 0)
735 printf("Save Size: %02.02f KB\n \n",((float)(savesize))/1024.f);
736 else
737 printf("No Save File\n \n");
738 //generate file paths
739 char gamename[64];
740 sprintf(gamename,"/dumps/%.12s [%.4s%.2s].gba",
741 (char*)(testdump+0xA0),(char*)(testdump+0xAC),(char*)(testdump+0xB0));
742 fixFName(gamename+7); //fix name behind "/dumps/"
743 char savename[64];
744 sprintf(savename,"/dumps/%.12s [%.4s%.2s].sav",
745 (char*)(testdump+0xA0),(char*)(testdump+0xAC),(char*)(testdump+0xB0));
746 fixFName(savename+7); //fix name behind "/dumps/"
747 //let the user choose the option
748 printf("Press A to dump this game, it will take about %i minutes.\n",gbasize/1024/1024*3/2);
749 printf("Press B if you want to cancel dumping this game.\n");
750 if(savesize > 0)
751 {
752 printf("Press Y to backup this save file.\n");
753 printf("Press X to restore this save file.\n");
754 printf("Press Z to clear the save file on the GBA Cartridge.\n\n");
755 }
756 else
757 printf("\n");
758
759 int command = 0;
760 while(1)
761 {
762 PAD_ScanPads();
763 VIDEO_WaitVSync();
764 u32 btns = PAD_ButtonsDown(0);
765 if(btns&PAD_BUTTON_START)
766 endproc();
767 else if(btns&PAD_BUTTON_A)
768 {
769 command = 1;
770 break;
771 }
772 else if(btns&PAD_BUTTON_B)
773 break;
774 else if(savesize > 0)
775 {
776 if(btns&PAD_BUTTON_Y)
777 {
778 command = 2;
779 break;
780 }
781 else if(btns&PAD_BUTTON_X)
782 {
783 command = 3;
784 break;
785 }
786 else if(btns&PAD_TRIGGER_Z)
787 {
788 command = 4;
789 break;
790 }
791 }
792 }
793 if(command == 1)
794 {
795 FILE *f = fopen(gamename,"rb");
796 if(f)
797 {
798 fclose(f);
799 command = 0;
800 warnError("ERROR: Game already dumped!\n");
801 }
802 }
803 else if(command == 2)
804 {
805 FILE *f = fopen(savename,"rb");
806 if(f)
807 {
808 fclose(f);
809 command = 0;
810 warnError("ERROR: Save already backed up!\n");
811 }
812 }
813 else if(command == 3)
814 {
815 size_t readsize = 0;
816 FILE *f = fopen(savename,"rb");
817 if(f)
818 {
819 fseek(f,0,SEEK_END);
820 readsize = ftell(f);
821 if(readsize != savesize)
822 {
823 command = 0;
824 warnError("ERROR: Save has the wrong size, aborting restore!\n");
825 }
826 else
827 {
828 rewind(f);
829 fread(testdump,readsize,1,f);
830 }
831 fclose(f);
832 }
833 else
834 {
835 command = 0;
836 warnError("ERROR: No Save to restore!\n");
837 }
838 }
839 send(command);
840 //let gba prepare
841 sleep(1);
842 if(command == 0)
843 continue;
844 else if(command == 1)
845 {
846 //create base file with size
847 printf("Preparing file...\n");
848 createFile(gamename,gbasize);
849 FILE *f = fopen(gamename,"wb");
850 if(!f)
851 fatalError("ERROR: Could not create file! Exit...");
852 printf("Dumping...\n");
853 u32 bytes_read = 0;
854 while(gbasize > 0)
855 {
856 int toread = (gbasize > 0x400000 ? 0x400000 : gbasize);
857 int j;
858 for(j = 0; j < toread; j+=4)
859 {
860 *(vu32*)(testdump+j) = recv();
861 bytes_read+=4;
862 if((bytes_read&0xFFFF) == 0)
863 printf("\r%02.02f MB done",(float)(bytes_read/1024)/1024.f);
864 }
865 fwrite(testdump,toread,1,f);
866 gbasize -= toread;
867 }
868 printf("\nClosing file\n");
869 fclose(f);
870 printf("Game dumped!\n");
871 sleep(5);
872 }
873 else if(command == 2)
874 {
875 //create base file with size
876 printf("Preparing file...\n");
877 createFile(savename,savesize);
878 FILE *f = fopen(savename,"wb");
879 if(!f)
880 fatalError("ERROR: Could not create file! Exit...");
881 printf("Waiting for GBA\n");
882 VIDEO_WaitVSync();
883 u32 readval = 0;
884 while(readval != savesize)
885 readval = __builtin_bswap32(recv());
886 send(0); //got savesize
887 printf("Receiving...\n");
888 for(i = 0; i < savesize; i+=4)
889 *(vu32*)(testdump+i) = recv();
890 printf("Writing save...\n");
891 fwrite(testdump,savesize,1,f);
892 fclose(f);
893 printf("Save backed up!\n");
894 sleep(5);
895 }
896 else if(command == 3 || command == 4)
897 {
898 u32 readval = 0;
899 while(readval != savesize)
900 readval = __builtin_bswap32(recv());
901 if(command == 3)
902 {
903 printf("Sending save\n");
904 VIDEO_WaitVSync();
905 for(i = 0; i < savesize; i+=4)
906 send(__builtin_bswap32(*(vu32*)(testdump+i)));
907 }
908 printf("Waiting for GBA\n");
909 while(recv() != 0)
910 VIDEO_WaitVSync();
911 printf(command == 3 ? "Save restored!\n" : "Save cleared!\n");
912 send(0);
913 sleep(5);
914 }*/
915 }
916 }
917 /*else if(btns&PAD_BUTTON_Y)
918 {
919 const char *biosname = "/dumps/gba_bios.bin";
920 FILE *f = fopen(biosname,"rb");
921 if(f)
922 {
923 fclose(f);
924 warnError("ERROR: BIOS already backed up!\n");
925 }
926 else
927 {
928 //create base file with size
929 printf("Preparing file...\n");
930 createFile(biosname,0x4000);
931 f = fopen(biosname,"wb");
932 if(!f)
933 fatalError("ERROR: Could not create file! Exit...");
934 //send over bios dump command
935 send(5);
936 //the gba might still be in a loop itself
937 sleep(1);
938 //lets go!
939 printf("Dumping...\n");
940 for(i = 0; i < 0x4000; i+=4)
941 *(vu32*)(testdump+i) = recv();
942 fwrite(testdump,0x4000,1,f);
943 printf("Closing file\n");
944 fclose(f);
945 printf("BIOS dumped!\n");
946 sleep(5);
947 }
948 }*/
949 }
950// }
951// }
952 } 526 }
527
953 return 0; 528 return 0;
954} 529}