diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/main.c | 231 |
1 files changed, 180 insertions, 51 deletions
diff --git a/source/main.c b/source/main.c index afe3423..ee23263 100644 --- a/source/main.c +++ b/source/main.c | |||
@@ -23,7 +23,8 @@ void printmain() | |||
23 | { | 23 | { |
24 | printf("\x1b[2J"); | 24 | printf("\x1b[2J"); |
25 | printf("\x1b[37m"); | 25 | printf("\x1b[37m"); |
26 | printf("GBA Link Cable Dumper v1.0 by FIX94\n"); | 26 | printf("GBA Link Cable Dumper v1.1 by FIX94\n"); |
27 | printf("Save Support based on SendSave by Chishm\n"); | ||
27 | } | 28 | } |
28 | 29 | ||
29 | u8 *resbuf,*cmdbuf; | 30 | u8 *resbuf,*cmdbuf; |
@@ -299,9 +300,17 @@ int main(int argc, char *argv[]) | |||
299 | { | 300 | { |
300 | if(recvsafe() == 0) //ready | 301 | if(recvsafe() == 0) //ready |
301 | { | 302 | { |
302 | sleep(1); //gba rom prepare | 303 | printf("Waiting for GBA\n"); |
303 | u32 gbasize = __builtin_bswap32(recvsafe()); | 304 | VIDEO_WaitVSync(); |
304 | if(gbasize == 0) | 305 | int gbasize = 0; |
306 | while(gbasize == 0) | ||
307 | gbasize = __builtin_bswap32(recvsafe()); | ||
308 | sendsafe(0); //got gbasize | ||
309 | usleep(5000); //wait for it to set next val | ||
310 | u32 savesize = __builtin_bswap32(recvsafe()); | ||
311 | sendsafe(0); //got savesize | ||
312 | usleep(5000); //wait for it to set next val | ||
313 | if(gbasize == -1) | ||
305 | { | 314 | { |
306 | printf("ERROR: No (Valid) GBA Card inserted!\n"); | 315 | printf("ERROR: No (Valid) GBA Card inserted!\n"); |
307 | VIDEO_WaitVSync(); | 316 | VIDEO_WaitVSync(); |
@@ -309,29 +318,36 @@ int main(int argc, char *argv[]) | |||
309 | sleep(2); | 318 | sleep(2); |
310 | continue; | 319 | continue; |
311 | } | 320 | } |
321 | //get rom header | ||
312 | for(i = 0; i < 0xC0; i+=4) | 322 | for(i = 0; i < 0xC0; i+=4) |
313 | *(vu32*)(testdump+i) = recvfast(); | 323 | *(vu32*)(testdump+i) = recvfast(); |
324 | //print out all the info from the game | ||
314 | printf("Game Name: %.12s\n",(char*)(testdump+0xA0)); | 325 | printf("Game Name: %.12s\n",(char*)(testdump+0xA0)); |
315 | printf("Game ID: %.4s\n",(char*)(testdump+0xAC)); | 326 | printf("Game ID: %.4s\n",(char*)(testdump+0xAC)); |
316 | printf("Company ID: %.2s\n",(char*)(testdump+0xB0)); | 327 | printf("Company ID: %.2s\n",(char*)(testdump+0xB0)); |
317 | printf("ROM Size: %02.02f MB\n \n",((float)(gbasize/1024))/1024.f); | 328 | printf("ROM Size: %02.02f MB\n",((float)(gbasize/1024))/1024.f); |
329 | if(savesize > 0) | ||
330 | printf("Save Size: %02.02f KB\n \n",((float)(savesize))/1024.f); | ||
331 | else | ||
332 | printf("No Save File\n \n"); | ||
333 | //generate file paths | ||
318 | char gamename[64]; | 334 | char gamename[64]; |
319 | sprintf(gamename,"/dumps/%.12s [%.4s%.2s].gba", | 335 | sprintf(gamename,"/dumps/%.12s [%.4s%.2s].gba", |
320 | (char*)(testdump+0xA0),(char*)(testdump+0xAC),(char*)(testdump+0xB0)); | 336 | (char*)(testdump+0xA0),(char*)(testdump+0xAC),(char*)(testdump+0xB0)); |
321 | FILE *f = fopen(gamename,"rb"); | 337 | char savename[64]; |
322 | if(f) | 338 | sprintf(savename,"/dumps/%.12s [%.4s%.2s].sav", |
339 | (char*)(testdump+0xA0),(char*)(testdump+0xAC),(char*)(testdump+0xB0)); | ||
340 | //let the user choose the option | ||
341 | printf("Press A to dump this game, it will take about %i minutes.\n",gbasize/1024/1024*3/2); | ||
342 | printf("Press B if you want to cancel dumping this game.\n"); | ||
343 | if(savesize > 0) | ||
323 | { | 344 | { |
324 | fclose(f); | 345 | printf("Press Y to backup this save file.\n"); |
325 | sendsafe(0); | 346 | printf("Press X to restore this save file.\n\n"); |
326 | printf("ERROR: Game already dumped! Please insert another game.\n"); | ||
327 | VIDEO_WaitVSync(); | ||
328 | VIDEO_WaitVSync(); | ||
329 | sleep(2); | ||
330 | continue; | ||
331 | } | 347 | } |
332 | printf("Press A to dump this game, it will take about %i minutes.\n",gbasize/1024/1024*3/2); | 348 | else |
333 | printf("Press B if you want to cancel dumping this game.\n\n"); | 349 | printf("\n"); |
334 | int dumping = 0; | 350 | int command = 0; |
335 | while(1) | 351 | while(1) |
336 | { | 352 | { |
337 | PAD_ScanPads(); | 353 | PAD_ScanPads(); |
@@ -341,56 +357,169 @@ int main(int argc, char *argv[]) | |||
341 | endproc(); | 357 | endproc(); |
342 | else if(btns&PAD_BUTTON_A) | 358 | else if(btns&PAD_BUTTON_A) |
343 | { | 359 | { |
344 | dumping = 1; | 360 | command = 1; |
345 | break; | 361 | break; |
346 | } | 362 | } |
347 | else if(btns&PAD_BUTTON_B) | 363 | else if(btns&PAD_BUTTON_B) |
348 | break; | 364 | break; |
365 | else if(savesize > 0) | ||
366 | { | ||
367 | if(btns&PAD_BUTTON_Y) | ||
368 | { | ||
369 | command = 2; | ||
370 | break; | ||
371 | } | ||
372 | else if(btns&PAD_BUTTON_X) | ||
373 | { | ||
374 | command = 3; | ||
375 | break; | ||
376 | } | ||
377 | } | ||
349 | } | 378 | } |
350 | sendsafe(dumping); | 379 | if(command == 1) |
351 | if(dumping == 0) | ||
352 | continue; | ||
353 | //create base file with size | ||
354 | printf("Creating file...\n"); | ||
355 | int fd = open(gamename, O_WRONLY|O_CREAT); | ||
356 | if(fd >= 0) | ||
357 | { | 380 | { |
358 | ftruncate(fd, gbasize); | 381 | FILE *f = fopen(gamename,"rb"); |
359 | close(fd); | 382 | if(f) |
383 | { | ||
384 | fclose(f); | ||
385 | command = 0; | ||
386 | printf("ERROR: Game already dumped!\n"); | ||
387 | VIDEO_WaitVSync(); | ||
388 | sleep(2); | ||
389 | } | ||
360 | } | 390 | } |
361 | f = fopen(gamename,"wb"); | 391 | else if(command == 2) |
362 | if(!f) | ||
363 | { | 392 | { |
364 | printf("ERROR: Could not create file! Exit...\n"); | 393 | FILE *f = fopen(savename,"rb"); |
365 | VIDEO_WaitVSync(); | 394 | if(f) |
366 | VIDEO_WaitVSync(); | 395 | { |
367 | sleep(5); | 396 | fclose(f); |
368 | exit(0); | 397 | command = 0; |
398 | printf("ERROR: Save already backed up!\n"); | ||
399 | VIDEO_WaitVSync(); | ||
400 | sleep(2); | ||
401 | } | ||
369 | } | 402 | } |
370 | printf("Dumping...\n"); | 403 | else if(command == 3) |
371 | u32 bytes_read = 0; | ||
372 | while(gbasize > 0) | ||
373 | { | 404 | { |
374 | int toread = (gbasize > 0x400000 ? 0x400000 : gbasize); | 405 | size_t readsize = 0; |
375 | int j; | 406 | FILE *f = fopen(savename,"rb"); |
376 | for(j = 0; j < toread; j+=4) | 407 | if(f) |
377 | { | 408 | { |
378 | *(vu32*)(testdump+j) = recvfast(); | 409 | fseek(f,0,SEEK_END); |
379 | bytes_read+=4; | 410 | readsize = ftell(f); |
380 | if((bytes_read&0xFFFF) == 0) | 411 | if(readsize != savesize) |
381 | { | 412 | { |
382 | printf("\r%02.02f MB done",(float)(bytes_read/1024)/1024.f); | 413 | command = 0; |
414 | printf("ERROR: Save has the wrong size, aborting restore!\n"); | ||
383 | VIDEO_WaitVSync(); | 415 | VIDEO_WaitVSync(); |
416 | sleep(2); | ||
417 | } | ||
418 | else | ||
419 | { | ||
420 | rewind(f); | ||
421 | fread(testdump,readsize,1,f); | ||
422 | } | ||
423 | fclose(f); | ||
424 | } | ||
425 | else | ||
426 | { | ||
427 | command = 0; | ||
428 | printf("ERROR: No Save to restore!\n"); | ||
429 | VIDEO_WaitVSync(); | ||
430 | sleep(2); | ||
431 | } | ||
432 | } | ||
433 | sendsafe(command); | ||
434 | usleep(5000); //wait for it to set next val | ||
435 | if(command == 0) | ||
436 | continue; | ||
437 | else if(command == 1) | ||
438 | { | ||
439 | //create base file with size | ||
440 | printf("Creating file...\n"); | ||
441 | int fd = open(gamename, O_WRONLY|O_CREAT); | ||
442 | if(fd >= 0) | ||
443 | { | ||
444 | ftruncate(fd, gbasize); | ||
445 | close(fd); | ||
446 | } | ||
447 | FILE *f = fopen(gamename,"wb"); | ||
448 | if(!f) | ||
449 | { | ||
450 | printf("ERROR: Could not create file! Exit...\n"); | ||
451 | VIDEO_WaitVSync(); | ||
452 | VIDEO_WaitVSync(); | ||
453 | sleep(5); | ||
454 | exit(0); | ||
455 | } | ||
456 | printf("Dumping...\n"); | ||
457 | u32 bytes_read = 0; | ||
458 | while(gbasize > 0) | ||
459 | { | ||
460 | int toread = (gbasize > 0x400000 ? 0x400000 : gbasize); | ||
461 | int j; | ||
462 | for(j = 0; j < toread; j+=4) | ||
463 | { | ||
464 | *(vu32*)(testdump+j) = recvfast(); | ||
465 | bytes_read+=4; | ||
466 | if((bytes_read&0xFFFF) == 0) | ||
467 | { | ||
468 | printf("\r%02.02f MB done",(float)(bytes_read/1024)/1024.f); | ||
469 | VIDEO_WaitVSync(); | ||
470 | } | ||
384 | } | 471 | } |
385 | //printf("%02x%02x%02x%02x",resbuf[0],resbuf[1],resbuf[2],resbuf[3]); | 472 | fwrite(testdump,toread,1,f); |
473 | gbasize -= toread; | ||
474 | } | ||
475 | printf("\nClosing file\n"); | ||
476 | fclose(f); | ||
477 | printf("Game dumped!\n"); | ||
478 | sleep(5); | ||
479 | } | ||
480 | else if(command == 2) | ||
481 | { | ||
482 | FILE *f = fopen(savename,"wb"); | ||
483 | if(!f) | ||
484 | { | ||
485 | printf("ERROR: Could not create file! Exit...\n"); | ||
486 | VIDEO_WaitVSync(); | ||
487 | VIDEO_WaitVSync(); | ||
488 | sleep(5); | ||
489 | exit(0); | ||
386 | } | 490 | } |
387 | fwrite(testdump,toread,1,f); | 491 | printf("Waiting for GBA\n"); |
388 | gbasize -= toread; | 492 | VIDEO_WaitVSync(); |
493 | u32 readval = 0; | ||
494 | while(readval != savesize) | ||
495 | readval = __builtin_bswap32(recvsafe()); | ||
496 | sendsafe(0); //got savesize | ||
497 | usleep(5000); //wait for it to set next val | ||
498 | printf("Receiving...\n"); | ||
499 | for(i = 0; i < savesize; i+=4) | ||
500 | *(vu32*)(testdump+i) = recvsafe(); | ||
501 | printf("Writing save...\n"); | ||
502 | fwrite(testdump,savesize,1,f); | ||
503 | fclose(f); | ||
504 | printf("Save backed up!\n"); | ||
505 | sleep(5); | ||
506 | } | ||
507 | else if(command == 3) | ||
508 | { | ||
509 | printf("Sending save\n"); | ||
510 | VIDEO_WaitVSync(); | ||
511 | u32 readval = 0; | ||
512 | while(readval != savesize) | ||
513 | readval = __builtin_bswap32(recvsafe()); | ||
514 | for(i = 0; i < savesize; i+=4) | ||
515 | sendsafe(__builtin_bswap32(*(vu32*)(testdump+i))); | ||
516 | printf("Waiting for GBA\n"); | ||
517 | while(recvsafe() != 0) | ||
518 | VIDEO_WaitVSync(); | ||
519 | printf("Save restored!\n"); | ||
520 | sendsafe(0); | ||
521 | sleep(5); | ||
389 | } | 522 | } |
390 | printf("\nClosing file\n"); | ||
391 | fclose(f); | ||
392 | printf("Game dumped!\n"); | ||
393 | sleep(5); | ||
394 | } | 523 | } |
395 | } | 524 | } |
396 | } | 525 | } |