about summary refs log tree commit diff stats
path: root/source/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/main.c')
-rw-r--r--source/main.c145
1 files changed, 68 insertions, 77 deletions
diff --git a/source/main.c b/source/main.c index f57aa6f..53879de 100644 --- a/source/main.c +++ b/source/main.c
@@ -16,6 +16,10 @@
16#include <dirent.h> 16#include <dirent.h>
17#include <fat.h> 17#include <fat.h>
18 18
19//from my tests 50us seems to be the lowest
20//safe si transfer delay in between calls
21#define SI_TRANS_DELAY 50
22
19extern u8 gba_mb_gba[]; 23extern u8 gba_mb_gba[];
20extern u32 gba_mb_gba_size; 24extern u32 gba_mb_gba_size;
21 25
@@ -23,25 +27,12 @@ void printmain()
23{ 27{
24 printf("\x1b[2J"); 28 printf("\x1b[2J");
25 printf("\x1b[37m"); 29 printf("\x1b[37m");
26 printf("GBA Link Cable Dumper v1.4 by FIX94\n"); 30 printf("GBA Link Cable Dumper v1.5 by FIX94\n");
27 printf("Save Support based on SendSave by Chishm\n"); 31 printf("Save Support based on SendSave by Chishm\n");
28 printf("GBA BIOS Dumper by Dark Fader\n \n"); 32 printf("GBA BIOS Dumper by Dark Fader\n \n");
29} 33}
30 34
31u8 *resbuf,*cmdbuf; 35u8 *resbuf,*cmdbuf;
32volatile u16 pads = 0;
33volatile bool ctrlerr = false;
34void ctrlcb(s32 chan, u32 ret)
35{
36 if(ret)
37 {
38 ctrlerr = true;
39 return;
40 }
41 //just call us again
42 pads = (~((resbuf[1]<<8)|resbuf[0]))&0x3FF;
43 SI_Transfer(1,cmdbuf,1,resbuf,5,ctrlcb,350);
44}
45 36
46volatile u32 transval = 0; 37volatile u32 transval = 0;
47void transcb(s32 chan, u32 ret) 38void transcb(s32 chan, u32 ret)
@@ -72,12 +63,6 @@ unsigned int docrc(u32 crc, u32 val)
72 return crc; 63 return crc;
73} 64}
74 65
75static inline void wait_for_transfer()
76{
77 //350 is REALLY pushing it already, cant go further
78 do{ usleep(350); }while(transval == 0);
79}
80
81void endproc() 66void endproc()
82{ 67{
83 printf("Start pressed, exit\n"); 68 printf("Start pressed, exit\n");
@@ -85,6 +70,31 @@ void endproc()
85 VIDEO_WaitVSync(); 70 VIDEO_WaitVSync();
86 exit(0); 71 exit(0);
87} 72}
73void fixFName(char *str)
74{
75 u8 i = 0;
76 for(i = 0; i < strlen(str); ++i)
77 {
78 if(str[i] < 0x20 || str[i] > 0x7F)
79 str[i] = '_';
80 else switch(str[i])
81 {
82 case '\\':
83 case '/':
84 case ':':
85 case '*':
86 case '?':
87 case '\"':
88 case '<':
89 case '>':
90 case '|':
91 str[i] = '_';
92 break;
93 default:
94 break;
95 }
96 }
97}
88unsigned int calckey(unsigned int size) 98unsigned int calckey(unsigned int size)
89{ 99{
90 unsigned int ret = 0; 100 unsigned int ret = 0;
@@ -122,48 +132,33 @@ void doreset()
122{ 132{
123 cmdbuf[0] = 0xFF; //reset 133 cmdbuf[0] = 0xFF; //reset
124 transval = 0; 134 transval = 0;
125 SI_Transfer(1,cmdbuf,1,resbuf,3,transcb,0); 135 SI_Transfer(1,cmdbuf,1,resbuf,3,transcb,SI_TRANS_DELAY);
126 wait_for_transfer(); 136 while(transval == 0) ;
127} 137}
128void getstatus() 138void getstatus()
129{ 139{
130 cmdbuf[0] = 0; //status 140 cmdbuf[0] = 0; //status
131 transval = 0; 141 transval = 0;
132 SI_Transfer(1,cmdbuf,1,resbuf,3,transcb,0); 142 SI_Transfer(1,cmdbuf,1,resbuf,3,transcb,SI_TRANS_DELAY);
133 wait_for_transfer(); 143 while(transval == 0) ;
134} 144}
135u32 recvsafe() 145u32 recv()
136{ 146{
137 memset(resbuf,0,32); 147 memset(resbuf,0,32);
138 cmdbuf[0]=0x14; //read 148 cmdbuf[0]=0x14; //read
139 transval = 0; 149 transval = 0;
140 SI_Transfer(1,cmdbuf,1,resbuf,5,transcb,0); 150 SI_Transfer(1,cmdbuf,1,resbuf,5,transcb,SI_TRANS_DELAY);
141 wait_for_transfer(); 151 while(transval == 0) ;
142 return *(vu32*)resbuf; 152 return *(vu32*)resbuf;
143} 153}
144void sendsafe(u32 msg) 154void send(u32 msg)
145{ 155{
146 cmdbuf[0]=0x15;cmdbuf[1]=(msg>>0)&0xFF;cmdbuf[2]=(msg>>8)&0xFF; 156 cmdbuf[0]=0x15;cmdbuf[1]=(msg>>0)&0xFF;cmdbuf[2]=(msg>>8)&0xFF;
147 cmdbuf[3]=(msg>>16)&0xFF;cmdbuf[4]=(msg>>24)&0xFF; 157 cmdbuf[3]=(msg>>16)&0xFF;cmdbuf[4]=(msg>>24)&0xFF;
148 transval = 0; 158 transval = 0;
149 resbuf[0] = 0; 159 resbuf[0] = 0;
150 SI_Transfer(1,cmdbuf,5,resbuf,1,transcb,0); 160 SI_Transfer(1,cmdbuf,5,resbuf,1,transcb,SI_TRANS_DELAY);
151 wait_for_transfer();
152}
153void sendsafe_wait(u32 msg)
154{
155 sendsafe(msg);
156 //wait for GBA
157 usleep(5000);
158}
159u32 recvfast()
160{
161 cmdbuf[0]=0x14; //read
162 transval = 0;
163 SI_Transfer(1,cmdbuf,1,resbuf,5,transcb,0);
164 usleep(275);
165 while(transval == 0) ; 161 while(transval == 0) ;
166 return *(vu32*)resbuf;
167} 162}
168bool dirExists(const char *path) 163bool dirExists(const char *path)
169{ 164{
@@ -240,7 +235,6 @@ int main(int argc, char *argv[])
240 printmain(); 235 printmain();
241 printf("Waiting for a GBA in port 2...\n"); 236 printf("Waiting for a GBA in port 2...\n");
242 resval = 0; 237 resval = 0;
243 ctrlerr = false;
244 238
245 SI_GetTypeAsync(1,acb); 239 SI_GetTypeAsync(1,acb);
246 while(1) 240 while(1)
@@ -274,17 +268,14 @@ int main(int argc, char *argv[])
274 unsigned int ourkey = calckey(sendsize); 268 unsigned int ourkey = calckey(sendsize);
275 //printf("Our Key: %08x\n", ourkey); 269 //printf("Our Key: %08x\n", ourkey);
276 //get current sessionkey 270 //get current sessionkey
277 u32 sessionkeyraw = recvsafe(); 271 u32 sessionkeyraw = recv();
278 u32 sessionkey = __builtin_bswap32(sessionkeyraw^0x7365646F); 272 u32 sessionkey = __builtin_bswap32(sessionkeyraw^0x7365646F);
279 //send over our own key 273 //send over our own key
280 sendsafe(__builtin_bswap32(ourkey)); 274 send(__builtin_bswap32(ourkey));
281 unsigned int fcrc = 0x15a0; 275 unsigned int fcrc = 0x15a0;
282 //send over gba header 276 //send over gba header
283 for(i = 0; i < 0xC0; i+=4) 277 for(i = 0; i < 0xC0; i+=4)
284 { 278 send(__builtin_bswap32(*(vu32*)(gba_mb_gba+i)));
285 sendsafe(__builtin_bswap32(*(vu32*)(gba_mb_gba+i)));
286 //if(!(resbuf[0]&0x2)) printf("Possible error %02x\n",resbuf[0]);
287 }
288 //printf("Header done! Sending ROM...\n"); 279 //printf("Header done! Sending ROM...\n");
289 for(i = 0xC0; i < sendsize; i+=4) 280 for(i = 0xC0; i < sendsize; i+=4)
290 { 281 {
@@ -294,8 +285,7 @@ int main(int argc, char *argv[])
294 enc^=sessionkey; 285 enc^=sessionkey;
295 enc^=((~(i+(0x20<<20)))+1); 286 enc^=((~(i+(0x20<<20)))+1);
296 enc^=0x20796220; 287 enc^=0x20796220;
297 sendsafe(enc); 288 send(enc);
298 //if(!(resbuf[0]&0x2)) printf("Possible error %02x\n",resbuf[0]);
299 } 289 }
300 fcrc |= (sendsize<<16); 290 fcrc |= (sendsize<<16);
301 //printf("ROM done! CRC: %08x\n", fcrc); 291 //printf("ROM done! CRC: %08x\n", fcrc);
@@ -304,9 +294,9 @@ int main(int argc, char *argv[])
304 fcrc^=sessionkey; 294 fcrc^=sessionkey;
305 fcrc^=((~(i+(0x20<<20)))+1); 295 fcrc^=((~(i+(0x20<<20)))+1);
306 fcrc^=0x20796220; 296 fcrc^=0x20796220;
307 sendsafe(fcrc); 297 send(fcrc);
308 //get crc back (unused) 298 //get crc back (unused)
309 recvsafe(); 299 recv();
310 printf("Done!\n"); 300 printf("Done!\n");
311 sleep(2); 301 sleep(2);
312 //hm 302 //hm
@@ -322,16 +312,16 @@ int main(int argc, char *argv[])
322 endproc(); 312 endproc();
323 else if(btns&PAD_BUTTON_A) 313 else if(btns&PAD_BUTTON_A)
324 { 314 {
325 if(recvsafe() == 0) //ready 315 if(recv() == 0) //ready
326 { 316 {
327 printf("Waiting for GBA\n"); 317 printf("Waiting for GBA\n");
328 VIDEO_WaitVSync(); 318 VIDEO_WaitVSync();
329 int gbasize = 0; 319 int gbasize = 0;
330 while(gbasize == 0) 320 while(gbasize == 0)
331 gbasize = __builtin_bswap32(recvsafe()); 321 gbasize = __builtin_bswap32(recv());
332 sendsafe_wait(0); //got gbasize 322 send(0); //got gbasize
333 u32 savesize = __builtin_bswap32(recvsafe()); 323 u32 savesize = __builtin_bswap32(recv());
334 sendsafe_wait(0); //got savesize 324 send(0); //got savesize
335 if(gbasize == -1) 325 if(gbasize == -1)
336 { 326 {
337 warnError("ERROR: No (Valid) GBA Card inserted!\n"); 327 warnError("ERROR: No (Valid) GBA Card inserted!\n");
@@ -339,7 +329,7 @@ int main(int argc, char *argv[])
339 } 329 }
340 //get rom header 330 //get rom header
341 for(i = 0; i < 0xC0; i+=4) 331 for(i = 0; i < 0xC0; i+=4)
342 *(vu32*)(testdump+i) = recvfast(); 332 *(vu32*)(testdump+i) = recv();
343 //print out all the info from the game 333 //print out all the info from the game
344 printf("Game Name: %.12s\n",(char*)(testdump+0xA0)); 334 printf("Game Name: %.12s\n",(char*)(testdump+0xA0));
345 printf("Game ID: %.4s\n",(char*)(testdump+0xAC)); 335 printf("Game ID: %.4s\n",(char*)(testdump+0xAC));
@@ -353,9 +343,11 @@ int main(int argc, char *argv[])
353 char gamename[64]; 343 char gamename[64];
354 sprintf(gamename,"/dumps/%.12s [%.4s%.2s].gba", 344 sprintf(gamename,"/dumps/%.12s [%.4s%.2s].gba",
355 (char*)(testdump+0xA0),(char*)(testdump+0xAC),(char*)(testdump+0xB0)); 345 (char*)(testdump+0xA0),(char*)(testdump+0xAC),(char*)(testdump+0xB0));
346 fixFName(gamename+7); //fix name behind "/dumps/"
356 char savename[64]; 347 char savename[64];
357 sprintf(savename,"/dumps/%.12s [%.4s%.2s].sav", 348 sprintf(savename,"/dumps/%.12s [%.4s%.2s].sav",
358 (char*)(testdump+0xA0),(char*)(testdump+0xAC),(char*)(testdump+0xB0)); 349 (char*)(testdump+0xA0),(char*)(testdump+0xAC),(char*)(testdump+0xB0));
350 fixFName(savename+7); //fix name behind "/dumps/"
359 //let the user choose the option 351 //let the user choose the option
360 printf("Press A to dump this game, it will take about %i minutes.\n",gbasize/1024/1024*3/2); 352 printf("Press A to dump this game, it will take about %i minutes.\n",gbasize/1024/1024*3/2);
361 printf("Press B if you want to cancel dumping this game.\n"); 353 printf("Press B if you want to cancel dumping this game.\n");
@@ -441,7 +433,9 @@ int main(int argc, char *argv[])
441 warnError("ERROR: No Save to restore!\n"); 433 warnError("ERROR: No Save to restore!\n");
442 } 434 }
443 } 435 }
444 sendsafe_wait(command); 436 send(command);
437 //let gba prepare
438 sleep(1);
445 if(command == 0) 439 if(command == 0)
446 continue; 440 continue;
447 else if(command == 1) 441 else if(command == 1)
@@ -460,7 +454,7 @@ int main(int argc, char *argv[])
460 int j; 454 int j;
461 for(j = 0; j < toread; j+=4) 455 for(j = 0; j < toread; j+=4)
462 { 456 {
463 *(vu32*)(testdump+j) = recvfast(); 457 *(vu32*)(testdump+j) = recv();
464 bytes_read+=4; 458 bytes_read+=4;
465 if((bytes_read&0xFFFF) == 0) 459 if((bytes_read&0xFFFF) == 0)
466 printf("\r%02.02f MB done",(float)(bytes_read/1024)/1024.f); 460 printf("\r%02.02f MB done",(float)(bytes_read/1024)/1024.f);
@@ -485,11 +479,11 @@ int main(int argc, char *argv[])
485 VIDEO_WaitVSync(); 479 VIDEO_WaitVSync();
486 u32 readval = 0; 480 u32 readval = 0;
487 while(readval != savesize) 481 while(readval != savesize)
488 readval = __builtin_bswap32(recvsafe()); 482 readval = __builtin_bswap32(recv());
489 sendsafe_wait(0); //got savesize 483 send(0); //got savesize
490 printf("Receiving...\n"); 484 printf("Receiving...\n");
491 for(i = 0; i < savesize; i+=4) 485 for(i = 0; i < savesize; i+=4)
492 *(vu32*)(testdump+i) = recvsafe(); 486 *(vu32*)(testdump+i) = recv();
493 printf("Writing save...\n"); 487 printf("Writing save...\n");
494 fwrite(testdump,savesize,1,f); 488 fwrite(testdump,savesize,1,f);
495 fclose(f); 489 fclose(f);
@@ -502,22 +496,21 @@ int main(int argc, char *argv[])
502 VIDEO_WaitVSync(); 496 VIDEO_WaitVSync();
503 u32 readval = 0; 497 u32 readval = 0;
504 while(readval != savesize) 498 while(readval != savesize)
505 readval = __builtin_bswap32(recvsafe()); 499 readval = __builtin_bswap32(recv());
506 for(i = 0; i < savesize; i+=4) 500 for(i = 0; i < savesize; i+=4)
507 sendsafe(__builtin_bswap32(*(vu32*)(testdump+i))); 501 send(__builtin_bswap32(*(vu32*)(testdump+i)));
508 printf("Waiting for GBA\n"); 502 printf("Waiting for GBA\n");
509 while(recvsafe() != 0) 503 while(recv() != 0)
510 VIDEO_WaitVSync(); 504 VIDEO_WaitVSync();
511 printf("Save restored!\n"); 505 printf("Save restored!\n");
512 sendsafe_wait(0); 506 send(0);
513 sleep(5); 507 sleep(5);
514 } 508 }
515 } 509 }
516 } 510 }
517 else if(btns&PAD_BUTTON_Y) 511 else if(btns&PAD_BUTTON_Y)
518 { 512 {
519 char biosname[64]; 513 const char *biosname = "/dumps/gba_bios.bin";
520 sprintf(biosname,"/dumps/gba_bios.bin");
521 FILE *f = fopen(biosname,"rb"); 514 FILE *f = fopen(biosname,"rb");
522 if(f) 515 if(f)
523 { 516 {
@@ -533,15 +526,13 @@ int main(int argc, char *argv[])
533 if(!f) 526 if(!f)
534 fatalError("ERROR: Could not create file! Exit..."); 527 fatalError("ERROR: Could not create file! Exit...");
535 //send over bios dump command 528 //send over bios dump command
536 sendsafe_wait(4); 529 send(4);
537 //the gba might still be in a loop itself 530 //the gba might still be in a loop itself
538 VIDEO_WaitVSync(); VIDEO_WaitVSync(); 531 sleep(1);
539 VIDEO_WaitVSync(); VIDEO_WaitVSync();
540 VIDEO_WaitVSync(); VIDEO_WaitVSync();
541 //lets go! 532 //lets go!
542 printf("Dumping...\n"); 533 printf("Dumping...\n");
543 for(i = 0; i < 0x4000; i+=4) 534 for(i = 0; i < 0x4000; i+=4)
544 *(vu32*)(testdump+i) = recvsafe(); 535 *(vu32*)(testdump+i) = recv();
545 fwrite(testdump,0x4000,1,f); 536 fwrite(testdump,0x4000,1,f);
546 printf("Closing file\n"); 537 printf("Closing file\n");
547 fclose(f); 538 fclose(f);