take it further

This commit is contained in:
Arisotura 2021-08-21 21:25:08 +02:00
parent 9993dbdd55
commit 2773daf55b
4 changed files with 230 additions and 37 deletions

View File

@ -32,6 +32,7 @@ namespace DSi_NAND
{
FILE* CurFile;
FATFS CurFS;
u8 eMMC_CID[16];
u64 ConsoleID;
@ -42,11 +43,27 @@ u8 FATKey[16];
u8 ESKey[16];
UINT FF_ReadNAND(BYTE* buf, LBA_t sector, UINT num);
UINT FF_WriteNAND(BYTE* buf, LBA_t sector, UINT num);
bool Init(FILE* nandfile, u8* es_keyY)
{
if (!nandfile)
return false;
ff_disk_open(FF_ReadNAND, FF_WriteNAND);
FRESULT res;
res = f_mount(&CurFS, "0:", 0);
if (res != FR_OK)
{
printf("NAND mounting failed: %d\n", res);
f_unmount("0:");
ff_disk_close();
return false;
}
// read the nocash footer
fseek(nandfile, -0x40, SEEK_END);
@ -113,6 +130,9 @@ bool Init(FILE* nandfile, u8* es_keyY)
void DeInit()
{
f_unmount("0:");
ff_disk_close();
CurFile = nullptr;
}
@ -155,8 +175,8 @@ u32 ReadFATBlock(u64 addr, u32 len, u8* buf)
AES_ctx ctx;
SetupFATCrypto(&ctx, ctr);
fseek(DSi::SDMMCFile, addr, SEEK_SET);
u32 res = fread(buf, len, 1, DSi::SDMMCFile);
fseek(CurFile, addr, SEEK_SET);
u32 res = fread(buf, len, 1, CurFile);
if (!res) return 0;
for (u32 i = 0; i < len; i += 16)
@ -177,7 +197,7 @@ u32 WriteFATBlock(u64 addr, u32 len, u8* buf)
AES_ctx ctx;
SetupFATCrypto(&ctx, ctr);
fseek(DSi::SDMMCFile, addr, SEEK_SET);
fseek(CurFile, addr, SEEK_SET);
for (u32 s = 0; s < len; s += 0x200)
{
@ -191,7 +211,7 @@ u32 WriteFATBlock(u64 addr, u32 len, u8* buf)
DSi_AES::Swap16(&tempbuf[i], tmp);
}
u32 res = fwrite(tempbuf, 0x200, 1, DSi::SDMMCFile);
u32 res = fwrite(tempbuf, 0x200, 1, CurFile);
if (!res) return 0;
}
@ -418,18 +438,7 @@ bool ESDecrypt(u8* data, u32 len)
void PatchTSC()
{
ff_disk_open(FF_ReadNAND, FF_WriteNAND);
FRESULT res;
FATFS fs;
res = f_mount(&fs, "0:", 0);
if (res != FR_OK)
{
printf("NAND mounting failed: %d\n", res);
f_unmount("0:");
ff_disk_close();
return;
}
for (int i = 0; i < 2; i++)
{
@ -469,9 +478,6 @@ void PatchTSC()
f_close(&file);
}
f_unmount("0:");
ff_disk_close();
}
@ -533,6 +539,106 @@ void debug_dumpfile(char* path, char* out)
f_close(&file);
}
u32 GetTitleVersion(u32 category, u32 titleid)
{
FRESULT res;
char path[256];
sprintf(path, "0:/title/%08x/%08x/content/title.tmd", category, titleid);
FIL file;
res = f_open(&file, path, FA_OPEN_EXISTING | FA_READ);
if (res != FR_OK)
return 0xFFFFFFFF;
u32 version;
u32 nread;
f_lseek(&file, 0x1E4);
f_read(&file, &version, 4, &nread);
version = (version >> 24) | ((version & 0xFF0000) >> 8) | ((version & 0xFF00) << 8) | (version << 24);
f_close(&file);
return version;
}
void ListTitles(u32 category, std::vector<u32>& titlelist)
{
FRESULT res;
DIR titledir;
char path[256];
sprintf(path, "0:/title/%08x", category);
res = f_opendir(&titledir, path);
if (res != FR_OK)
{
printf("NAND: !! no title dir (%s)\n", path);
return;
}
for (;;)
{
FILINFO info;
f_readdir(&titledir, &info);
if (!info.fname[0])
break;
if (strlen(info.fname) != 8)
continue;
u32 titleid;
if (sscanf(info.fname, "%08x", &titleid) < 1)
continue;
u32 version = GetTitleVersion(category, titleid);
if (version == 0xFFFFFFFF)
continue;
sprintf(path, "0:/title/%08x/%08x/content/%08x.app", category, titleid, version);
FILINFO appinfo;
res = f_stat(path, &appinfo);
if (res != FR_OK)
continue;
if (appinfo.fattrib & AM_DIR)
continue;
if (appinfo.fsize < 0x4000)
continue;
// title is good, add it to the list
titlelist.push_back(titleid);
}
f_closedir(&titledir);
}
void GetTitleInfo(u32 category, u32 titleid, u32& version, u8* header, u8* banner)
{
version = GetTitleVersion(category, titleid);
FRESULT res;
char path[256];
sprintf(path, "0:/title/%08x/%08x/content/%08x.app", category, titleid, version);
FIL file;
res = f_open(&file, path, FA_OPEN_EXISTING | FA_READ);
if (res != FR_OK)
return;
u32 nread;
f_read(&file, header, 0x1000, &nread);
u32 banneraddr = *(u32*)&header[0x68];
if (!banneraddr)
{
memset(banner, 0, 0x2400);
}
else
{
f_lseek(&file, banneraddr);
f_read(&file, banner, 0x2400, &nread);
}
f_close(&file);
}
void CreateTicket(char* path, u32 titleid0, u32 titleid1, u8 version)
{
FIL file;
@ -639,18 +745,7 @@ void ImportTest()
char* tmdfile = "treasure.tmd";
char* appfile = "treasure.nds";
ff_disk_open(FF_ReadNAND, FF_WriteNAND);
FRESULT res;
FATFS fs;
res = f_mount(&fs, "0:", 0);
if (res != FR_OK)
{
printf("NAND mounting failed: %d\n", res);
f_unmount("0:");
ff_disk_close();
return;
}
/*debug_listfiles("0:");
@ -842,9 +937,6 @@ return;*/
printf("----- POST INSERTION:\n");
debug_listfiles("0:");
f_unmount("0:");
ff_disk_close();
}
}

