diff options
Diffstat (limited to 'source/main.c')
-rw-r--r-- | source/main.c | 145 |
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 | |||
19 | extern u8 gba_mb_gba[]; | 23 | extern u8 gba_mb_gba[]; |
20 | extern u32 gba_mb_gba_size; | 24 | extern 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 | ||
31 | u8 *resbuf,*cmdbuf; | 35 | u8 *resbuf,*cmdbuf; |
32 | volatile u16 pads = 0; | ||
33 | volatile bool ctrlerr = false; | ||
34 | void 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 | ||
46 | volatile u32 transval = 0; | 37 | volatile u32 transval = 0; |
47 | void transcb(s32 chan, u32 ret) | 38 | void 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 | ||
75 | static 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 | |||
81 | void endproc() | 66 | void 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 | } |
73 | void 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 | } | ||
88 | unsigned int calckey(unsigned int size) | 98 | unsigned 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 | } |
128 | void getstatus() | 138 | void 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 | } |
135 | u32 recvsafe() | 145 | u32 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 | } |
144 | void sendsafe(u32 msg) | 154 | void 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 | } | ||
153 | void sendsafe_wait(u32 msg) | ||
154 | { | ||
155 | sendsafe(msg); | ||
156 | //wait for GBA | ||
157 | usleep(5000); | ||
158 | } | ||
159 | u32 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 | } |
168 | bool dirExists(const char *path) | 163 | bool 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); |