about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--gba/source/gamedata.c56
-rw-r--r--gba/source/gamedata.h7
-rw-r--r--gba/source/libSave.c596
-rw-r--r--gba/source/libSave.h27
-rw-r--r--gba/source/link.c23
-rw-r--r--gba/source/link.h9
-rw-r--r--gba/source/main.c485
-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
12 files changed, 348 insertions, 1707 deletions
diff --git a/gba/source/gamedata.c b/gba/source/gamedata.c index 8e63232..6868b2b 100644 --- a/gba/source/gamedata.c +++ b/gba/source/gamedata.c
@@ -1,9 +1,9 @@
1/* 1/*
2 * Pokemon Gen III Data Extractor by hatkirby 2017. 2 * Copyright (C) 2017 hatkirby
3 * Copyright (C) 2017 slipstream/RoL
3 * 4 *
4 * This software may be modified and distributed under the terms 5 * This software may be modified and distributed under the terms
5 * of the MIT license. See the LICENSE file for details. 6 * of the MIT license. See the LICENSE file for details.
6 *
7 */ 7 */
8#include "gamedata.h" 8#include "gamedata.h"
9 9
@@ -245,9 +245,10 @@ bool initSaveData(
245 } 245 }
246 246
247 /// --- FR/LG --- 247 /// --- FR/LG ---
248 // In FR/LG, the function that initialises the save-block pointers to default does not set up saveblock3. 248 // In FR/LG, the function that initialises the save-block pointers to
249 // Which will need to be set up before loading the save if we want boxed Pokémon to not disappear. 249 // default does not set up saveblock3. Which will need to be set up before
250 // Oh, and loadsave() offset is different between FR and LG... 250 // loading the save if we want boxed Pokémon to not disappear. Oh, and
251 // loadsave() offset is different between FR and LG...
251 252
252 case 'DRPB': // FireRed German 253 case 'DRPB': // FireRed German
253 case 'DGPB': // LeafGreen German 254 case 'DGPB': // LeafGreen German
@@ -376,12 +377,14 @@ bool initSaveData(
376 { 377 {
377 // LeafGreen v1.1 Japanese is undumped. 378 // LeafGreen v1.1 Japanese is undumped.
378 // Therefore, it is unsupported. 379 // Therefore, it is unsupported.
379 // I will make guesses at the offsets in the comments, but I will not actually implement them until LeafGreen v1.1 is dumped. 380 // I will make guesses at the offsets in the comments, but I will
381 // not actually implement them until LeafGreen v1.1 is dumped.
380 382
381 return false; 383 return false;
382 } 384 }
383 385
384 loadsave = (void(*)(char)) 0x80db529; // potential LG1.1 address: 0x80db4fd 386 loadsave = (void(*)(char)) 0x80db529;
387 // potential LG1.1 address: 0x80db4fd
385 //mainloop = (void(*)()) 0x8000417; 388 //mainloop = (void(*)()) 0x8000417;
386 //titlemid = 0x8078987; 389 //titlemid = 0x8078987;
387 //load_pokemon = (void(*)()) 0x804b9c5; 390 //load_pokemon = (void(*)()) 0x804b9c5;
@@ -399,8 +402,10 @@ bool initSaveData(
399 } 402 }
400 403
401 /// --- Emerald --- 404 /// --- Emerald ---
402 // In Emerald, the saveblock pointer that isn't set up is saveblock1 (in FR/LG it was saveblock3). 405 // In Emerald, the saveblock pointer that isn't set up is saveblock1 (in
403 // The initial save loading code after the copyright screen is also updated, now it sets up ASLR/crypto here before loading the save. 406 // FR/LG it was saveblock3). The initial save loading code after the
407 // copyright screen is also updated, now it sets up ASLR/crypto here before
408 // loading the save.
404 409
405 case 'DEPB': // Emerald German 410 case 'DEPB': // Emerald German
406 { 411 {
@@ -493,42 +498,15 @@ bool initSaveData(
493 } 498 }
494 499
495 loadsave(0); 500 loadsave(0);
496// sendS32(-1); 501
497 // now the save is loaded, we can do what we want with the loaded blocks. 502 // now the save is loaded, we can do what we want with the loaded blocks.
498 // first, we're going to want to decrypt the parts that are crypted, if applicable. 503 // first, we're going to want to decrypt the parts that are crypted, if
504 // applicable.
499 decryptSaveStructures(gSaveBlock1,gSaveBlock2,gSaveBlock3); 505 decryptSaveStructures(gSaveBlock1,gSaveBlock2,gSaveBlock3);
500 506
501 *SaveBlock1 = gSaveBlock1; 507 *SaveBlock1 = gSaveBlock1;
502 *SaveBlock2 = gSaveBlock2; 508 *SaveBlock2 = gSaveBlock2;
503 *SaveBlock3 = gSaveBlock3; 509 *SaveBlock3 = gSaveBlock3;
504 510
505 /*
506 // time to call the payload.
507 payload(gSaveBlock1,gSaveBlock2,gSaveBlock3);
508 // Now, we better call the function that sets the pokemon-related stuff from the structure elements of the loaded save again.
509 // Just in case the payload did something with that.
510 load_pokemon();
511 // In FR/LG/Emerald, just returning to the game is unwise.
512 // The game reloads the savefile.
513 // In FR/LG, this is done at the title screen after setting ASLR/saveblock-crypto up. (probably because at initial save-load, SaveBlock3 ptr isn't set up lol)
514 // So, better bypass the title screen and get the game to return directly to the Continue/New Game screen.
515 // In Emerald, the save reload happens after the Continue option was chosen, so we have no choice but to bypass everything and get the game to go straight to the overworld.
516 // Easiest way to do this is to call into the middle of the function we want, using an ASM wrapper to set up the stack.
517 // Here goes...
518 if (titlemid) {
519 // Function reserves an extra 4 bytes of stack space in FireRed/LeafGreen, and none in Emerald.
520 call_into_middle_of_titlescreen_func(titlemid,(GAME_EM ? 0 : 4));
521 }
522 // Now we've done what we want, time to return to the game.
523 // Can't just return, the game will reload the save.
524 // So let's just call the main-loop directly ;)
525 // turn the sound back on before we head back to the game
526 *(vu16 *)(REG_BASE + 0x84) = 0x8f;
527 // re-enable interrupts
528 REG_IME = 1;
529 mainloop();
530 // Anything past here will not be executed.
531 return 0;
532 */
533 return true; 511 return true;
534} 512}
diff --git a/gba/source/gamedata.h b/gba/source/gamedata.h index 99dfa8e..4d0a2a9 100644 --- a/gba/source/gamedata.h +++ b/gba/source/gamedata.h
@@ -1,3 +1,10 @@
1/*
2 * Copyright (C) 2017 hatkirby
3 * Copyright (C) 2017 slipstream/RoL
4 *
5 * This software may be modified and distributed under the terms
6 * of the MIT license. See the LICENSE file for details.
7 */
1#ifndef _GAMEDATA_H_ 8#ifndef _GAMEDATA_H_
2#define _GAMEDATA_H_ 9#define _GAMEDATA_H_
3 10
diff --git a/gba/source/libSave.c b/gba/source/libSave.c deleted file mode 100644 index e3bda1d..0000000 --- a/gba/source/libSave.c +++ /dev/null
@@ -1,596 +0,0 @@
1/*
2 libSave
3 Cartridge backup memory save routines. To use, call the required
4 routine with a pointer to an appropriately sized array of data to
5 be read from or written to the cartridge.
6 Data types are from wintermute's gba_types.h libgba library.
7 Original file from SendSave by Chishm
8*/
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <gba_dma.h>
14
15#define EEPROM_ADDRESS (0xDFFFF00)
16#define REG_EEPROM *(vu16 *)(EEPROM_ADDRESS)
17#define REG_DMA3CNT_H *(vu16 *)(REG_BASE + 0x0de)
18#define REG_WAITCNT *(vu16 *)(REG_BASE + 0x204)
19
20//-----------------------------------------------------------------------
21// Common EEPROM Routines
22//-----------------------------------------------------------------------
23
24void EEPROM_SendPacket( u16* packet, int size )
25{
26 REG_WAITCNT = (REG_WAITCNT & 0xF8FF) | 0x0300;
27 REG_DMA3SAD = (u32)packet;
28 REG_DMA3DAD = EEPROM_ADDRESS;
29 REG_DMA3CNT = 0x80000000 + size;
30 while((REG_DMA3CNT_H & 0x8000) != 0) ;
31}
32
33void EEPROM_ReceivePacket( u16* packet, int size )
34{
35 REG_WAITCNT = (REG_WAITCNT & 0xF8FF) | 0x0300;
36 REG_DMA3SAD = EEPROM_ADDRESS;
37 REG_DMA3DAD = (u32)packet;
38 REG_DMA3CNT = 0x80000000 + size;
39 while((REG_DMA3CNT_H & 0x8000) != 0) ;
40}
41
42//-----------------------------------------------------------------------
43// Routines for 512B EEPROM
44//-----------------------------------------------------------------------
45
46void EEPROM_Read_512B( volatile u8 offset, u8* dest ) // dest must point to 8 bytes
47{
48 u16 packet[68];
49 u8* out_pos;
50 u16* in_pos;
51 u8 out_byte;
52 int byte, bit;
53
54 memset( packet, 0, 68*2 );
55
56 // Read request
57 packet[0] = 1;
58 packet[1] = 1;
59
60 // 6 bits eeprom address (MSB first)
61 packet[2] = (offset>>5)&1;
62 packet[3] = (offset>>4)&1;
63 packet[4] = (offset>>3)&1;
64 packet[5] = (offset>>2)&1;
65 packet[6] = (offset>>1)&1;
66 packet[7] = (offset)&1;
67
68 // End of request
69 packet[8] = 0;
70
71 // Do transfers
72 EEPROM_SendPacket( packet, 9 );
73 memset( packet, 0, 68*2 );
74 EEPROM_ReceivePacket( packet, 68 );
75
76 // Extract data
77 in_pos = &packet[4];
78 out_pos = dest;
79 for( byte = 7; byte >= 0; --byte )
80 {
81 out_byte = 0;
82 for( bit = 7; bit >= 0; --bit )
83 {
84// out_byte += (*in_pos++)<<bit;
85 out_byte += ((*in_pos++)&1)<<bit;
86 }
87 *out_pos++ = out_byte ;
88 }
89}
90
91void EEPROM_Write_512B( volatile u8 offset, u8* source ) // source must point to 8 bytes
92{
93 u16 packet[73];
94 u8* in_pos;
95 u16* out_pos;
96 u8 in_byte;
97 int byte, bit;
98
99 memset( packet, 0, 73*2 );
100
101 // Write request
102 packet[0] = 1;
103 packet[1] = 0;
104
105 // 6 bits eeprom address (MSB first)
106 packet[2] = (offset>>5)&1;
107 packet[3] = (offset>>4)&1;
108 packet[4] = (offset>>3)&1;
109 packet[5] = (offset>>2)&1;
110 packet[6] = (offset>>1)&1;
111 packet[7] = (offset)&1;
112
113 // Extract data
114 in_pos = source;
115 out_pos = &packet[8];
116 for( byte = 7; byte >= 0; --byte )
117 {
118 in_byte = *in_pos++;
119 for( bit = 7; bit >= 0; --bit )
120 {
121 *out_pos++ = (in_byte>>bit)&1;
122 }
123 }
124
125 // End of request
126 packet[72] = 0;
127
128 // Do transfers
129 EEPROM_SendPacket( packet, 73 );
130
131 // Wait for EEPROM to finish (should timeout after 10 ms)
132 while( (REG_EEPROM & 1) == 0 );
133}
134
135//---------------------------------------------------------------------------------
136void GetSave_EEPROM_512B(u8* data)
137//---------------------------------------------------------------------------------
138{
139 volatile u8 x;
140 u32 sleep;
141
142 for (x=0;x<64;++x){
143 EEPROM_Read_512B(x,&data[x*8]);
144 for(sleep=0;sleep<512000;sleep++);
145 }
146}
147
148//---------------------------------------------------------------------------------
149void PutSave_EEPROM_512B(u8* data)
150//---------------------------------------------------------------------------------
151{
152 volatile u8 x;
153 u32 sleep;
154
155 for (x=0;x<64;x++){
156 EEPROM_Write_512B(x,&data[x*8]);
157 for(sleep=0;sleep<512000;sleep++);
158 }
159}
160//-----------------------------------------------------------------------
161// Routines for 8KB EEPROM
162//-----------------------------------------------------------------------
163
164void EEPROM_Read_8KB( volatile u16 offset, u8* dest ) // dest must point to 8 bytes
165{
166 u16 packet[68];
167 u8* out_pos;
168 u16* in_pos;
169 u8 out_byte;
170 int byte, bit;
171
172 memset( packet, 0, 68*2 );
173
174 // Read request
175 packet[0] = 1;
176 packet[1] = 1;
177
178 // 14 bits eeprom address (MSB first)
179 packet[2] = (offset>>13)&1;
180 packet[3] = (offset>>12)&1;
181 packet[4] = (offset>>11)&1;
182 packet[5] = (offset>>10)&1;
183 packet[6] = (offset>>9)&1;
184 packet[7] = (offset>>8)&1;
185 packet[8] = (offset>>7)&1;
186 packet[9] = (offset>>6)&1;
187 packet[10] = (offset>>5)&1;
188 packet[11] = (offset>>4)&1;
189 packet[12] = (offset>>3)&1;
190 packet[13] = (offset>>2)&1;
191 packet[14] = (offset>>1)&1;
192 packet[15] = (offset)&1;
193
194 // End of request
195 packet[16] = 0;
196
197 // Do transfers
198 EEPROM_SendPacket( packet, 17 );
199 memset( packet, 0, 68*2 );
200 EEPROM_ReceivePacket( packet, 68 );
201
202 // Extract data
203 in_pos = &packet[4];
204 out_pos = dest;
205 for( byte = 7; byte >= 0; --byte )
206 {
207 out_byte = 0;
208 for( bit = 7; bit >= 0; --bit )
209 {
210// out_byte += (*in_pos++)<<bit;
211 out_byte += ((*in_pos++)&1)<<bit;
212 }
213 *out_pos++ = out_byte;
214 }
215
216}
217
218void EEPROM_Write_8KB( volatile u16 offset, u8* source ) // source must point to 8 bytes
219{
220 u16 packet[81];
221 u8* in_pos;
222 u16* out_pos;
223 u8 in_byte;
224 int byte, bit;
225
226 memset( packet, 0, 81*2 );
227
228 // Write request
229 packet[0] = 1;
230 packet[1] = 0;
231
232 // 14 bits eeprom address (MSB first)
233 packet[2] = (offset>>13)&1;
234 packet[3] = (offset>>12)&1;
235 packet[4] = (offset>>11)&1;
236 packet[5] = (offset>>10)&1;
237 packet[6] = (offset>>9)&1;
238 packet[7] = (offset>>8)&1;
239 packet[8] = (offset>>7)&1;
240 packet[9] = (offset>>6)&1;
241 packet[10] = (offset>>5)&1;
242 packet[11] = (offset>>4)&1;
243 packet[12] = (offset>>3)&1;
244 packet[13] = (offset>>2)&1;
245 packet[14] = (offset>>1)&1;
246 packet[15] = (offset)&1;
247
248 // Extract data
249 in_pos = source;
250 out_pos = &packet[16];
251 for( byte = 7; byte >= 0; --byte )
252 {
253 in_byte = *in_pos++;
254 for( bit = 7; bit >= 0; --bit )
255 {
256 *out_pos++ = (in_byte>>bit)&1;
257 }
258 }
259
260 // End of request
261 packet[80] = 0;
262
263 // Do transfers
264 EEPROM_SendPacket( packet, 81 );
265
266 // Wait for EEPROM to finish (should timeout after 10 ms)
267 while( (REG_EEPROM & 1) == 0 );
268}
269
270//---------------------------------------------------------------------------------
271void GetSave_EEPROM_8KB(u8* data)
272//---------------------------------------------------------------------------------
273{
274 volatile u16 x;
275 u32 sleep;
276
277 for (x=0;x<1024;x++){
278 EEPROM_Read_8KB(x,&data[x*8]);
279 for(sleep=0;sleep<512000;sleep++);
280 }
281
282}
283
284//---------------------------------------------------------------------------------
285void PutSave_EEPROM_8KB(u8* data)
286//---------------------------------------------------------------------------------
287{
288 volatile u16 x;
289 u32 sleep;
290
291 for (x=0;x<1024;x++){
292 EEPROM_Write_8KB(x,&data[x*8]);
293 for(sleep=0;sleep<512000;sleep++);
294 }
295}
296
297//---------------------------------------------------------------------------------
298void GetSave_SRAM_32KB(u8* data)
299//---------------------------------------------------------------------------------
300{
301 volatile u8 *sram= (u8*) 0x0E000000;
302 volatile u16 x;
303
304 for (x = 0; x < 0x8000; ++x)
305 {
306 data[x] = sram[x];
307 }
308
309}
310
311//---------------------------------------------------------------------------------
312void PutSave_SRAM_32KB(u8* data)
313//---------------------------------------------------------------------------------
314{
315 volatile u8 *sram= (u8*) 0x0E000000;
316 volatile u16 x;
317
318 for (x = 0; x < 0x8000; ++x)
319 {
320 sram[x] = data[x];
321 }
322}
323
324//---------------------------------------------------------------------------------
325void GetSave_FLASH_64KB(u8* data)
326//---------------------------------------------------------------------------------
327{
328 volatile u8 *sram= (u8*) 0x0E000000;
329 volatile u32 x;
330
331 for (x = 0; x < 0x10000; ++x)
332 {
333 data[x] = sram[x];
334 }
335}
336
337//---------------------------------------------------------------------------------
338void PutSave_FLASH_64KB(u8* foo)
339//---------------------------------------------------------------------------------
340{
341 volatile u8 *fctrl0 = (u8*) 0xE005555;
342 volatile u8 *fctrl1 = (u8*) 0xE002AAA;
343 volatile u8 *fctrl2 = (u8*) 0xE000000;
344
345 //init flash
346 *fctrl0 = 0xAA;
347 *fctrl1 = 0x55;
348 *fctrl0 = 0x90;
349 *fctrl2 = 0xF0;
350
351 //erase chip
352 *fctrl0 = 0xAA;
353 *fctrl1 = 0x55;
354 *fctrl0 = 0x80;
355 *fctrl0 = 0xAA;
356 *fctrl1 = 0x55;
357 *fctrl0 = 0x10;
358
359 //wait for erase done
360 u8 val1;
361 u8 val2;
362 val1 = *fctrl2;
363 val2 = *fctrl2;
364 while (val1 != val2) {
365 val1 = *fctrl2;
366 val2 = *fctrl2;
367 }
368 val1 = *fctrl2;
369 val2 = *fctrl2;
370 while (val1 != val2) {
371 val1 = *fctrl2;
372 val2 = *fctrl2;
373 }
374
375 volatile u8 *data = fctrl2;
376 u32 i;
377 //write data
378 for (i=0; i<65536; i++) {
379 *fctrl0 = 0xAA;
380 *fctrl1 = 0x55;
381 *fctrl0 = 0xA0;
382 data [i] = foo [ i ];
383 val1 = data [ i ];
384 val2 = data [ i ];
385
386 while (val1 != val2) {
387 val1 = data [ i ];
388 val2 = data [ i ];
389 }
390 val1 = data [ i ];
391 val2 = data [ i ];
392 while (val1 != val2) {
393 val1 = data [ i ];
394 val2 = data [ i ];
395 }
396 val1 = data [ i ];
397 val2 = data [ i ];
398 while (val1 != val2) {
399 val1 = data [ i ];
400 val2 = data [ i ];
401 }
402 }
403}
404
405//---------------------------------------------------------------------------------
406void GetSave_FLASH_128KB(u8* data)
407//---------------------------------------------------------------------------------
408{
409 const u32 size = 0x10000;
410
411 volatile u8 *fctrl0 = (u8*) 0xE005555;
412 volatile u8 *fctrl1 = (u8*) 0xE002AAA;
413 volatile u8 *fctrl2 = (u8*) 0xE000000;
414 volatile u32 i;
415 volatile u8 *sram= (u8*) 0x0E000000;
416
417 //init flash
418 *fctrl0 = 0xAA;
419 *fctrl1 = 0x55;
420 *fctrl0 = 0x90;
421 *fctrl2 = 0xF0;
422
423 // read first bank
424 *fctrl0 = 0xAA;
425 *fctrl1 = 0x55;
426 *fctrl0 = 0xB0;
427 *fctrl2 = 0x00;
428
429 for (i=0; i<size; i++){
430 data[i] = sram[i];
431 }
432
433 // read second bank
434 *fctrl0 = 0xAA;
435 *fctrl1 = 0x55;
436 *fctrl0 = 0xB0;
437 *fctrl2 = 0x01;
438
439 for (i=0; i<size; i++){
440 data[i + size] = sram[i];
441 }
442
443}
444
445//---------------------------------------------------------------------------------
446void PutSave_FLASH_128KB(u8* foo)
447//---------------------------------------------------------------------------------
448{
449 volatile u8 *fctrl0 = (u8*) 0xE005555;
450 volatile u8 *fctrl1 = (u8*) 0xE002AAA;
451 volatile u8 *fctrl2 = (u8*) 0xE000000;
452
453 u8 val1;
454 u8 val2;
455
456 //init flash
457 *fctrl0 = 0xAA;
458 *fctrl1 = 0x55;
459 *fctrl0 = 0x90;
460 *fctrl2 = 0xF0;
461
462 //erase chip
463 *fctrl0 = 0xAA;
464 *fctrl1 = 0x55;
465 *fctrl0 = 0x80;
466 *fctrl0 = 0xAA;
467 *fctrl1 = 0x55;
468 *fctrl0 = 0x10;
469
470 //wait for erase done
471 val1 = *fctrl2;
472 val2 = *fctrl2;
473 while (val1 != val2) {
474 val1 = *fctrl2;
475 val2 = *fctrl2;
476 }
477 val1 = *fctrl2;
478 val2 = *fctrl2;
479 while (val1 != val2) {
480 val1 = *fctrl2;
481 val2 = *fctrl2;
482 }
483
484 volatile u8 *data = fctrl2;
485 volatile u32 i;
486 // change to bank 0
487 *fctrl0 = 0xAA;
488 *fctrl1 = 0x55;
489 *fctrl0 = 0xB0;
490 *fctrl2 = 0x00;
491
492 //write data
493 for (i=0; i<65536; i++) {
494 *fctrl0 = 0xAA;
495 *fctrl1 = 0x55;
496 *fctrl0 = 0xA0;
497 data [i] = foo [ i ];
498 val1 = data [ i ];
499 val2 = data [ i ];
500
501 while (val1 != val2) {
502 val1 = data [ i ];
503 val2 = data [ i ];
504 }
505 val1 = data [ i ];
506 val2 = data [ i ];
507 while (val1 != val2) {
508 val1 = data [ i ];
509 val2 = data [ i ];
510 }
511 val1 = data [ i ];
512 val2 = data [ i ];
513 while (val1 != val2) {
514 val1 = data [ i ];
515 val2 = data [ i ];
516 }
517 }
518
519 // Change to bank 1
520 *fctrl0 = 0xAA;
521 *fctrl1 = 0x55;
522 *fctrl0 = 0xB0;
523 *fctrl2 = 0x01;
524
525 //write data
526 for (i=0; i<65536; i++) {
527 *fctrl0 = 0xAA;
528 *fctrl1 = 0x55;
529 *fctrl0 = 0xA0;
530 data [i] = foo [ i + 0x10000];
531 val1 = data [ i ];
532 val2 = data [ i ];
533
534 while (val1 != val2) {
535 val1 = data [ i ];
536 val2 = data [ i ];
537 }
538 val1 = data [ i ];
539 val2 = data [ i ];
540 while (val1 != val2) {
541 val1 = data [ i ];
542 val2 = data [ i ];
543 }
544 val1 = data [ i ];
545 val2 = data [ i ];
546 while (val1 != val2) {
547 val1 = data [ i ];
548 val2 = data [ i ];
549 }
550 }
551
552}
553
554//---------------------------------------------------------------------------------
555u32 SaveSize(u8* data, s32 gamesize)
556//---------------------------------------------------------------------------------
557{
558 if(gamesize < 0)
559 return 0;
560
561 u32 *pak= ((u32*)0x08000000);
562 s32 x;
563 u16 i;
564 s32 size = gamesize/4;
565
566
567 for (x=size-1;x>=0;x--){
568 switch (pak[x]) {
569 case 0x53414C46:
570 if (pak[x+1] == 0x5F4D3148){
571 return 0x20000; // FLASH_128KB
572 } else if ((pak[x+1] & 0x0000FFFF) == 0x00005F48){
573 return 0x10000; // FLASH_64KB
574 } else if (pak[x+1] == 0x32313548){
575 return 0x10000; // FLASH_64KB
576 }
577 break;
578 case 0x52504545:
579 if ((pak[x+1] & 0x00FFFFFF) == 0x005F4D4F){
580 GetSave_EEPROM_8KB(data);
581 for(i = 8; i < 0x800; i += 8) {
582 if(memcmp(data, data+i, 8) != 0)
583 return 0x2000; // EEPROM_8KB
584 }
585 return 0x200; // EEPROM_512B
586 }
587 break;
588 case 0x4D415253:
589 if ((pak[x+1] & 0x000000FF) == 0x0000005F){
590 return 0x8000; // SRAM_32KB
591 }
592 }
593 }
594 return 0;
595}
596
diff --git a/gba/source/libSave.h b/gba/source/libSave.h deleted file mode 100644 index 5ecf822..0000000 --- a/gba/source/libSave.h +++ /dev/null
@@ -1,27 +0,0 @@
1
2
3//---------------------------------------------------------------------------------
4#ifdef __cplusplus
5extern "C" {
6#endif
7//---------------------------------------------------------------------------------
8
9void GetSave_EEPROM_512B(u8* data);
10void PutSave_EEPROM_512B(u8* data);
11void GetSave_EEPROM_8KB(u8* data);
12void PutSave_EEPROM_8KB(u8* data);
13void GetSave_SRAM_32KB(u8* data);
14void PutSave_SRAM_32KB(u8* data);
15void GetSave_FLASH_64KB(u8* data);
16void PutSave_FLASH_64KB(u8* foo);
17void GetSave_FLASH_128KB(u8* data);
18void PutSave_FLASH_128KB(u8* foo);
19
20u32 SaveSize(u8* data, s32 gamesize);
21
22
23//---------------------------------------------------------------------------------
24#ifdef __cplusplus
25} // extern "C"
26#endif
27//---------------------------------------------------------------------------------
diff --git a/gba/source/link.c b/gba/source/link.c index e695622..c84e44d 100644 --- a/gba/source/link.c +++ b/gba/source/link.c
@@ -1,13 +1,20 @@
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
3#define JOY_WRITE 2 9#define JOY_WRITE 2
4#define JOY_READ 4 10#define JOY_READ 4
5#define JOY_RW 6 11#define JOY_RW 6
6 12
7void waitForWriteAccess() 13void initializeLink()
8{ 14{
9 //while ((REG_HS_CTRL & JOY_READ) == 0); 15 REG_HS_CTRL |= JOY_RW;
10 while ((REG_HS_CTRL & JOY_WRITE) == 0); 16 REG_JOYTR = 0;
17 while ((REG_HS_CTRL & JOY_WRITE) == 0);
11 REG_HS_CTRL |= JOY_RW; 18 REG_HS_CTRL |= JOY_RW;
12} 19}
13 20
@@ -23,19 +30,9 @@ void waitForAck()
23void sendS32(s32 val) 30void sendS32(s32 val)
24{ 31{
25 REG_JOYTR = val; 32 REG_JOYTR = val;
26 //waitForWriteAccess();
27} 33}
28 34
29void sendU32(u32 val) 35void sendU32(u32 val)
30{ 36{
31 REG_JOYTR = val; 37 REG_JOYTR = val;
32 //waitForWriteAccess();
33}
34
35u32 recieveU32()
36{
37 while ((REG_HS_CTRL & JOY_WRITE) == 0);
38 REG_HS_CTRL |= JOY_RW;
39 return REG_JOYRE;
40} 38}
41
diff --git a/gba/source/link.h b/gba/source/link.h index f18b38a..08fd998 100644 --- a/gba/source/link.h +++ b/gba/source/link.h
@@ -1,12 +1,17 @@
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
4#include <gba.h> 10#include <gba.h>
5 11
6void waitForWriteAccess(); 12void initializeLink();
7void waitForAck(); 13void waitForAck();
8void sendS32(s32 val); 14void sendS32(s32 val);
9void sendU32(u32 val); 15void sendU32(u32 val);
10u32 recieveU32();
11 16
12#endif 17#endif
diff --git a/gba/source/main.c b/gba/source/main.c index 94d4c2b..9f97324 100644 --- a/gba/source/main.c +++ b/gba/source/main.c
@@ -1,435 +1,110 @@
1/* 1/*
2 * Copyright (C) 2016 FIX94 2 * Copyright (C) 2017 hatkirby
3 * 3 *
4 * This software may be modified and distributed under the terms 4 * This software may be modified and distributed under the terms
5 * of the MIT license. See the LICENSE file for details. 5 * of the MIT license. See the LICENSE file for details.
6 */ 6 */
7#include <gba.h> 7#include <gba.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include "libSave.h"
11#include "gamedata.h" 8#include "gamedata.h"
12#include "link.h" 9#include "link.h"
13 10
14#define REG_WAITCNT *(vu16 *)(REG_BASE + 0x204)
15#define JOY_WRITE 2
16#define JOY_READ 4
17#define JOY_RW 6
18
19u8 save_data[0x20000] __attribute__ ((section (".sbss")));
20
21s32 getGameSize(void)
22{
23 if(*(vu32*)(0x08000004) != 0x51AEFF24)
24 return -1;
25 s32 i;
26 for(i = (1<<20); i < (1<<25); i<<=1)
27 {
28 vu16 *rompos = (vu16*)(0x08000000+i);
29 int j;
30 bool romend = true;
31 for(j = 0; j < 0x1000; j++)
32 {
33 if(rompos[j] != j)
34 {
35 romend = false;
36 break;
37 }
38 }
39 if(romend) break;
40 }
41 return i;
42}
43
44
45// === (from tonc_memdef.h) ===========================================
46
47// --- REG_DISPCNT defines ---
48#define DCNT_MODE0 0x0000
49#define DCNT_MODE1 0x0001
50#define DCNT_MODE2 0x0002
51#define DCNT_MODE3 0x0003
52#define DCNT_MODE4 0x0004
53#define DCNT_MODE5 0x0005
54// layers
55#define DCNT_BG0 0x0100
56#define DCNT_BG1 0x0200
57#define DCNT_BG2 0x0400
58#define DCNT_BG3 0x0800
59#define DCNT_OBJ 0x1000
60typedef u16 COLOR;
61#define MEM_VRAM 0x06000000
62#define SCREEN_WIDTH 240
63#define vid_mem ((u16*)MEM_VRAM)
64static inline void m3_plot(int x, int y, COLOR clr)
65{ vid_mem[y*SCREEN_WIDTH+x]= clr; }
66static inline COLOR RGB15(u32 red, u32 green, u32 blue)
67{ return red | (green<<5) | (blue<<10); }
68void plot_sqr(int x, int y, COLOR clr)
69{
70 /*for (int j=0;j<8; j++)
71 {
72 for (int i=0;i<8; i++)
73 {
74 vid_mem[(y*8+j+32)*SCREEN_WIDTH+x*8+i+32] = clr;
75 }
76 }
77 vid_mem[(y*8+1+32)*SCREEN_WIDTH+x*8+1+32] = RGB15(31,31,31);*/
78}
79void m3_fill(COLOR clr)
80{
81 /*int ii;
82 u32 *dst= (u32*)vid_mem;
83 u32 wd= (clr<<16) | clr;
84
85 for(ii=0; ii<SCREEN_WIDTH/4; ii++)
86 *dst++= wd;*/
87}
88
89//---------------------------------------------------------------------------------
90// Program entry point
91//---------------------------------------------------------------------------------
92int main(void) 11int main(void)
93{ 12{
94 //REG_IME = 0; 13 initializeLink();
95 //REG_DISPCNT= DCNT_MODE3 | DCNT_BG2;
96 m3_fill(RGB15(31,31,31));
97 plot_sqr( 4, 4, RGB15(31, 0, 0) ); // or CLR_RED
98
99 /*
100
101 //*(vu16 *)(REG_BASE + 0x84) = 0x8f;
102 //REG_IME = 1;
103 // the vblank interrupt must be enabled for VBlankIntrWait() to work
104 // since the default dispatcher handles the bios flags no vblank handler
105 // is required
106 irqInit();
107 irqEnable(IRQ_VBLANK);
108
109 consoleDemoInit();
110 //REG_JOYTR = 0;
111
112 // ansi escape sequence to set print co-ordinates
113 // /x1b[line;columnH
114 //u32 i;
115 iprintf("\x1b[9;2HPokemon Gen III Data Extractor\n");
116 iprintf("\x1b[10;4HPlease look at the TV\n");
117 14
118 // disable this, needs power 15 // Identify the host game.
119 SNDSTAT = 0; 16 if (GAME_RUBY)
120 SNDBIAS = 0;
121
122 // Set up waitstates for EEPROM access etc.
123 REG_WAITCNT = 0x0317;
124
125 s32 gamesize = getGameSize();
126 u32 savesize = SaveSize(save_data,gamesize);
127 switch (savesize){
128 case 0x200:
129 GetSave_EEPROM_512B(save_data);
130 break;
131 case 0x2000:
132 GetSave_EEPROM_8KB(save_data);
133 break;
134 case 0x8000:
135 GetSave_SRAM_32KB(save_data);
136 break;
137 case 0x10000:
138 GetSave_FLASH_64KB(save_data);
139 break;
140 case 0x20000:
141 GetSave_FLASH_128KB(save_data);
142 break;
143 default:
144 break;
145 }*/
146
147 //clear out previous messages
148 REG_HS_CTRL |= JOY_RW;
149 sendU32(0);
150 plot_sqr( 4, 5, RGB15( 0,31, 0) ); // or CLR_LIME
151 while (1)
152 { 17 {
153 waitForWriteAccess(); 18 sendS32(1);
154 //while (recieveU32() != 0); 19 } else if (GAME_SAPP)
155 //waitForAck(); 20 {
156 plot_sqr( 4, 6, RGB15( 0, 0,31) ); // or CLR_BLUE 21 sendS32(2);
157 // Send game size to acknowledge that an actual cart is inserted. 22 } else if (GAME_FR)
158 //s32 gamesize = getGameSize(); 23 {
159 //sendS32(gamesize); 24 sendS32(3);
160 //waitForAck(); 25 } else if (GAME_LG)
161 26 {
162 // If the game size is illegal, start over. 27 sendS32(4);
163 //if (gamesize == -1) 28 } else if (GAME_EM)
164 //{ 29 {
165 // sendS32(0); 30 sendS32(5);
166 // 31 } else {
167 // continue; 32 sendS32(-1);
168 //} 33 waitForAck();
169
170 // Identify the inserted game.
171 if (GAME_RUBY)
172 {
173 sendS32(1);
174 } else if (GAME_SAPP)
175 {
176 sendS32(2);
177 } else if (GAME_FR)
178 {
179 sendS32(3);
180 } else if (GAME_LG)
181 {
182 sendS32(4);
183 } else if (GAME_EM)
184 {
185 sendS32(5);
186 } else {
187 sendS32(-1);
188 waitForAck();
189
190 sendS32(0);
191 34
192 continue; 35 return 0;
193 } 36 }
194 plot_sqr( 5, 4, RGB15( 31, 0,31) );
195 waitForAck();
196 plot_sqr( 5, 5, RGB15( 16, 16,16) );
197 37
198 // Get access to save data. 38 waitForAck();
199 pSaveBlock1 SaveBlock1;
200 pSaveBlock2 SaveBlock2;
201 pSaveBlock3 SaveBlock3;
202 //iprintf("gonna check thing\n");
203 if (!initSaveData(&SaveBlock1, &SaveBlock2, &SaveBlock3))
204 {
205 // Unsupported game version.
206 //iprintf("Unsupported game version\n");
207 sendS32(-1);
208 waitForAck();
209 39
210 sendS32(0); 40 // Get access to save data.
41 pSaveBlock1 SaveBlock1;
42 pSaveBlock2 SaveBlock2;
43 pSaveBlock3 SaveBlock3;
211 44
212 continue; 45 if (!initSaveData(&SaveBlock1, &SaveBlock2, &SaveBlock3))
213 } 46 {
214 //iprintf("success\n"); 47 // Unsupported game version.
215 plot_sqr( 5, 6, RGB15( 0, 31,16) ); 48 sendS32(-1);
216 sendS32(1); 49 waitForAck();
217 waitForAck();
218
219 // Send trainer name.
220 u8* trainerName = 0;
221 50
222 if (GAME_RS) 51 return 0;
223 { 52 }
224 trainerName = SaveBlock2->rs.playerName;
225 } else if (GAME_FRLG)
226 {
227 trainerName = SaveBlock2->frlg.playerName;
228 } else if (GAME_EM)
229 {
230 trainerName = SaveBlock2->e.playerName;
231 }
232 53
233 u32 tn1 = 54 sendS32(1);
234 (trainerName[0] << 24) 55 waitForAck();
235 | (trainerName[1] << 16)
236 | (trainerName[2] << 8)
237 | (trainerName[3]);
238 56
239 u32 tn2 = 57 // Send trainer name.
240 (trainerName[4] << 24) 58 u8* trainerName = 0;
241 | (trainerName[5] << 16)
242 | (trainerName[6] << 8)
243 | (trainerName[7]);
244 59
245 sendU32(tn1); 60 if (GAME_RS)
246 waitForAck(); 61 {
62 trainerName = SaveBlock2->rs.playerName;
63 } else if (GAME_FRLG)
64 {
65 trainerName = SaveBlock2->frlg.playerName;
66 } else if (GAME_EM)
67 {
68 trainerName = SaveBlock2->e.playerName;
69 }
247 70
248 sendU32(tn2); 71 u32 tn1 =
249 waitForAck(); 72 (trainerName[0] << 24)
73 | (trainerName[1] << 16)
74 | (trainerName[2] << 8)
75 | (trainerName[3]);
250 76
251 // Send trainer ID. 77 u32 tn2 =
252 78 (trainerName[4] << 24)
253 u8* trainerId = 0; 79 | (trainerName[5] << 16)
254 if (GAME_RS) 80 | (trainerName[6] << 8)
255 { 81 | (trainerName[7]);
256 trainerId = SaveBlock2->rs.playerTrainerId;
257 } else if (GAME_FRLG)
258 {
259 trainerId = SaveBlock2->frlg.playerTrainerId;
260 } else if (GAME_EM)
261 {
262 trainerId = SaveBlock2->e.playerTrainerId;
263 }
264 82
265 u32 tti = 83 sendU32(tn1);
266 (trainerId[1] << 8) 84 waitForAck();
267 | (trainerId[0]);
268 85
269 //iprintf("sending trainer id %ld\n", tti); 86 sendU32(tn2);
270 sendU32(tti); 87 waitForAck();
271 waitForAck();
272 88
273 // Restart, because we're just testing. 89 // Send trainer ID.
274 sendS32(0); 90 u8* trainerId = 0;
275 //continue; 91 if (GAME_RS)
276 break; 92 {
93 trainerId = SaveBlock2->rs.playerTrainerId;
94 } else if (GAME_FRLG)
95 {
96 trainerId = SaveBlock2->frlg.playerTrainerId;
97 } else if (GAME_EM)
98 {
99 trainerId = SaveBlock2->e.playerTrainerId;
100 }
277 101
278/* 102 u32 tti =
103 (trainerId[1] << 8)
104 | (trainerId[0]);
279 105
106 sendU32(tti);
107 waitForAck();
280 108
281 //game in, send header 109 // Halt();
282 for(i = 0; i < 0xC0; i+=4)
283 {
284 REG_JOYTR = *(vu32*)(0x08000000+i);
285 while((REG_HS_CTRL&JOY_READ) == 0) ;
286 REG_HS_CTRL |= JOY_RW;
287 }
288 REG_JOYTR = 0;
289 //wait for other side to choose
290 while((REG_HS_CTRL&JOY_WRITE) == 0) ;
291 REG_HS_CTRL |= JOY_RW;
292 u32 choseval = REG_JOYRE;
293 if(choseval == 0)
294 {
295 REG_JOYTR = 0;
296 continue; //nothing to read
297 }
298 else if(choseval == 1)
299 {
300 //disable interrupts
301 u32 prevIrqMask = REG_IME;
302 REG_IME = 0;
303 //dump the game
304 for(i = 0; i < gamesize; i+=4)
305 {
306 REG_JOYTR = *(vu32*)(0x08000000+i);
307 while((REG_HS_CTRL&JOY_READ) == 0) ;
308 REG_HS_CTRL |= JOY_RW;
309 }
310 //restore interrupts
311 REG_IME = prevIrqMask;
312 }
313 else if(choseval == 2)
314 {
315 //disable interrupts
316 u32 prevIrqMask = REG_IME;
317 REG_IME = 0;
318 //backup save
319 switch (savesize){
320 case 0x200:
321 GetSave_EEPROM_512B(save_data);
322 break;
323 case 0x2000:
324 GetSave_EEPROM_8KB(save_data);
325 break;
326 case 0x8000:
327 GetSave_SRAM_32KB(save_data);
328 break;
329 case 0x10000:
330 GetSave_FLASH_64KB(save_data);
331 break;
332 case 0x20000:
333 GetSave_FLASH_128KB(save_data);
334 break;
335 default:
336 break;
337 }
338 //restore interrupts
339 REG_IME = prevIrqMask;
340 //say gc side we read it
341 REG_JOYTR = savesize;
342 //wait for a cmd receive for safety
343 while((REG_HS_CTRL&JOY_WRITE) == 0) ;
344 REG_HS_CTRL |= JOY_RW;
345 //send the save
346 for(i = 0; i < savesize; i+=4)
347 {
348 REG_JOYTR = *(vu32*)(save_data+i);
349 while((REG_HS_CTRL&JOY_READ) == 0) ;
350 REG_HS_CTRL |= JOY_RW;
351 }
352 }
353 else if(choseval == 3 || choseval == 4)
354 {
355 REG_JOYTR = savesize;
356 if(choseval == 3)
357 {
358 //receive the save
359 for(i = 0; i < savesize; i+=4)
360 {
361 while((REG_HS_CTRL&JOY_WRITE) == 0) ;
362 REG_HS_CTRL |= JOY_RW;
363 *(vu32*)(save_data+i) = REG_JOYRE;
364 }
365 }
366 else
367 {
368 //clear the save
369 for(i = 0; i < savesize; i+=4)
370 *(vu32*)(save_data+i) = 0;
371 }
372 //disable interrupts
373 u32 prevIrqMask = REG_IME;
374 REG_IME = 0;
375 //write it
376 switch (savesize){
377 case 0x200:
378 PutSave_EEPROM_512B(save_data);
379 break;
380 case 0x2000:
381 PutSave_EEPROM_8KB(save_data);
382 break;
383 case 0x8000:
384 PutSave_SRAM_32KB(save_data);
385 break;
386 case 0x10000:
387 PutSave_FLASH_64KB(save_data);
388 break;
389 case 0x20000:
390 PutSave_FLASH_128KB(save_data);
391 break;
392 default:
393 break;
394 }
395 //restore interrupts
396 REG_IME = prevIrqMask;
397 //say gc side we're done
398 REG_JOYTR = 0;
399 //wait for a cmd receive for safety
400 while((REG_HS_CTRL&JOY_WRITE) == 0) ;
401 REG_HS_CTRL |= JOY_RW;
402 }
403 REG_JOYTR = 0;
404 }
405 } else if(REG_HS_CTRL&JOY_WRITE)
406 {
407 REG_HS_CTRL |= JOY_RW;
408 u32 choseval = REG_JOYRE;
409 if(choseval == 5)
410 {
411 //disable interrupts
412 u32 prevIrqMask = REG_IME;
413 REG_IME = 0;
414 //dump BIOS
415 for (i = 0; i < 0x4000; i+=4)
416 {
417 // the lower bits are inaccurate, so just get it four times :)
418 u32 a = MidiKey2Freq((WaveData *)(i-4), 180-12, 0) * 2;
419 u32 b = MidiKey2Freq((WaveData *)(i-3), 180-12, 0) * 2;
420 u32 c = MidiKey2Freq((WaveData *)(i-2), 180-12, 0) * 2;
421 u32 d = MidiKey2Freq((WaveData *)(i-1), 180-12, 0) * 2;
422 REG_JOYTR = ((a>>24<<24) | (d>>24<<16) | (c>>24<<8) | (b>>24));
423 while((REG_HS_CTRL&JOY_READ) == 0) ;
424 REG_HS_CTRL |= JOY_RW;
425 }
426 //restore interrupts
427 REG_IME = prevIrqMask;
428 }
429 REG_JOYTR = 0;
430 }*/
431 Halt();
432 }
433} 110}
434
435
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}