diff options
| author | FIX94 <fix94.1@gmail.com> | 2016-04-22 15:08:18 +0200 | 
|---|---|---|
| committer | FIX94 <fix94.1@gmail.com> | 2016-04-22 15:08:18 +0200 | 
| commit | 098b3d74b96827febcbcb18ddb08e8d318b4631d (patch) | |
| tree | 6984dd4ea9e8b0e500d1a7d6f58451402e0954de /source | |
| parent | 089ba86faf70be52e25eef5bbfbeb54439ea67f6 (diff) | |
| download | gen3uploader-098b3d74b96827febcbcb18ddb08e8d318b4631d.tar.gz gen3uploader-098b3d74b96827febcbcb18ddb08e8d318b4631d.tar.bz2 gen3uploader-098b3d74b96827febcbcb18ddb08e8d318b4631d.zip | |
-make sure to correct filenames with invalid filesystem characters (issue #3)
-corrected the si transfer delay code to only have one properly set delay
Diffstat (limited to 'source')
| -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); | 
