about summary refs log tree commit diff stats
path: root/gba
diff options
context:
space:
mode:
Diffstat (limited to 'gba')
-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
7 files changed, 121 insertions, 1082 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