From 3aa9c24992f72fd2b05e140cb256f2d08b6db8dc Mon Sep 17 00:00:00 2001 From: RocketRobz Date: Sun, 7 Oct 2018 00:04:05 -0600 Subject: [PATCH] Implement GBA ROM dumping --- arm9/source/driveMenu.cpp | 154 ++++++++++++++++++++++++++++++++------ arm9/source/main.cpp | 2 + 2 files changed, 134 insertions(+), 22 deletions(-) diff --git a/arm9/source/driveMenu.cpp b/arm9/source/driveMenu.cpp index e5dd4f4..9341215 100644 --- a/arm9/source/driveMenu.cpp +++ b/arm9/source/driveMenu.cpp @@ -21,6 +21,10 @@ ------------------------------------------------------------------*/ #include +#include +#include +#include +#include #include "main.h" #include "date.h" @@ -38,6 +42,73 @@ static bool flashcardMountRan = true; static bool dmTextPrinted = false; int dmCursorPosition = 0; +static u8 gbaFixedValue = 0; + +void gbaCartDump(void) { + int pressed = 0; + + printf ("\x1b[0;27H"); + printf (" "); // Clear time + consoleInit(NULL, 1, BgType_Text4bpp, BgSize_T_256x256, 15, 0, false, true); + printf("Dump GBA cart ROM to\n"); + printf("\"fat:/gm9i/out\"?\n"); + printf("( yes, no)"); + while (true) { + // Power saving loop. Only poll the keys once per frame and sleep the CPU if there is nothing else to do + do { + scanKeys(); + pressed = keysDownRepeat(); + swiWaitForVBlank(); + } while (!(pressed & KEY_A) && !(pressed & KEY_B)); + + if (pressed & KEY_A) { + consoleClear(); + if (access("fat:/gm9i", F_OK) != 0) { + printf("Creating directory..."); + mkdir("fat:/gm9i", 0777); + } + if (access("fat:/gm9i/out", F_OK) != 0) { + printf ("\x1b[0;0H"); + printf("Creating directory..."); + mkdir("fat:/gm9i/out", 0777); + } + char gbaHeaderGameTitle[13] = "/0"; + char gbaHeaderGameCode[5] = "/0"; + char gbaHeaderMakerCode[3] = "/0"; + for (int i = 0; i < 12; i++) { + gbaHeaderGameTitle[i] = *(char*)(0x080000A0+i); + if (*(u8*)(0x080000A0+i) == 0) { + break; + } + } + for (int i = 0; i < 4; i++) { + gbaHeaderGameCode[i] = *(char*)(0x080000AC+i); + if (*(u8*)(0x080000AC+i) == 0) { + break; + } + } + for (int i = 0; i < 2; i++) { + gbaHeaderMakerCode[i] = *(char*)(0x080000B0+i); + } + char destPath[256]; + snprintf(destPath, sizeof(destPath), "fat:/gm9i/out/%s_%s_%s.gba", gbaHeaderGameTitle, gbaHeaderGameCode, gbaHeaderMakerCode); + consoleClear(); + printf("Dumping...\n"); + printf("This may take a while.\n"); + printf("\n"); + printf("Do not remove the GBA cart.\n"); + remove(destPath); + FILE* destinationFile = fopen(destPath, "wb"); + fwrite((void*)0x08000000, 1, 0x400000, destinationFile); + fclose(destinationFile); + break; + } + if (pressed & KEY_B) { + break; + } + } +} + void driveMenu (void) { int pressed = 0; int held = 0; @@ -54,14 +125,26 @@ void driveMenu (void) { flashcardMountRan = false; } + gbaFixedValue = *(u8*)(0x080000B2); + if (!dmTextPrinted) { consoleInit(NULL, 1, BgType_Text4bpp, BgSize_T_256x256, 15, 0, false, true); - if (dmCursorPosition == 0 && isDSiMode()) { - printf ("[sd:] SDCARD\n"); - printf ("(SD FAT)"); + if (isDSiMode()) { + if (dmCursorPosition == 0) { + printf ("[sd:] SDCARD\n"); + printf ("(SD FAT)"); + } else { + printf ("[fat:] GAMECART\n"); + printf ("(Flashcart FAT)"); + } } else { - printf ("[fat:] GAMECART\n"); - printf ("(Flashcart FAT)"); + if (dmCursorPosition == 0) { + printf ("[fat:] GAMECART\n"); + printf ("(Flashcart FAT)"); + } else if (!isDSiMode() && isRegularDS) { + printf ("GBA GAMECART\n"); + printf ("(GBA Game)"); + } } iprintf ("\x1b[%i;0H", 22-isDSiMode()); printf (titleName); @@ -102,6 +185,14 @@ void driveMenu (void) { iprintf ("\x1b[%i;29H", 2+isDSiMode()); printf ("[x]"); } + if (!isDSiMode() && isRegularDS) { + printf ("\x1b[3;1H"); + printf ("GBA GAMECART"); + if (gbaFixedValue != 0x96) { + printf ("\x1b[3;29H"); + printf ("[x]"); + } + } dmTextPrinted = true; } @@ -120,38 +211,57 @@ void driveMenu (void) { held = keysHeld(); swiWaitForVBlank(); - if (REG_SCFG_MC != stored_SCFG_MC) { + if ((REG_SCFG_MC != stored_SCFG_MC) + || (*(u8*)(0x080000B2) != gbaFixedValue)) { dmTextPrinted = false; break; } } while (!(pressed & KEY_UP) && !(pressed & KEY_DOWN) && !(pressed & KEY_A) && !(held & KEY_R)); - if ((pressed & KEY_UP) && isDSiMode()) { - dmCursorPosition -= 1; - dmTextPrinted = false; + if (pressed & KEY_UP) { + if (isDSiMode() || isRegularDS) { + dmCursorPosition -= 1; + dmTextPrinted = false; + } } - if ((pressed & KEY_DOWN) && isDSiMode()) { - dmCursorPosition += 1; - dmTextPrinted = false; + if (pressed & KEY_DOWN) { + if (isDSiMode() || isRegularDS) { + dmCursorPosition += 1; + dmTextPrinted = false; + } } if (dmCursorPosition < 0) dmCursorPosition = 1; // Wrap around to bottom of list if (dmCursorPosition > 1) dmCursorPosition = 0; // Wrap around to top of list if (pressed & KEY_A) { - if (dmCursorPosition == 0 && isDSiMode()) { - if (sdMounted) { - dmTextPrinted = false; - chdir("sd:/"); - screenMode = 1; - break; + if (dmCursorPosition == 0) { + if (isDSiMode()) { + if (sdMounted) { + dmTextPrinted = false; + chdir("sd:/"); + screenMode = 1; + break; + } + } else { + if (flashcardMounted) { + dmTextPrinted = false; + chdir("fat:/"); + screenMode = 1; + break; + } } } else { - if (flashcardMounted) { + if (isDSiMode()) { + if (flashcardMounted) { + dmTextPrinted = false; + chdir("fat:/"); + screenMode = 1; + break; + } + } else if (isRegularDS && flashcardMounted && gbaFixedValue == 0x96) { dmTextPrinted = false; - chdir("fat:/"); - screenMode = 1; - break; + gbaCartDump(); } } } diff --git a/arm9/source/main.cpp b/arm9/source/main.cpp index abc8d77..205e757 100644 --- a/arm9/source/main.cpp +++ b/arm9/source/main.cpp @@ -122,6 +122,8 @@ int main(int argc, char **argv) { printf ("\x1b[22;11H"); printf ("mounting drive(s)..."); + sysSetCartOwner (BUS_OWNER_ARM9); // Allow arm9 to access GBA ROM + if (isDSiMode()) { sdMounted = sdMount(); }