diff --git a/arm9/src/backupmenu.c b/arm9/src/backupmenu.c index 9f02323..408062c 100644 --- a/arm9/src/backupmenu.c +++ b/arm9/src/backupmenu.c @@ -18,13 +18,16 @@ static bool delete(Menu* m); void backupMenu() { + clearScreen(&topScreen); + Menu* m = newMenu(); + setMenuHeader(m, "BACKUP MENU"); generateList(m); //no files found if (m->itemCount <= 0) { - messageBox("No backups found.\n"); + messageBox("\x1B[33mNo backups found.\n\x1B[47m"); } else { @@ -77,9 +80,9 @@ static int subMenu() Menu* m = newMenu(); - addMenuItem(m, "Restore", NULL); - addMenuItem(m, "Delete", NULL); - addMenuItem(m, "Back - [B]", NULL); + addMenuItem(m, "Restore", NULL, 0); + addMenuItem(m, "Delete", NULL, 0); + addMenuItem(m, "Back - [B]", NULL, 0); printMenu(m); @@ -145,7 +148,7 @@ static void generateList(Menu* m) char* path = (char*)malloc(strlen(BACKUP_PATH) + strlen(ent->d_name) + 8); sprintf(path, "%s/%s", BACKUP_PATH, ent->d_name); - addMenuItem(m, ent->d_name, path); + addMenuItem(m, ent->d_name, path, 0); free(path); } @@ -166,7 +169,7 @@ static void generateList(Menu* m) static void restore(Menu* m) { - char* fpath = m->items[m->cursor]; + char* fpath = m->items[m->cursor].value; bool choice = NO; { @@ -183,7 +186,7 @@ static void restore(Menu* m) { if (!fpath) { - messageBox("Failed to restore backup.\n"); + messageBox("\x1B[31mFailed to restore backup.\n\x1B[47m"); } else { @@ -191,11 +194,11 @@ static void restore(Menu* m) if (!copyDir(fpath, "/title")) { - messagePrint("\nFailed to restore backup.\n"); + messagePrint("\x1B[31m\nFailed to restore backup.\n\x1B[47m"); } else { - messagePrint("\nBackup restored.\n"); + messagePrint("\x1B[42m\nBackup restored.\n\x1B[47m"); } } } @@ -205,7 +208,7 @@ static bool delete(Menu* m) { if (!m) return false; - char* fpath = m->items[m->cursor]; + char* fpath = m->items[m->cursor].value; bool result = false; bool choice = NO; @@ -223,13 +226,13 @@ static bool delete(Menu* m) { if (!fpath) { - messageBox("Failed to delete backup.\n"); + messageBox("\x1B[31mFailed to delete backup.\n\x1B[47m"); } else { if (!dirExists(fpath)) { - messageBox("Failed to delete backup.\n"); + messageBox("\x1B[31mFailed to delete backup.\n\x1B[47m"); } else { @@ -238,11 +241,11 @@ static bool delete(Menu* m) if (deleteDir(fpath)) { result = true; - messagePrint("\nBackup deleted.\n"); + messagePrint("\x1B[42m\nBackup deleted.\n\x1B[47m"); } else { - messagePrint("\nError deleting backup.\n"); + messagePrint("\n\x1B[31mError deleting backup.\n\x1B[47m"); } } } diff --git a/arm9/src/install.c b/arm9/src/install.c index 12d4472..8c20e84 100644 --- a/arm9/src/install.c +++ b/arm9/src/install.c @@ -1,8 +1,9 @@ #include "install.h" -#include "fat12.h" +#include "sav.h" #include "main.h" #include "message.h" #include "maketmd.h" +#include "rom.h" #include "storage.h" #include @@ -42,7 +43,9 @@ static bool _patchGameCode(tDSiHeader* h) } while (_titleIsUsed(h)); + iprintf("\x1B[42m"); //green iprintf("Done\n"); + iprintf("\x1B[47m"); //white return true; } @@ -56,26 +59,22 @@ static bool _iqueHack(tDSiHeader* h) if (h->ndshdr.reserved1[8] == 0x80) { iprintf("iQue Hack..."); + h->ndshdr.reserved1[8] = 0x00; + + iprintf("\x1B[42m"); //green iprintf("Done\n"); + iprintf("\x1B[47m"); //white return true; } return false; } -static unsigned long long _getSize(FILE* f, tDSiHeader* h) +static unsigned long long _getSaveDataSize(tDSiHeader* h) { - iprintf("Install Size: "); - swiWaitForVBlank(); - unsigned long long size = 0; - //get app size - if (f) - size = getFileSize(f); - - //add save file size if (h) { size += h->public_sav_size; @@ -86,9 +85,6 @@ static unsigned long long _getSize(FILE* f, tDSiHeader* h) size += 0x4000; } - printBytes(size); - iprintf("\n"); - return size; } @@ -99,11 +95,15 @@ static bool _checkSdSpace(unsigned long long size) if (getSDCardFree() < size) { + iprintf("\x1B[31m"); //red iprintf("No\n"); + iprintf("\x1B[47m"); //white return false; } + iprintf("\x1B[42m"); //green iprintf("Yes\n"); + iprintf("\x1B[47m"); //white return true; } @@ -114,11 +114,15 @@ static bool _checkDsiSpace(unsigned long long size) if (getDsiFree() < size) { + iprintf("\x1B[31m"); //red iprintf("No\n"); + iprintf("\x1B[47m"); //white return false; } + iprintf("\x1B[42m"); //green iprintf("Yes\n"); + iprintf("\x1B[47m"); //white return true; } @@ -129,26 +133,15 @@ static bool _openMenuSlot() if (getMenuSlotsFree() <= 0) { + iprintf("\x1B[31m"); //red iprintf("No\n"); + iprintf("\x1B[47m"); //white return choicePrint("Try installing anyway?"); } + iprintf("\x1B[42m"); //green iprintf("Yes\n"); - return true; -} - -static bool _isDSiRom(tDSiHeader* h) -{ - //high title id must be one of four - if (h->tid_high != 0x00030004 && - h->tid_high != 0x00030005 && - h->tid_high != 0x00030015 && - h->tid_high != 0x00030017) - { - iprintf("Error: This is not a DSi rom.\n"); - return false; - } - + iprintf("\x1B[47m"); //white return true; } @@ -163,7 +156,9 @@ static void _createPublicSav(tDSiHeader* h, char* dataPath) if (!dataPath) { + iprintf("\x1B[31m"); //red iprintf("Failed\n"); + iprintf("\x1B[47m"); //white } else { @@ -174,7 +169,9 @@ static void _createPublicSav(tDSiHeader* h, char* dataPath) if (!f) { + iprintf("\x1B[31m"); //red iprintf("Failed\n"); + iprintf("\x1B[47m"); //white } else { @@ -182,7 +179,9 @@ static void _createPublicSav(tDSiHeader* h, char* dataPath) fputc(0, f); initFatHeader(f); + iprintf("\x1B[42m"); //green iprintf("Done\n"); + iprintf("\x1B[47m"); //white } fclose(f); @@ -202,7 +201,9 @@ static void _createPrivateSav(tDSiHeader* h, char* dataPath) if (!dataPath) { + iprintf("\x1B[31m"); //red iprintf("Failed\n"); + iprintf("\x1B[47m"); //white } else { @@ -213,7 +214,9 @@ static void _createPrivateSav(tDSiHeader* h, char* dataPath) if (!f) { + iprintf("\x1B[31m"); //red iprintf("Failed\n"); + iprintf("\x1B[47m"); //white } else { @@ -221,7 +224,9 @@ static void _createPrivateSav(tDSiHeader* h, char* dataPath) fputc(0, f); initFatHeader(f); + iprintf("\x1B[42m"); //green iprintf("Done\n"); + iprintf("\x1B[47m"); //white } fclose(f); @@ -241,7 +246,9 @@ static void _createBannerSav(tDSiHeader* h, char* dataPath) if (!dataPath) { + iprintf("\x1B[31m"); //red iprintf("Failed\n"); + iprintf("\x1B[47m"); //white } else { @@ -252,14 +259,18 @@ static void _createBannerSav(tDSiHeader* h, char* dataPath) if (!f) { + iprintf("\x1B[31m"); //red iprintf("Failed\n"); + iprintf("\x1B[47m"); //white } else { fseek(f, 0x4000 - 1, SEEK_SET); fputc(0, f); + iprintf("\x1B[42m"); //green iprintf("Done\n"); + iprintf("\x1B[47m"); //white } fclose(f); @@ -274,10 +285,14 @@ bool install(char* fpath, bool systemTitle) //confirmation message { - char msg[512]; - sprintf(msg, "Are you sure you want to install\n%s\n", fpath); + char str[] = "Are you sure you want to install\n"; + char* msg = (char*)malloc(strlen(str) + strlen(fpath) + 8); + sprintf(msg, "%s%s\n", str, fpath); - if (choiceBox(msg) == NO) + bool choice = choiceBox(msg); + free(msg); + + if (choice == NO) return false; } @@ -285,33 +300,49 @@ bool install(char* fpath, bool systemTitle) clearScreen(&bottomScreen); iprintf("Installing %s\n\n", fpath); swiWaitForVBlank(); - tDSiHeader* header = (tDSiHeader*)malloc(sizeof(tDSiHeader)); - FILE* f = fopen(fpath, "rb"); + tDSiHeader* h = getRomHeader(fpath); - if (!f) + if (!h) { - iprintf("Error: could not open file.\n"); + iprintf("\x1B[31m"); //red + iprintf("Error: "); + iprintf("\x1B[33m"); //yellow + iprintf("Could not open file.\n"); + iprintf("\x1B[47m"); //white goto error; } else { bool fixHeader = false; - //read header - fseek(f, 0, SEEK_SET); - fread(header, sizeof(tDSiHeader), 1, f); - - if (_patchGameCode(header)) + if (_patchGameCode(h)) fixHeader = true; - if (!_isDSiRom(header)) + //title id must be one of these + if (h->tid_high == 0x00030004 || + h->tid_high == 0x00030005 || + h->tid_high == 0x00030015 || + h->tid_high == 0x00030017) + {} + else + { + iprintf("\x1B[31m"); //red + iprintf("Error: "); + iprintf("\x1B[33m"); //yellow + iprintf("This is not a DSi rom.\n"); + iprintf("\x1B[47m"); //white goto error; + } - unsigned long long fileSize = getFileSize(f); - unsigned long long installSize = _getSize(f, header); + //get install size + iprintf("Install Size: "); + swiWaitForVBlank(); + + unsigned long long fileSize = getRomSize(fpath); + unsigned long long installSize = fileSize + _getSaveDataSize(h); - //do not need file opened anymore - fclose(f); + printBytes(installSize); + iprintf("\n"); if (!_checkSdSpace(installSize)) goto error; @@ -324,20 +355,22 @@ bool install(char* fpath, bool systemTitle) { iprintf("System Title Patch..."); swiWaitForVBlank(); - header->tid_high = 0x00030015; + h->tid_high = 0x00030015; + iprintf("\x1B[42m"); //green iprintf("Done\n"); + iprintf("\x1B[47m"); //white fixHeader = true; } //skip nand check if system title - if (header->tid_high != 0x00030015) + if (h->tid_high != 0x00030015) { if (!_checkDsiSpace(installSize)) { if (choicePrint("Install as system title?")) { - header->tid_high = 0x00030015; + h->tid_high = 0x00030015; fixHeader = true; } else @@ -348,22 +381,29 @@ bool install(char* fpath, bool systemTitle) } } - if (_iqueHack(header)) - fixHeader = true; - - //check if title is free - if (_titleIsUsed(header)) - { - char msg[512]; - sprintf(msg, "Title %08x is already used.\nInstall anyway?", (unsigned int)header->tid_low); - - if (choicePrint(msg) == NO) - goto error; - } + if (_iqueHack(h)) + fixHeader = true; //create title directory /title/XXXXXXXX/XXXXXXXX char dirPath[32]; - sprintf(dirPath, "/title/%08x/%08x", (unsigned int)header->tid_high, (unsigned int)header->tid_low); + sprintf(dirPath, "/title/%08x/%08x", (unsigned int)h->tid_high, (unsigned int)h->tid_low); + + //check if title is free + if (_titleIsUsed(h)) + { + char msg[64]; + sprintf(msg, "Title %08x is already used.\nInstall anyway?", (unsigned int)h->tid_low); + + if (choicePrint(msg) == NO) + goto error; + + else + { + iprintf("\nDeleting:\n"); + deleteDir(dirPath); + iprintf("\n"); + } + } mkdir(dirPath, 0777); @@ -384,26 +424,67 @@ bool install(char* fpath, bool systemTitle) //copy nds file to app { - if (copyFile(fpath, appPath) == 0) + int result = 0; + + if (!romIsCia(fpath)) + result = copyFile(fpath, appPath); + else + result = copyFilePart(fpath, 0x3900, fileSize, appPath); + + if (result != 0) { + iprintf("\x1B[31m"); //red iprintf("Failed\n"); + iprintf("\x1B[33m"); //yellow + + switch (result) + { + case 1: + iprintf("Empty input path.\n"); + break; + + case 2: + iprintf("Empty output path.\n"); + break; + + case 3: + iprintf("Error opening input file.\n"); + break; + + case 4: + iprintf("Error opening output file.\n"); + break; + } + + iprintf("\x1B[47m"); //white + goto error; } + iprintf("\x1B[42m"); //green iprintf("Done\n"); + iprintf("\x1B[47m"); //white } //pad out banner if it is the last part of the file { - if (header->ndshdr.bannerOffset == fileSize - 0x1C00) + if (h->ndshdr.bannerOffset == fileSize - 0x1C00) { iprintf("Padding banner..."); swiWaitForVBlank(); if (padFile(appPath, 0x7C0) == false) + { + iprintf("\x1B[31m"); //red iprintf("Failed\n"); + iprintf("\x1B[47m"); //white + } else + { + iprintf("\x1B[42m"); //green iprintf("Done\n"); + iprintf("\x1B[47m"); //white + } } } @@ -415,25 +496,29 @@ bool install(char* fpath, bool systemTitle) swiWaitForVBlank(); //fix header checksum - header->ndshdr.headerCRC16 = swiCRC16(0xFFFF, header, 0x15E); + h->ndshdr.headerCRC16 = swiCRC16(0xFFFF, h, 0x15E); //fix RSA signature u8 buffer[20]; - swiSHA1Calc(&buffer, header, 0xE00); - memcpy(&(header->rsa_signature[0x6C]), buffer, 20); + swiSHA1Calc(&buffer, h, 0xE00); + memcpy(&(h->rsa_signature[0x6C]), buffer, 20); - f = fopen(appPath, "r+"); + FILE* f = fopen(appPath, "r+"); if (!f) { + iprintf("\x1B[31m"); //red iprintf("Failed\n"); + iprintf("\x1B[47m"); //white } else { fseek(f, 0, SEEK_SET); - fwrite(header, sizeof(tDSiHeader), 1, f); + fwrite(h, sizeof(tDSiHeader), 1, f); + iprintf("\x1B[42m"); //green iprintf("Done\n"); + iprintf("\x1B[47m"); //white } fclose(f); @@ -458,25 +543,27 @@ bool install(char* fpath, bool systemTitle) mkdir(dataPath, 0777); - _createPublicSav(header, dataPath); - _createPrivateSav(header, dataPath); - _createBannerSav(header, dataPath); + _createPublicSav(h, dataPath); + _createPrivateSav(h, dataPath); + _createBannerSav(h, dataPath); } //end result = true; - iprintf("\nInstallation complete.\nBack - [B]\n"); - keyWait(KEY_A | KEY_B); - } + iprintf("\x1B[42m"); //green + iprintf("\nInstallation complete.\n"); + iprintf("\x1B[47m"); //white + iprintf("Back - [B]\n"); + keyWait(KEY_A | KEY_B); - goto complete; + goto complete; + } error: - messagePrint("\nInstallation failed.\n"); + messagePrint("\x1B[31m\nInstallation failed.\n\x1B[47m"); complete: - fclose(f); - free(header); + free(h); return result; } \ No newline at end of file diff --git a/arm9/src/installmenu.c b/arm9/src/installmenu.c index 18a6fd8..2aeb64b 100644 --- a/arm9/src/installmenu.c +++ b/arm9/src/installmenu.c @@ -1,5 +1,5 @@ #include "main.h" -#include "app.h" +#include "rom.h" #include "install.h" #include "menu.h" #include "storage.h" @@ -13,28 +13,41 @@ enum { INSTALL_MENU_BACK }; +static char currentDir[512] = ""; + static void generateList(Menu* m); static void printItem(Menu* m); static int subMenu(); static bool delete(Menu* m); +static void _setHeader(Menu* m) +{ + if (!m) return; + if (currentDir[0] == '\0') + setMenuHeader(m, "/"); + else + setMenuHeader(m, currentDir); +} + void installMenu() { Menu* m = newMenu(); + _setHeader(m); generateList(m); //no files found - if (m->itemCount <= 0) +/* if (m->itemCount <= 0) { clearScreen(&bottomScreen); + iprintf("\x1B[31m"); //red iprintf("No files found.\n"); - iprintf("Place .nds, .app, or .dsi files in %s\n", ROM_PATH); + iprintf("\x1B[47m"); //white iprintf("\nBack - [B]\n"); keyWait(KEY_B | KEY_A | KEY_START); } - else + else*/ { while (1) { @@ -51,51 +64,70 @@ void installMenu() } //back - if (keysDown() & KEY_B || m->itemCount <= 0) + if (keysDown() & KEY_B) { - break; + char* ptr = strrchr(currentDir, '/'); + + if (ptr) + { + *ptr = '\0'; + _setHeader(m); + resetMenu(m); + generateList(m); + printMenu(m); + } + else + { + break; + } } + else if (keysDown() & KEY_X) + break; + //selection else if (keysDown() & KEY_A) { - switch (subMenu()) + if (m->itemCount > 0) { - case INSTALL_MENU_INSTALL: + if (m->items[m->cursor].directory == false) { - if (install(m->items[m->cursor], false)) + //nds file + switch (subMenu()) { - resetMenu(m); - generateList(m); - } - } - break; - - case INSTALL_MENU_SYSTEM_TITLE: - { - if (install(m->items[m->cursor], true)) - { - resetMenu(m); - generateList(m); - } - } - break; + case INSTALL_MENU_INSTALL: + install(m->items[m->cursor].value, false); + break; + + case INSTALL_MENU_SYSTEM_TITLE: + install(m->items[m->cursor].value, true); + break; - case INSTALL_MENU_DELETE: - { - if (delete(m)) - { - resetMenu(m); - generateList(m); + case INSTALL_MENU_DELETE: + { + if (delete(m)) + { + resetMenu(m); + generateList(m); + } + } + break; + + case INSTALL_MENU_BACK: + break; } } - break; + else + { + //directory + sprintf(currentDir, "%s", m->items[m->cursor].value); + _setHeader(m); + resetMenu(m); + generateList(m); + } - case INSTALL_MENU_BACK: - break; + printMenu(m); } - - printMenu(m); } } } @@ -116,7 +148,7 @@ static void generateList(Menu* m) bool done = false; struct dirent* ent; - DIR* dir = opendir(ROM_PATH); + DIR* dir = opendir(currentDir); if (dir) { @@ -128,14 +160,35 @@ static void generateList(Menu* m) if (strcmp(".", ent->d_name) == 0 || strcmp("..", ent->d_name) == 0) continue; - if (ent->d_type != DT_DIR) + if (ent->d_type == DT_DIR) + { + if (count < m->page * ITEMS_PER_PAGE) + count += 1; + + else + { + if (m->itemCount >= ITEMS_PER_PAGE) + done = true; + + else + { + char* fpath = (char*)malloc(strlen(currentDir) + strlen(ent->d_name) + 8); + sprintf(fpath, "%s/%s", currentDir, ent->d_name); + + addMenuItem(m, ent->d_name, fpath, 1); + } + } + } + else { if (strstr(ent->d_name, ".nds") != NULL || strstr(ent->d_name, ".app") != NULL || strstr(ent->d_name, ".dsi") != NULL || + strstr(ent->d_name, ".cia") != NULL || strstr(ent->d_name, ".NDS") != NULL || strstr(ent->d_name, ".APP") != NULL || - strstr(ent->d_name, ".DSI") != NULL) + strstr(ent->d_name, ".DSI") != NULL || + strstr(ent->d_name, ".CIA") != NULL) { if (count < m->page * ITEMS_PER_PAGE) count += 1; @@ -147,10 +200,10 @@ static void generateList(Menu* m) else { - char* fpath = (char*)malloc(strlen(ROM_PATH) + strlen(ent->d_name) + 8); - sprintf(fpath, "%s/%s", ROM_PATH, ent->d_name); + char* fpath = (char*)malloc(strlen(currentDir) + strlen(ent->d_name) + 8); + sprintf(fpath, "%s/%s", currentDir, ent->d_name); - addMenuItem(m, ent->d_name, fpath); + addMenuItem(m, ent->d_name, fpath, 0); free(fpath); } @@ -174,7 +227,12 @@ static void generateList(Menu* m) static void printItem(Menu* m) { if (!m) return; - printAppInfo(m->items[m->cursor]); + if (m->itemCount <= 0) return; + + if (m->items[m->cursor].directory) + clearScreen(&topScreen); + else + printRomInfo(m->items[m->cursor].value); } static int subMenu() @@ -183,10 +241,10 @@ static int subMenu() Menu* m = newMenu(); - addMenuItem(m, "Install", NULL); - addMenuItem(m, "Install as System Title", NULL); - addMenuItem(m, "Delete", NULL); - addMenuItem(m, "Back - [B]", NULL); + addMenuItem(m, "Install", NULL, 0); + addMenuItem(m, "Install as System Title", NULL, 0); + addMenuItem(m, "Delete", NULL, 0); + addMenuItem(m, "Back - [B]", NULL, 0); printMenu(m); @@ -219,7 +277,7 @@ static bool delete(Menu* m) { if (!m) return false; - char* fpath = m->items[m->cursor]; + char* fpath = m->items[m->cursor].value; bool result = false; bool choice = NO; @@ -237,18 +295,18 @@ static bool delete(Menu* m) { if (!fpath) { - messageBox("Could not delete file."); + messageBox("\x1B[31mCould not delete file.\x1B[47m"); } else { if (remove(fpath) == 0) { result = true; - messageBox("File deleted."); + messageBox("\x1B[42mFile deleted.\x1B[47m"); } else { - messageBox("Could not delete file."); + messageBox("\x1B[31mCould not delete file.\x1B[47m"); } } } diff --git a/arm9/src/main.c b/arm9/src/main.c index 806872e..8c9ece5 100644 --- a/arm9/src/main.c +++ b/arm9/src/main.c @@ -3,7 +3,7 @@ #include "message.h" #include -#define VERSION "0.6.5 beta" +#define VERSION "0.6.8" enum { MAIN_MENU_INSTALL, @@ -43,12 +43,13 @@ static int _mainMenu(int cursor) //menu Menu* m = newMenu(); + setMenuHeader(m, "MAIN MENU"); - addMenuItem(m, "Install", NULL); - addMenuItem(m, "Titles", NULL); - addMenuItem(m, "Restore", NULL); - addMenuItem(m, "Test", NULL); - addMenuItem(m, "Shut Down", NULL); + addMenuItem(m, "Install", NULL, 0); + addMenuItem(m, "Titles", NULL, 0); + addMenuItem(m, "Restore", NULL, 0); + addMenuItem(m, "Test", NULL, 0); + addMenuItem(m, "Shut Down", NULL, 0); m->cursor = cursor; @@ -81,14 +82,14 @@ int main(int argc, char **argv) //DSi check if (!isDSiMode()) { - messageBox("Error: This app is only for the DSi.\n"); + messageBox("\x1B[31mError:\x1B[33m This app is only for DSi.\x1B[47m"); return 0; } //setup sd card access if (!fatInitDefault()) { - messageBox("fatInitDefault()...Failed\n"); + messageBox("fatInitDefault()...\x1B[31mFailed\n\x1B[47m"); return 0; } diff --git a/arm9/src/maketmd.c b/arm9/src/maketmd.c index a44b68e..b9b7e87 100644 --- a/arm9/src/maketmd.c +++ b/arm9/src/maketmd.c @@ -141,7 +141,9 @@ int maketmd(char* input, char* tmdPath) iprintf("by Przemyslaw Skryjomski\n\t(Tuxality)\n"); if(input == NULL || tmdPath == NULL) { + iprintf("\x1B[33m"); //yellow iprintf("\nUsage: %s file.app \n", "maketmd"); + iprintf("\x1B[47m"); //white return 1; } @@ -149,7 +151,9 @@ int maketmd(char* input, char* tmdPath) FILE* app = fopen(input, "rb"); if(!app) { + iprintf("\x1B[31m"); //red iprintf("Error at opening %s for reading.\n", input); + iprintf("\x1B[47m"); //white return 1; } @@ -159,7 +163,9 @@ int maketmd(char* input, char* tmdPath) if (!tmd) { fclose(app); + iprintf("\x1B[31m"); //white iprintf("Error at opening %s for writing.\n", tmdPath); + iprintf("\x1B[47m"); //white return 1; } diff --git a/arm9/src/menu.c b/arm9/src/menu.c index b016115..733216c 100644 --- a/arm9/src/menu.c +++ b/arm9/src/menu.c @@ -10,11 +10,13 @@ Menu* newMenu() m->itemCount = 0; m->nextPage = false; m->changePage = 0; + m->header[0] = '\0'; for (int i = 0; i < ITEMS_PER_PAGE; i++) { - m->labels[i] = NULL; - m->items[i] = NULL; + m->items[i].directory = false; + m->items[i].label = NULL; + m->items[i].value = NULL; } return m; @@ -30,28 +32,48 @@ void freeMenu(Menu* m) m = NULL; } -void addMenuItem(Menu* m, char const* label, char const* value) +void addMenuItem(Menu* m, char const* label, char const* value, bool directory) { if (!m) return; int i = m->itemCount; if (i >= ITEMS_PER_PAGE) return; + m->items[i].directory = directory; + if (label) { - m->labels[i] = (char*)malloc(32); - sprintf(m->labels[i], "%.31s", label); + m->items[i].label = (char*)malloc(32); + sprintf(m->items[i].label, "%.31s", label); } if (value) { - m->items[i] = (char*)malloc(strlen(value)+1); - sprintf(m->items[i], "%s", value); + m->items[i].value = (char*)malloc(strlen(value)+1); + sprintf(m->items[i].value, "%s", value); } m->itemCount += 1; } +void setMenuHeader(Menu* m, char* str) +{ + if (!m) return; + + if (!str) + { + m->header[0] = '\0'; + return; + } + + char* strPtr = str; + + if (strlen(strPtr) > 30) + strPtr = str + (strlen(strPtr) - 30); + + sprintf(m->header, "%.30s", strPtr); +} + void resetMenu(Menu* m) { m->cursor = 0; @@ -66,16 +88,16 @@ void clearMenu(Menu* m) for (int i = 0; i < ITEMS_PER_PAGE; i++) { - if (m->labels[i]) + if (m->items[i].label) { - free(m->labels[i]); - m->labels[i] = NULL; + free(m->items[i].label); + m->items[i].label = NULL; } - if (m->items[i]) + if (m->items[i].value) { - free(m->items[i]); - m->items[i] = NULL; + free(m->items[i].value); + m->items[i].value = NULL; } } @@ -88,23 +110,40 @@ void printMenu(Menu* m) if (!m) return; + //header + iprintf("\x1B[42m"); //green + iprintf("%.30s\n\n", m->header); + iprintf("\x1B[47m"); //white + + if (m->itemCount <= 0) + { + iprintf("Back - [B]\n"); + return; + } + + //items for (int i = 0; i < m->itemCount; i++) { - if (m->labels[i]) - iprintf(" %.30s\n", m->labels[i]); + if (m->items[i].label) + { + if (m->items[i].directory) + iprintf(" [%.28s]\n", m->items[i].label); + else + iprintf(" %.30s\n", m->items[i].label); + } else iprintf(" \n"); } - //cursor - iprintf("\x1b[%d;0H>", m->cursor); + //cursor + iprintf("\x1b[%d;0H>", 2 + m->cursor); //scroll arrows if (m->page > 0) - iprintf("\x1b[0;31H^"); + iprintf("\x1b[2;31H^"); if (m->nextPage) - iprintf("\x1b[22;31Hv"); + iprintf("\x1b[21;31Hv"); } static void _moveCursor(Menu* m, int dir) @@ -127,7 +166,7 @@ static void _moveCursor(Menu* m, int dir) else if (m->cursor > m->itemCount-1) { - if (m->cursor >= ITEMS_PER_PAGE) + if (m->nextPage && m->cursor >= ITEMS_PER_PAGE) { m->changePage = 1; m->cursor = 0; diff --git a/arm9/src/menu.h b/arm9/src/menu.h index 518ec9b..088905c 100644 --- a/arm9/src/menu.h +++ b/arm9/src/menu.h @@ -3,7 +3,13 @@ #include -#define ITEMS_PER_PAGE 23 +#define ITEMS_PER_PAGE 20 + +typedef struct { + bool directory; + char* label; + char* value; +} Item; typedef struct { int cursor; @@ -11,14 +17,15 @@ typedef struct { int itemCount; bool nextPage; int changePage; - char* labels[ITEMS_PER_PAGE]; - char* items[ITEMS_PER_PAGE]; + char header[32]; + Item items[ITEMS_PER_PAGE]; } Menu; Menu* newMenu(); void freeMenu(Menu* m); -void addMenuItem(Menu* m, char const* label, char const* value); +void addMenuItem(Menu* m, char const* label, char const* value, bool directory); +void setMenuHeader(Menu* m, char* str); void resetMenu(Menu* m); void clearMenu(Menu* m); diff --git a/arm9/src/message.c b/arm9/src/message.c index 400ea6b..ab6706e 100644 --- a/arm9/src/message.c +++ b/arm9/src/message.c @@ -20,7 +20,9 @@ bool choiceBox(char* message) clearScreen(&bottomScreen); + iprintf("\x1B[33m"); //yellow iprintf("%s\n", message); + iprintf("\x1B[47m"); //white iprintf("\x1b[%d;0H\tYes\n\tNo\n", choiceRow); while (1) @@ -55,7 +57,9 @@ bool choicePrint(char* message) { bool choice = NO; + iprintf("\x1B[33m"); //yellow iprintf("\n%s\n", message); + iprintf("\x1B[47m"); //white iprintf("Yes - [A]\nNo - [B]\n"); while (1) diff --git a/arm9/src/rom.c b/arm9/src/rom.c new file mode 100644 index 0000000..82ae5e1 --- /dev/null +++ b/arm9/src/rom.c @@ -0,0 +1,281 @@ +#include "rom.h" +#include "main.h" +#include "storage.h" +#include +#include +#include + +tDSiHeader* getRomHeader(char const* fpath) +{ + if (!fpath) return NULL; + + tDSiHeader* h = NULL; + FILE* f = fopen(fpath, "rb"); + + if (f) + { + h = (tDSiHeader*)malloc(sizeof(tDSiHeader)); + + if (h) + { + if (romIsCia(fpath)) + fseek(f, 0x3900, SEEK_SET); + else + fseek(f, 0, SEEK_SET); + + fread(h, sizeof(tDSiHeader), 1, f); + } + + fclose(f); + } + + return h; +} + +tNDSBanner* getRomBanner(char const* fpath) +{ + if (!fpath) return NULL; + + tDSiHeader* h = getRomHeader(fpath); + tNDSBanner* b = NULL; + + if (h) + { + FILE* f = fopen(fpath, "rb"); + + if (f) + { + b = (tNDSBanner*)malloc(sizeof(tNDSBanner)); + + if (b) + { + if (romIsCia(fpath)) + fseek(f, 0x3900, SEEK_SET); + else + fseek(f, 0, SEEK_SET); + + fseek(f, h->ndshdr.bannerOffset, SEEK_CUR); + fread(b, sizeof(tNDSBanner), 1, f); + } + } + + free(h); + fclose(f); + } + + return b; +} + +bool getGameTitle(tNDSBanner* b, char* out, bool full) +{ + if (!b) return false; + if (!out) return false; + + //get system language + int lang = PersonalData->language; + + //not japanese or chinese + if (lang == 0 || lang == 6) + lang = 1; + + //read title + u16 c; + for (int i = 0; i < 128; i++) + { + c = b->titles[lang][i]; + + //remove accents + if (c == 0x00F3) + c = 'o'; + + if (c == 0x00E1) + c = 'a'; + + out[i] = (char)c; + + if (!full && out[i] == '\n') + { + out[i] = '\0'; + break; + } + } + out[128] = '\0'; + + return true; +} + +bool getGameTitlePath(char const* fpath, char* out, bool full) +{ + if (!fpath) return false; + if (!out) return false; + + tNDSBanner* b = getRomBanner(fpath); + bool result = getGameTitle(b, out, full); + + free(b); + return result; +} + +bool getRomLabel(tDSiHeader* h, char* out) +{ + if (!h) return false; + if (!out) return false; + + sprintf(out, "%.12s", h->ndshdr.gameTitle); + + return true; +} + +bool getRomCode(tDSiHeader* h, char* out) +{ + if (!h) return false; + if (!out) return false; + + sprintf(out, "%.4s", h->ndshdr.gameCode); + + return true; +} + +bool getTitleId(tDSiHeader* h, u32* low, u32* high) +{ + if (!h) return false; + + if (low != NULL) + *low = h->tid_low; + + if (high != NULL) + *high = h->tid_high; + + return true; +} + +void printRomInfo(char const* fpath) +{ + clearScreen(&topScreen); + + if (!fpath) return; + + tDSiHeader* h = getRomHeader(fpath); + tNDSBanner* b = getRomBanner(fpath); + + if (!isDsiHeader(h)) + { + iprintf("Could not read dsi header.\n"); + } + else + { + if (!b) + { + iprintf("Could not read banner.\n"); + } + else + { + //proper title + { + char gameTitle[128+1]; + getGameTitle(b, gameTitle, true); + + iprintf("%s\n\n", gameTitle); + } + + //file size + { + iprintf("Size: "); + printBytes(getRomSize(fpath)); + iprintf("\n"); + } + + iprintf("Label: %.12s\n", h->ndshdr.gameTitle); + iprintf("Game Code: %.4s\n", h->ndshdr.gameCode); + + //system type + { + iprintf("Unit Code: "); + + switch (h->ndshdr.unitCode) + { + case 0: iprintf("NDS"); break; + case 2: iprintf("NDS+DSi"); break; + case 3: iprintf("DSi"); break; + default: iprintf("unknown"); + } + + iprintf("\n"); + } + + //application type + { + iprintf("Program Type: "); + + switch (h->ndshdr.reserved1[7]) + { + case 0x3: iprintf("Normal"); break; + case 0xB: iprintf("Sys"); break; + case 0xF: iprintf("Debug/Sys"); break; + default: iprintf("unknown"); + } + + iprintf("\n"); + } + + //DSi title ids + { + if (h->tid_high == 0x00030004 || + h->tid_high == 0x00030005 || + h->tid_high == 0x00030015 || + h->tid_high == 0x00030017 || + h->tid_high == 0x00030000) + { + iprintf("Title ID: %08x %08x\n", (unsigned int)h->tid_high, (unsigned int)h->tid_low); + } + } + + //print full file path + iprintf("\n%s\n", fpath); + } + } + + free(b); + free(h); +} + +unsigned long long getRomSize(char const* fpath) +{ + if (!fpath) return 0; + + unsigned long long size = 0; + FILE* f = fopen(fpath, "rb"); + + if (f) + { + //cia + if (romIsCia(fpath)) + { + unsigned char bytes[4] = { 0 }; + fseek(f, 0x38D0, SEEK_SET); + fread(bytes, 4, 1, f); + size = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]; + } + else + { + fseek(f, 0, SEEK_END); + size = ftell(f); + } + } + + fclose(f); + return size; +} + +bool romIsCia(char const* fpath) +{ + if (!fpath) return false; + return (strstr(fpath, ".cia") != NULL || strstr(fpath, ".CIA") != NULL); +} + +bool isDsiHeader(tDSiHeader* h) +{ + if (!h) return false; + + return ( h->tid_low == (unsigned int)((h->ndshdr.gameCode[0] << 24) | (h->ndshdr.gameCode[1] << 16) | (h->ndshdr.gameCode[2] << 8) | h->ndshdr.gameCode[3]) ); +} \ No newline at end of file diff --git a/arm9/src/rom.h b/arm9/src/rom.h new file mode 100644 index 0000000..97f322b --- /dev/null +++ b/arm9/src/rom.h @@ -0,0 +1,24 @@ +#ifndef ROM_H +#define ROM_H + +#include +#include + +tDSiHeader* getRomHeader(char const* fpath); +tNDSBanner* getRomBanner(char const* fpath); + +bool getGameTitle(tNDSBanner* b, char* out, bool full); +bool getGameTitlePath(char const* fpath, char* out, bool full); + +bool getRomLabel(tDSiHeader* h, char* out); +bool getRomCode(tDSiHeader* h, char* out); +bool getTitleId(tDSiHeader* h, u32* low, u32* high); + +void printRomInfo(char const* fpath); + +unsigned long long getRomSize(char const* fpath); + +bool romIsCia(char const* fpath); +bool isDsiHeader(tDSiHeader* h); + +#endif \ No newline at end of file diff --git a/arm9/src/sav.c b/arm9/src/sav.c new file mode 100644 index 0000000..90cdbde --- /dev/null +++ b/arm9/src/sav.c @@ -0,0 +1,123 @@ +#include "sav.h" +#include +#include + +static u32 _getClusterSize(u32 sizebytes) +{ + if (sizebytes < 573440) + return 512; + + else if (sizebytes < 5472256) + return 2048; + + else if (sizebytes < 17301504) + return 4096; + + else + return 2048; +} + +static u16 _getMaxFiles(u32 sizebytes) +{ + if (sizebytes < 573440) + return 16; + + else + return 256; +} + +//wip +static u16 _getFatz(u32 sizebytes) +{ + if (sizebytes <= 0x4000) //16 kb + return 1; + + else if (sizebytes <= 0x200000) //2 mb + return 3; + + else + return 6; +} + +//wip +static u16 _getTotSec16(u32 sizebytes, u16 bytesPerSec) +{ + if (sizebytes == 0x4000) //16 kb + return 27; + + return sizebytes / bytesPerSec; +} + +bool initFatHeader(FILE* f) +{ + if (!f) + return false; + + //get size + fseek(f, 0, SEEK_END); + u32 size = ftell(f); + + FATHeader* h = (FATHeader*)malloc(sizeof(FATHeader)); + + h->BS_JmpBoot[0] = 0xE9; + h->BS_JmpBoot[1] = 0; + h->BS_JmpBoot[2] = 0; + + h->BS_OEMName[0] = 'M'; + h->BS_OEMName[1] = 'S'; + h->BS_OEMName[2] = 'W'; + h->BS_OEMName[3] = 'I'; + h->BS_OEMName[4] = 'N'; + h->BS_OEMName[5] = '4'; + h->BS_OEMName[6] = '.'; + h->BS_OEMName[7] = '1'; + + h->BPB_BytesPerSec = 512; + h->BPB_SecPerClus = _getClusterSize(size) / h->BPB_BytesPerSec; + h->BPB_RsvdSecCnt = 1; + h->BPB_NumFATs = 2; + h->BPB_RootEntCnt = _getMaxFiles(size) * 2; + h->BPB_TotSec16 = _getTotSec16(size, h->BPB_BytesPerSec); // + h->BPB_Media = 0xF8; + h->BPB_FATSz16 = _getFatz(size); // + h->BPB_SecPerTrk = 0; + h->BPB_NumHeads = 0; + h->BPB_HiddSec = 0; + h->BPB_TotSec32 = 0; + h->BS_DrvNum = 0x07; + h->BS_Reserved1 = 0; + h->BS_BootSig = 0x29; + h->BS_VolID = 305419896; + + h->BS_VolLab[0] = 'V'; + h->BS_VolLab[1] = 'O'; + h->BS_VolLab[2] = 'L'; + h->BS_VolLab[3] = 'U'; + h->BS_VolLab[4] = 'M'; + h->BS_VolLab[5] = 'E'; + h->BS_VolLab[6] = 'L'; + h->BS_VolLab[7] = 'A'; + h->BS_VolLab[8] = 'B'; + h->BS_VolLab[9] = 'E'; + h->BS_VolLab[10] = 'L'; + + h->BS_FilSysType[0] = 'F'; + h->BS_FilSysType[1] = 'A'; + h->BS_FilSysType[2] = 'T'; + h->BS_FilSysType[3] = '1'; + h->BS_FilSysType[4] = '2'; + h->BS_FilSysType[5] = ' '; + h->BS_FilSysType[6] = ' '; + h->BS_FilSysType[7] = ' '; + + memset(h->BS_BootCode, 0, 448); + + h->BS_BootSign = 0xAA55; + + fseek(f, 0, SEEK_SET); + fwrite(h, sizeof(FATHeader), 1, f); + + free(h); + + return true; +} \ No newline at end of file diff --git a/arm9/src/sav.h b/arm9/src/sav.h new file mode 100644 index 0000000..514f342 --- /dev/null +++ b/arm9/src/sav.h @@ -0,0 +1,38 @@ +#ifndef SAV_H +#define SAV_H + +#include +#include +//http://elm-chan.org/docs/fat_e.html + +#pragma pack(push, 1) +typedef struct +{ + u8 BS_JmpBoot[3]; //0x0000 + u8 BS_OEMName[8]; //0x0003 + u16 BPB_BytesPerSec; //0x000B + u8 BPB_SecPerClus; //0x000D + u16 BPB_RsvdSecCnt; //0x000E + u8 BPB_NumFATs; + u16 BPB_RootEntCnt; + u16 BPB_TotSec16; + u8 BPB_Media; + u16 BPB_FATSz16; + u16 BPB_SecPerTrk; + u16 BPB_NumHeads; + u32 BPB_HiddSec; + u32 BPB_TotSec32; + u8 BS_DrvNum; + u8 BS_Reserved1; + u8 BS_BootSig; + u32 BS_VolID; + u8 BS_VolLab[11]; + u8 BS_FilSysType[8]; + u8 BS_BootCode[448]; + u16 BS_BootSign; +} FATHeader; +#pragma pack(push, 0) + +bool initFatHeader(FILE* f); + +#endif \ No newline at end of file diff --git a/arm9/src/storage.c b/arm9/src/storage.c index 867f5d8..4497ed5 100644 --- a/arm9/src/storage.c +++ b/arm9/src/storage.c @@ -36,6 +36,8 @@ void printProgressBar(float percent) { consoleSelect(&topScreen); + iprintf("\x1B[42m"); //green + //Print frame if (lastBars <= 0) { @@ -45,12 +47,14 @@ void printProgressBar(float percent) //Print bars if (bars > 0) - { + { for (int i = 0; i < bars; i++) - iprintf("\x1b[23;%dH|", 1 + i); + iprintf("\x1b[23;%dH|", 1 + i); } lastBars = bars; + + iprintf("\x1B[47m"); //white } } @@ -74,52 +78,75 @@ bool fileExists(char const* path) return true; } -bool copyFile(char const* in, char const* out) +int copyFile(char const* src, char const* dst) { - if (!in || !out) return false; + if (!src) return 1; - FILE* fin = fopen(in, "rb"); - FILE* fout = fopen(out, "wb"); + unsigned long long size = getFileSizePath(src); + return copyFilePart(src, 0, size, dst); +} - if (!fin || !fout) +int copyFilePart(char const* src, u32 offset, u32 size, char const* dst) +{ + if (!src) return 1; + if (!dst) return 2; + + FILE* fin = fopen(src, "rb"); + + if (!fin) { fclose(fin); - fclose(fout); - return false; + return 3; } else { - consoleSelect(&topScreen); + FILE* fout = fopen(dst, "wb"); - int bytesRead; - int totalBytesRead = 0; - int fileSize = getFileSize(fin); - - #define BUFF_SIZE 128 //Arbitrary. A value too large freezes the ds. - char* buffer = (char*)malloc(BUFF_SIZE); - - while (1) + if (!fout) { - bytesRead = fread(buffer, 1, BUFF_SIZE, fin); - fwrite(buffer, bytesRead, 1, fout); + fclose(fin); + fclose(fout); + return 4; + } + else + { + fseek(fin, offset, SEEK_SET); - totalBytesRead += bytesRead; - printProgressBar( ((float)totalBytesRead / (float)fileSize) ); + consoleSelect(&topScreen); - if (bytesRead != BUFF_SIZE) - break; + int bytesRead; + unsigned int totalBytesRead = 0; + + #define BUFF_SIZE 128 //Arbitrary. A value too large freezes the ds. + char* buffer = (char*)malloc(BUFF_SIZE); + + while (1) + { + unsigned int toRead = BUFF_SIZE; + if (size - totalBytesRead < BUFF_SIZE) + toRead = size - totalBytesRead; + + bytesRead = fread(buffer, 1, toRead, fin); + fwrite(buffer, bytesRead, 1, fout); + + totalBytesRead += bytesRead; + printProgressBar( ((float)totalBytesRead / (float)size) ); + + if (bytesRead != BUFF_SIZE) + break; + } + + clearProgressBar(); + consoleSelect(&bottomScreen); + + free(buffer); } - clearProgressBar(); - consoleSelect(&bottomScreen); - - free(buffer); + fclose(fout); } fclose(fin); - fclose(fout); - - return true; + return 0; } unsigned long long getFileSize(FILE* f) @@ -224,14 +251,42 @@ bool copyDir(char const* src, char const* dst) // iprintf("%s\n%s\n\n", fsrc, fdst); iprintf("%s...", fdst); - if(!copyFile(fsrc, fdst)) + + int ret = copyFile(fsrc, fdst); + + if(ret != 0) { + iprintf("\x1B[31m"); //red iprintf("Fail\n"); + iprintf("\x1B[33m"); //yellow + + switch (ret) + { + case 1: + iprintf("Empty input path.\n"); + break; + + case 2: + iprintf("Empty output path.\n"); + break; + + case 3: + iprintf("Error opening input file.\n"); + break; + + case 4: + iprintf("Error opening output file.\n"); + break; + } + + iprintf("\x1B[47m"); //white result = false; } else { + iprintf("\x1B[42m"); //green iprintf("Done\n"); + iprintf("\x1B[47m"); //white } free(fdst); @@ -288,12 +343,16 @@ bool deleteDir(char const* path) iprintf("%s...", fpath); if (remove(fpath) != 0) { + iprintf("\x1B[31m"); iprintf("Fail\n"); + iprintf("\x1B[47m"); result = false; } else { + iprintf("\x1B[42m"); iprintf("Done\n"); + iprintf("\x1B[47m"); } } } @@ -304,12 +363,16 @@ bool deleteDir(char const* path) iprintf("%s...", path); if (remove(path) != 0) { + iprintf("\x1B[31m"); iprintf("Fail\n"); + iprintf("\x1B[47m"); result = false; } else { + iprintf("\x1B[42m"); iprintf("Done\n"); + iprintf("\x1B[47m"); } return result; @@ -333,14 +396,14 @@ unsigned long long getDirSize(const char* path) if (ent->d_type == DT_DIR) { char fullpath[512]; - sprintf(fullpath, "%s%s/", path, ent->d_name); + sprintf(fullpath, "%s/%s", path, ent->d_name); size += getDirSize(fullpath); } else { - char fullpath[256]; - sprintf(fullpath, "%s%s", path, ent->d_name); + char fullpath[260]; + sprintf(fullpath, "%s/%s", path, ent->d_name); size += getFileSizePath(fullpath); } @@ -432,32 +495,36 @@ unsigned long long getSDCardFree() } //internal storage -int getDsiSize() +unsigned long long getDsiSize() { //The DSi has 256MB of internal storage. Some is unavailable and used by other things. //Find a better way to do this return 240 * 1024 * 1024; } -int getDsiFree() +unsigned long long getDsiFree() { //Get free space by subtracting file sizes in emulated nand folders //Find a better way to do this - int size = getDsiSize(); + long long size = getDsiSize(); - size -= getDirSize("/sys/"); - size -= getDirSize("/title/"); - size -= getDirSize("/ticket/"); - size -= getDirSize("/shared1/"); - size -= getDirSize("/shared2/"); - size -= getDirSize("/import/"); - size -= getDirSize("/tmp/"); - size -= getDirSize("/progress/"); + size -= getDirSize("/sys"); + size -= getDirSize("/title/0003000f"); + size -= getDirSize("/title/00030004"); + size -= getDirSize("/title/00030005"); + size -= getDirSize("/title/00030017"); + size -= getDirSize("/ticket"); + size -= getDirSize("/shared1"); + size -= getDirSize("/shared2"); + size -= getDirSize("/import"); + size -= getDirSize("/tmp"); + size -= getDirSize("/progress"); - size -= getDirSize("/photo/"); - size -= getDirSize("/private/"); + size -= getDirSize("/photo"); + size -= getDirSize("/private"); - size += getDirSize("/title/00030015/"); - - return size; + if (size < 0) + return 0; + + return (unsigned long long)size; } \ No newline at end of file diff --git a/arm9/src/storage.h b/arm9/src/storage.h index d6947d2..bdf3a65 100644 --- a/arm9/src/storage.h +++ b/arm9/src/storage.h @@ -5,7 +5,6 @@ #include #define BACKUP_PATH "/titlebackup" -#define ROM_PATH "/dsi" #define BYTES_PER_BLOCK (1024*128) //printing @@ -17,7 +16,8 @@ void clearProgressBar(); //Files bool fileExists(char const* path); -bool copyFile(char const* src, char const* dst); +int copyFile(char const* src, char const* dst); +int copyFilePart(char const* src, u32 offset, u32 size, char const* dst); unsigned long long getFileSize(FILE* f); unsigned long long getFileSizePath(char const* path); bool padFile(char const* path, int size); @@ -40,8 +40,8 @@ unsigned long long getSDCardFree(); #define getSDCardUsedSpace() (getSDCardSize() - getSDCardFree()) //internal storage -int getDsiSize(); -int getDsiFree(); +unsigned long long getDsiSize(); +unsigned long long getDsiFree(); #define getDsiUsed() (getDSIStorageSize() - getDSIStorageFree()) #endif \ No newline at end of file diff --git a/arm9/src/titlemenu.c b/arm9/src/titlemenu.c index aeca4c3..70414be 100644 --- a/arm9/src/titlemenu.c +++ b/arm9/src/titlemenu.c @@ -1,5 +1,5 @@ #include "main.h" -#include "app.h" +#include "rom.h" #include "menu.h" #include "message.h" #include "storage.h" @@ -20,6 +20,7 @@ static bool delete(Menu* m); void titleMenu() { Menu* m = newMenu(); + setMenuHeader(m, "INSTALLED TITLES"); generateList(m); //no titles @@ -146,9 +147,9 @@ static void generateList(Menu* m) sprintf(path, "%s/%s", contentPath, subent->d_name); char title[128]; - getAppTitle(path, title); + getGameTitlePath(path, title, false); - addMenuItem(m, title, path); + addMenuItem(m, title, path, 0); free(path); } @@ -180,7 +181,7 @@ static void generateList(Menu* m) static void printItem(Menu* m) { if (!m) return; - printAppInfo(m->items[m->cursor]); + printRomInfo(m->items[m->cursor].value); } static int subMenu() @@ -189,9 +190,9 @@ static int subMenu() Menu* m = newMenu(); - addMenuItem(m, "Backup", NULL); - addMenuItem(m, "Delete", NULL); - addMenuItem(m, "Back - [B]", NULL); + addMenuItem(m, "Backup", NULL, 0); + addMenuItem(m, "Delete", NULL, 0); + addMenuItem(m, "Back - [B]", NULL, 0); printMenu(m); @@ -219,16 +220,18 @@ static int subMenu() static void backup(Menu* m) { - char* fpath = m->items[m->cursor]; + char* fpath = m->items[m->cursor].value; char* backname = NULL; + tDSiHeader* h = getRomHeader(fpath); + { //make backup folder name char label[16]; - getAppLabel(fpath, label); + getRomLabel(h, label); char gamecode[5]; - getGameCode(fpath, gamecode); + getRomCode(h, gamecode); backname = (char*)malloc(strlen(label) + strlen(gamecode) + 16); sprintf(backname, "%s-%s", label, gamecode); @@ -263,7 +266,7 @@ static void backup(Menu* m) { u32 tid_low = 1; u32 tid_high = 1; - getTid(fpath, &tid_low, &tid_high); + getTitleId(h, &tid_low, &tid_high); char* srcpath = (char*)malloc(strlen("/title/") + 32); sprintf(srcpath, "/title/%08x/%08x", (unsigned int)tid_high, (unsigned int)tid_low); @@ -310,20 +313,21 @@ static void backup(Menu* m) } free(backname); + free(h); } static bool delete(Menu* m) { if (!m) return false; - char* fpath = m->items[m->cursor]; + char* fpath = m->items[m->cursor].value; bool result = false; bool choice = NO; { //get app title char title[128]; - getAppTitle(m->items[m->cursor], title); + getGameTitlePath(m->items[m->cursor].value, title, false); char str[] = "Are you sure you want to delete\n"; char* msg = (char*)malloc(strlen(str) + strlen(title) + 8); @@ -343,7 +347,7 @@ static bool delete(Menu* m) else { char dirPath[64]; - sprintf(dirPath, "%.25s", fpath); + sprintf(dirPath, "%.24s", fpath); if (!dirExists(dirPath)) {