mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-24 14:49:53 -06:00
Refactor DSi_NAND (#1844)
* Refactor diskio's contents - Change ff_disk_read_cb/write_cb into a std::function instead of a raw pointer - Add const specifiers as needed * Refactor DSi_NAND to manage the file system's mounted lifetime with RAII * Split NANDMount into NANDMount and NANDImage - NANDImage is used for information about the NAND that doesn't require decryption or filesystem access - NANDMount is used to actually access the file system - Both classes manage their respective resources (the NAND file handle and the NAND's mount) with RAII - Also split the file loading into another function that I will remove in a later PR * Make NANDMount immovable * Remove NAND-loading code that I had sectioned off into a function - Incomplete copypasta - I must have gotten distracted * Tidy up NANDImage's initialization - Don't unmount the disk image if the constructor fails (that's NANDMount's job now) - Only assign CurFile if the constructor succeeds * Add some const-correctness * Move DSi NAND initialization to the frontend - The NANDImage is now installed via a unique_ptr in DSi * Remove Platform::DSi_NANDPath - Not Config::DSiNANDPath; that can still be configured as usual - The core no longer needs to care
This commit is contained in:

committed by
GitHub

parent
b2fcff97c1
commit
d4e51f8060
@ -250,8 +250,6 @@ std::string GetConfigString(ConfigEntry entry)
|
||||
{
|
||||
switch (entry)
|
||||
{
|
||||
case DSi_NANDPath: return Config::DSiNANDPath;
|
||||
|
||||
case DLDI_ImagePath: return Config::DLDISDPath;
|
||||
case DLDI_FolderPath: return Config::DLDIFolderPath;
|
||||
|
||||
|
@ -595,6 +595,10 @@ void Reset()
|
||||
LoadBIOSFiles();
|
||||
|
||||
InstallFirmware();
|
||||
if (Config::ConsoleType == 1)
|
||||
{
|
||||
InstallNAND(&DSi::ARM7iBIOS[0x8308]);
|
||||
}
|
||||
NDS::Reset();
|
||||
SetBatteryLevels();
|
||||
|
||||
@ -657,6 +661,9 @@ bool LoadBIOS()
|
||||
if (!InstallFirmware())
|
||||
return false;
|
||||
|
||||
if (Config::ConsoleType == 1 && !InstallNAND(&DSi::ARM7iBIOS[0x8308]))
|
||||
return false;
|
||||
|
||||
if (NDS::NeedsDirectBoot())
|
||||
return false;
|
||||
|
||||
@ -948,6 +955,47 @@ void LoadUserSettingsFromConfig(SPI_Firmware::Firmware& firmware)
|
||||
firmware.UpdateChecksums();
|
||||
}
|
||||
|
||||
static Platform::FileHandle* OpenNANDFile() noexcept
|
||||
{
|
||||
std::string nandpath = Config::DSiNANDPath;
|
||||
std::string instnand = nandpath + Platform::InstanceFileSuffix();
|
||||
|
||||
FileHandle* nandfile = Platform::OpenLocalFile(instnand, FileMode::ReadWriteExisting);
|
||||
if ((!nandfile) && (Platform::InstanceID() > 0))
|
||||
{
|
||||
FileHandle* orig = Platform::OpenLocalFile(nandpath, FileMode::Read);
|
||||
if (!orig)
|
||||
{
|
||||
Log(LogLevel::Error, "Failed to open DSi NAND\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QFile::copy(QString::fromStdString(nandpath), QString::fromStdString(instnand));
|
||||
|
||||
nandfile = Platform::OpenLocalFile(instnand, FileMode::ReadWriteExisting);
|
||||
}
|
||||
|
||||
return nandfile;
|
||||
}
|
||||
|
||||
bool InstallNAND(const u8* es_keyY)
|
||||
{
|
||||
Platform::FileHandle* nandfile = OpenNANDFile();
|
||||
if (!nandfile)
|
||||
return false;
|
||||
|
||||
if (auto nand = std::make_unique<DSi_NAND::NANDImage>(nandfile, es_keyY); *nand)
|
||||
{
|
||||
DSi::NANDImage = std::move(nand);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
DSi::NANDImage = nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool InstallFirmware()
|
||||
{
|
||||
using namespace SPI_Firmware;
|
||||
@ -1089,6 +1137,9 @@ bool LoadROM(QStringList filepath, bool reset)
|
||||
NDS::SetConsoleType(Config::ConsoleType);
|
||||
NDS::EjectCart();
|
||||
LoadBIOSFiles();
|
||||
if (Config::ConsoleType == 1)
|
||||
InstallNAND(&DSi::ARM7iBIOS[0x8308]);
|
||||
|
||||
NDS::Reset();
|
||||
SetBatteryLevels();
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "types.h"
|
||||
#include "SaveManager.h"
|
||||
#include "AREngine.h"
|
||||
#include "DSi_NAND.h"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
@ -40,6 +41,7 @@ bool LoadBIOS();
|
||||
void ClearBackupState();
|
||||
|
||||
bool InstallFirmware();
|
||||
bool InstallNAND(const u8* es_keyY);
|
||||
bool LoadROM(QStringList filepath, bool reset);
|
||||
void EjectCart();
|
||||
bool CartInserted();
|
||||
|
@ -32,13 +32,13 @@
|
||||
|
||||
using namespace Platform;
|
||||
|
||||
bool TitleManagerDialog::NANDInited = false;
|
||||
std::unique_ptr<DSi_NAND::NANDImage> TitleManagerDialog::nand = nullptr;
|
||||
TitleManagerDialog* TitleManagerDialog::currentDlg = nullptr;
|
||||
|
||||
extern std::string EmuDirectory;
|
||||
|
||||
|
||||
TitleManagerDialog::TitleManagerDialog(QWidget* parent) : QDialog(parent), ui(new Ui::TitleManagerDialog)
|
||||
TitleManagerDialog::TitleManagerDialog(QWidget* parent, DSi_NAND::NANDImage& image) : QDialog(parent), ui(new Ui::TitleManagerDialog), nandmount(image)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
@ -47,7 +47,7 @@ TitleManagerDialog::TitleManagerDialog(QWidget* parent) : QDialog(parent), ui(ne
|
||||
|
||||
const u32 category = 0x00030004;
|
||||
std::vector<u32> titlelist;
|
||||
DSi_NAND::ListTitles(category, titlelist);
|
||||
nandmount.ListTitles(category, titlelist);
|
||||
|
||||
for (std::vector<u32>::iterator it = titlelist.begin(); it != titlelist.end(); it++)
|
||||
{
|
||||
@ -109,7 +109,7 @@ void TitleManagerDialog::createTitleItem(u32 category, u32 titleid)
|
||||
NDSHeader header;
|
||||
NDSBanner banner;
|
||||
|
||||
DSi_NAND::GetTitleInfo(category, titleid, version, &header, &banner);
|
||||
nandmount.GetTitleInfo(category, titleid, version, &header, &banner);
|
||||
|
||||
u32 icondata[32*32];
|
||||
ROMManager::ROMIcon(banner.Icon, banner.Palette, icondata);
|
||||
@ -137,7 +137,7 @@ void TitleManagerDialog::createTitleItem(u32 category, u32 titleid)
|
||||
|
||||
bool TitleManagerDialog::openNAND()
|
||||
{
|
||||
NANDInited = false;
|
||||
nand = nullptr;
|
||||
|
||||
FileHandle* bios7i = Platform::OpenLocalFile(Config::DSiBIOS7Path, FileMode::Read);
|
||||
if (!bios7i)
|
||||
@ -148,22 +148,25 @@ bool TitleManagerDialog::openNAND()
|
||||
FileRead(es_keyY, 16, 1, bios7i);
|
||||
CloseFile(bios7i);
|
||||
|
||||
if (!DSi_NAND::Init(es_keyY))
|
||||
{
|
||||
FileHandle* nandfile = Platform::OpenLocalFile(Config::DSiNANDPath, FileMode::ReadWriteExisting);
|
||||
if (!nandfile)
|
||||
return false;
|
||||
|
||||
nand = std::make_unique<DSi_NAND::NANDImage>(nandfile, es_keyY);
|
||||
if (!*nand)
|
||||
{ // If loading and mounting the NAND image failed...
|
||||
nand = nullptr;
|
||||
return false;
|
||||
// NOTE: The NANDImage takes ownership of the FileHandle,
|
||||
// so it will be closed even if the NANDImage constructor fails.
|
||||
}
|
||||
|
||||
NANDInited = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void TitleManagerDialog::closeNAND()
|
||||
{
|
||||
if (NANDInited)
|
||||
{
|
||||
DSi_NAND::DeInit();
|
||||
NANDInited = false;
|
||||
}
|
||||
nand = nullptr;
|
||||
}
|
||||
|
||||
void TitleManagerDialog::done(int r)
|
||||
@ -175,7 +178,7 @@ void TitleManagerDialog::done(int r)
|
||||
|
||||
void TitleManagerDialog::on_btnImportTitle_clicked()
|
||||
{
|
||||
TitleImportDialog* importdlg = new TitleImportDialog(this, importAppPath, &importTmdData, importReadOnly);
|
||||
TitleImportDialog* importdlg = new TitleImportDialog(this, importAppPath, &importTmdData, importReadOnly, nandmount);
|
||||
importdlg->open();
|
||||
connect(importdlg, &TitleImportDialog::finished, this, &TitleManagerDialog::onImportTitleFinished);
|
||||
|
||||
@ -190,14 +193,16 @@ void TitleManagerDialog::onImportTitleFinished(int res)
|
||||
titleid[0] = importTmdData.GetCategory();
|
||||
titleid[1] = importTmdData.GetID();
|
||||
|
||||
assert(nand != nullptr);
|
||||
assert(*nand);
|
||||
// remove anything that might hinder the install
|
||||
DSi_NAND::DeleteTitle(titleid[0], titleid[1]);
|
||||
nandmount.DeleteTitle(titleid[0], titleid[1]);
|
||||
|
||||
bool importres = DSi_NAND::ImportTitle(importAppPath.toStdString().c_str(), importTmdData, importReadOnly);
|
||||
bool importres = nandmount.ImportTitle(importAppPath.toStdString().c_str(), importTmdData, importReadOnly);
|
||||
if (!importres)
|
||||
{
|
||||
// remove a potential half-completed install
|
||||
DSi_NAND::DeleteTitle(titleid[0], titleid[1]);
|
||||
nandmount.DeleteTitle(titleid[0], titleid[1]);
|
||||
|
||||
QMessageBox::critical(this,
|
||||
"Import title - melonDS",
|
||||
@ -224,7 +229,7 @@ void TitleManagerDialog::on_btnDeleteTitle_clicked()
|
||||
return;
|
||||
|
||||
u64 titleid = cur->data(Qt::UserRole).toULongLong();
|
||||
DSi_NAND::DeleteTitle((u32)(titleid >> 32), (u32)titleid);
|
||||
nandmount.DeleteTitle((u32)(titleid >> 32), (u32)titleid);
|
||||
|
||||
delete cur;
|
||||
}
|
||||
@ -317,7 +322,7 @@ void TitleManagerDialog::onImportTitleData()
|
||||
}
|
||||
|
||||
u64 titleid = cur->data(Qt::UserRole).toULongLong();
|
||||
bool res = DSi_NAND::ImportTitleData((u32)(titleid >> 32), (u32)titleid, type, file.toStdString().c_str());
|
||||
bool res = nandmount.ImportTitleData((u32)(titleid >> 32), (u32)titleid, type, file.toStdString().c_str());
|
||||
if (!res)
|
||||
{
|
||||
QMessageBox::critical(this,
|
||||
@ -370,7 +375,7 @@ void TitleManagerDialog::onExportTitleData()
|
||||
if (file.isEmpty()) return;
|
||||
|
||||
u64 titleid = cur->data(Qt::UserRole).toULongLong();
|
||||
bool res = DSi_NAND::ExportTitleData((u32)(titleid >> 32), (u32)titleid, type, file.toStdString().c_str());
|
||||
bool res = nandmount.ExportTitleData((u32)(titleid >> 32), (u32)titleid, type, file.toStdString().c_str());
|
||||
if (!res)
|
||||
{
|
||||
QMessageBox::critical(this,
|
||||
@ -380,8 +385,8 @@ void TitleManagerDialog::onExportTitleData()
|
||||
}
|
||||
|
||||
|
||||
TitleImportDialog::TitleImportDialog(QWidget* parent, QString& apppath, const DSi_TMD::TitleMetadata* tmd, bool& readonly)
|
||||
: QDialog(parent), ui(new Ui::TitleImportDialog), appPath(apppath), tmdData(tmd), readOnly(readonly)
|
||||
TitleImportDialog::TitleImportDialog(QWidget* parent, QString& apppath, const DSi_TMD::TitleMetadata* tmd, bool& readonly, DSi_NAND::NANDMount& nandmount)
|
||||
: QDialog(parent), ui(new Ui::TitleImportDialog), appPath(apppath), tmdData(tmd), readOnly(readonly), nandmount(nandmount)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
@ -455,7 +460,7 @@ void TitleImportDialog::accept()
|
||||
}
|
||||
}
|
||||
|
||||
if (DSi_NAND::TitleExists(titleid[1], titleid[0]))
|
||||
if (nandmount.TitleExists(titleid[1], titleid[0]))
|
||||
{
|
||||
if (QMessageBox::question(this,
|
||||
"Import title - melonDS",
|
||||
|
@ -19,6 +19,7 @@
|
||||
#ifndef TITLEMANAGERDIALOG_H
|
||||
#define TITLEMANAGERDIALOG_H
|
||||
|
||||
#include <memory>
|
||||
#include <QDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QListWidget>
|
||||
@ -30,6 +31,7 @@
|
||||
#include <QNetworkAccessManager>
|
||||
|
||||
#include "DSi_TMD.h"
|
||||
#include "DSi_NAND.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
@ -44,10 +46,10 @@ class TitleManagerDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TitleManagerDialog(QWidget* parent);
|
||||
explicit TitleManagerDialog(QWidget* parent, DSi_NAND::NANDImage& image);
|
||||
~TitleManagerDialog();
|
||||
|
||||
static bool NANDInited;
|
||||
static std::unique_ptr<DSi_NAND::NANDImage> nand;
|
||||
static bool openNAND();
|
||||
static void closeNAND();
|
||||
|
||||
@ -68,7 +70,10 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
currentDlg = new TitleManagerDialog(parent);
|
||||
assert(nand != nullptr);
|
||||
assert(*nand);
|
||||
|
||||
currentDlg = new TitleManagerDialog(parent, *nand);
|
||||
currentDlg->open();
|
||||
return currentDlg;
|
||||
}
|
||||
@ -89,6 +94,7 @@ private slots:
|
||||
void onExportTitleData();
|
||||
|
||||
private:
|
||||
DSi_NAND::NANDMount nandmount;
|
||||
Ui::TitleManagerDialog* ui;
|
||||
|
||||
QString importAppPath;
|
||||
@ -106,7 +112,7 @@ class TitleImportDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TitleImportDialog(QWidget* parent, QString& apppath, const DSi_TMD::TitleMetadata* tmd, bool& readonly);
|
||||
explicit TitleImportDialog(QWidget* parent, QString& apppath, const DSi_TMD::TitleMetadata* tmd, bool& readonly, DSi_NAND::NANDMount& nand);
|
||||
~TitleImportDialog();
|
||||
|
||||
private slots:
|
||||
@ -119,6 +125,7 @@ private slots:
|
||||
|
||||
private:
|
||||
Ui::TitleImportDialog* ui;
|
||||
DSi_NAND::NANDMount& nandmount;
|
||||
|
||||
QButtonGroup* grpTmdSource;
|
||||
|
||||
|
Reference in New Issue
Block a user