mirror of
https://github.com/rvtr/TDT.git
synced 2025-10-31 13:51:07 -04:00
0.6.8
This commit is contained in:
parent
1491f6b862
commit
c05199c59a
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 <sys/stat.h>
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
#include "message.h"
|
||||
#include <time.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
@ -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 <file.tmd>\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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -3,7 +3,13 @@
|
||||
|
||||
#include <nds/ndstypes.h>
|
||||
|
||||
#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);
|
||||
|
||||
@ -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)
|
||||
|
||||
281
arm9/src/rom.c
Normal file
281
arm9/src/rom.c
Normal file
@ -0,0 +1,281 @@
|
||||
#include "rom.h"
|
||||
#include "main.h"
|
||||
#include "storage.h"
|
||||
#include <nds.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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]) );
|
||||
}
|
||||
24
arm9/src/rom.h
Normal file
24
arm9/src/rom.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef ROM_H
|
||||
#define ROM_H
|
||||
|
||||
#include <nds/ndstypes.h>
|
||||
#include <nds/memory.h>
|
||||
|
||||
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
|
||||
123
arm9/src/sav.c
Normal file
123
arm9/src/sav.c
Normal file
@ -0,0 +1,123 @@
|
||||
#include "sav.h"
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
|
||||
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;
|
||||
}
|
||||
38
arm9/src/sav.h
Normal file
38
arm9/src/sav.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef SAV_H
|
||||
#define SAV_H
|
||||
|
||||
#include <nds/ndstypes.h>
|
||||
#include <stdio.h>
|
||||
//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
|
||||
@ -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;
|
||||
}
|
||||
@ -5,7 +5,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#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
|
||||
@ -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))
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user