View File

@ -20,6 +20,7 @@
#define DSI_NAND_H
#include "types.h"
#include <vector>
namespace DSi_NAND
{
@ -31,6 +32,8 @@ void GetIDs(u8* emmc_cid, u64& consoleid);
void PatchTSC();
void ListTitles(u32 category, std::vector<u32>& titlelist);
void GetTitleInfo(u32 category, u32 titleid, u32& version, u8* header, u8* banner);
void ImportTest();
}

View File

@ -17,17 +17,19 @@
*/
#include <stdio.h>
#include <QMessageBox>
#include "types.h"
#include "Platform.h"
#include "Config.h"
#include "PlatformConfig.h"
#include "FrontendUtil.h"
#include "DSi_NAND.h"
#include "TitleManagerDialog.h"
#include "ui_TitleManagerDialog.h"
FILE* TitleManagerDialog::curNAND = nullptr;
TitleManagerDialog* TitleManagerDialog::currentDlg = nullptr;
@ -36,11 +38,50 @@ TitleManagerDialog::TitleManagerDialog(QWidget* parent) : QDialog(parent), ui(ne
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
//ui->lstTitleList->setViewMode(QListView::IconMode);
//ui->lstTitleList->setFlow(QListView::LeftToRight);
ui->lstTitleList->setIconSize(QSize(32, 32));
const u32 category = 0x00030004;
std::vector<u32> titlelist;
DSi_NAND::ListTitles(category, titlelist);
for (std::vector<u32>::iterator it = titlelist.begin(); it != titlelist.end(); it++)
{
u32 titleid = *it;
u32 version;
u8 header[0x1000];
u8 banner[0x2400];
DSi_NAND::GetTitleInfo(category, titleid, version, header, banner);
u8 icongfx[512];
u16 iconpal[16];
memcpy(icongfx, &banner[0x20], 512);
memcpy(iconpal, &banner[0x220], 16*2);
u32 icondata[32*32];
Frontend::ROMIcon(icongfx, iconpal, icondata);
QImage iconimg((const uchar*)icondata, 32, 32, QImage::Format_ARGB32);
QIcon icon(QPixmap::fromImage(iconimg.copy()));
// TODO: make it possible to select other languages?
u16 titleraw[129];
memcpy(titleraw, &banner[0x340], 128*sizeof(u16));
titleraw[128] = '\0';
QString title = QString::fromUtf16(titleraw);
title.replace("\n", " · ");
char gamecode[5];
*(u32*)&gamecode[0] = *(u32*)&header[0xC];
gamecode[4] = '\0';
char extra[128];
sprintf(extra, "\n(title ID: %s · %08x/%08x · version %08x)", gamecode, category, titleid, version);
QListWidgetItem* item = new QListWidgetItem(title + QString(extra));
item->setIcon(icon);
ui->lstTitleList->addItem(item);
}
/*{
QPixmap boobs(32, 32);
boobs.fill(Qt::blue);
QIcon piss(boobs);
@ -75,10 +116,53 @@ TitleManagerDialog::TitleManagerDialog(QWidget* parent) : QDialog(parent), ui(ne
QListWidgetItem* derp = new QListWidgetItem("trans\nrights");
derp->setIcon(piss);
ui->lstTitleList->addItem(derp);
}
}*/
}
TitleManagerDialog::~TitleManagerDialog()
{
delete ui;
}
bool TitleManagerDialog::openNAND()
{
FILE* bios7i = Platform::OpenLocalFile(Config::DSiBIOS7Path, "rb");
if (!bios7i)
return false;
u8 es_keyY[16];
fseek(bios7i, 0x8308, SEEK_SET);
fread(es_keyY, 16, 1, bios7i);
fclose(bios7i);
curNAND = Platform::OpenLocalFile(Config::DSiNANDPath, "r+b");
if (!curNAND)
return false;
if (!DSi_NAND::Init(curNAND, es_keyY))
{
fclose(curNAND);
curNAND = nullptr;
return false;
}
return true;
}
void TitleManagerDialog::closeNAND()
{
if (curNAND)
{
DSi_NAND::DeInit();
fclose(curNAND);
curNAND = nullptr;
}
}
void TitleManagerDialog::done(int r)
{
QDialog::done(r);
closeDlg();
}

View File

@ -20,6 +20,7 @@
#define TITLEMANAGERDIALOG_H
#include <QDialog>
#include <QMessageBox>
namespace Ui { class TitleManagerDialog; }
class TitleManagerDialog;
@ -32,6 +33,10 @@ public:
explicit TitleManagerDialog(QWidget* parent);
~TitleManagerDialog();
static FILE* curNAND;
static bool openNAND();
static void closeNAND();
static TitleManagerDialog* currentDlg;
static TitleManagerDialog* openDlg(QWidget* parent)
{
@ -41,6 +46,14 @@ public:
return currentDlg;
}
if (!openNAND())
{
QMessageBox::critical(parent,
"DSi title manager - melonDS",
"Failed to mount the DSi NAND. Check that your NAND dump is valid.");
return nullptr;
}
currentDlg = new TitleManagerDialog(parent);
currentDlg->open();
return currentDlg;
@ -48,10 +61,11 @@ public:
static void closeDlg()
{
currentDlg = nullptr;
closeNAND();
}
private slots:
// shit
void done(int r);
private:
Ui::TitleManagerDialog* ui;