Check for write permissions for some key files (#1972)
* check if an nds save file can be opened for writing also add the ability to open a file in append mode * fix multi-instance saves also move the check for file writability into a separate function (probably uneeded?) * implement check for gba roms * move rom load error messages into the functions also finish gba slot (oops) * improve error string * check write perms before saving path settings * fix memory leak * check for writability of firmware/nand/sds * add secondary checks for nand/firmware * add check for config file being writable * Return the file write error as a QString to avoid the invalid char* causing a garbled error message. Qt wants it as QString either way.
This commit is contained in:
parent
71e1ba8c40
commit
5ffa642980
|
@ -136,6 +136,11 @@ enum FileMode : unsigned {
|
||||||
*/
|
*/
|
||||||
Text = 0b01'00'00,
|
Text = 0b01'00'00,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a file in append mode.
|
||||||
|
*/
|
||||||
|
Append = 0b10'00'00,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a file for reading and writing.
|
* Opens a file for reading and writing.
|
||||||
* Equivalent to <tt>Read | Write</tt>.
|
* Equivalent to <tt>Read | Write</tt>.
|
||||||
|
@ -201,6 +206,13 @@ FileHandle* OpenLocalFile(const std::string& path, FileMode mode);
|
||||||
bool FileExists(const std::string& name);
|
bool FileExists(const std::string& name);
|
||||||
bool LocalFileExists(const std::string& name);
|
bool LocalFileExists(const std::string& name);
|
||||||
|
|
||||||
|
// Returns true if we have permission to write to the file.
|
||||||
|
// Warning: Also creates the file if not present!
|
||||||
|
bool CheckFileWritable(const std::string& filepath);
|
||||||
|
|
||||||
|
// Same as above (CheckFileWritable()) but for local files.
|
||||||
|
bool CheckLocalFileWritable(const std::string& filepath);
|
||||||
|
|
||||||
/** Close a file opened with \c OpenFile.
|
/** Close a file opened with \c OpenFile.
|
||||||
* @returns \c true if the file was closed successfully, false otherwise.
|
* @returns \c true if the file was closed successfully, false otherwise.
|
||||||
* @post \c file is no longer valid and should not be used.
|
* @post \c file is no longer valid and should not be used.
|
||||||
|
|
|
@ -378,7 +378,7 @@ ConfigEntry ConfigFile[] =
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void LoadFile(int inst)
|
bool LoadFile(int inst, int actualinst)
|
||||||
{
|
{
|
||||||
Platform::FileHandle* f;
|
Platform::FileHandle* f;
|
||||||
if (inst > 0)
|
if (inst > 0)
|
||||||
|
@ -386,11 +386,17 @@ void LoadFile(int inst)
|
||||||
char name[100] = {0};
|
char name[100] = {0};
|
||||||
snprintf(name, 99, kUniqueConfigFile, inst+1);
|
snprintf(name, 99, kUniqueConfigFile, inst+1);
|
||||||
f = Platform::OpenLocalFile(name, Platform::FileMode::ReadText);
|
f = Platform::OpenLocalFile(name, Platform::FileMode::ReadText);
|
||||||
|
|
||||||
|
if (!Platform::CheckLocalFileWritable(name)) return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
f = Platform::OpenLocalFile(kConfigFile, Platform::FileMode::ReadText);
|
f = Platform::OpenLocalFile(kConfigFile, Platform::FileMode::ReadText);
|
||||||
|
|
||||||
if (!f) return;
|
if (actualinst == 0 && !Platform::CheckLocalFileWritable(kConfigFile)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!f) return true;
|
||||||
|
|
||||||
char linebuf[1024];
|
char linebuf[1024];
|
||||||
char entryname[32];
|
char entryname[32];
|
||||||
|
@ -425,9 +431,10 @@ void LoadFile(int inst)
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseFile(f);
|
CloseFile(f);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Load()
|
bool Load()
|
||||||
{
|
{
|
||||||
|
|
||||||
for (ConfigEntry* entry = &ConfigFile[0]; entry->Value; entry++)
|
for (ConfigEntry* entry = &ConfigFile[0]; entry->Value; entry++)
|
||||||
|
@ -440,12 +447,14 @@ void Load()
|
||||||
case 3: *(int64_t*)entry->Value = std::get<int64_t>(entry->Default); break;
|
case 3: *(int64_t*)entry->Value = std::get<int64_t>(entry->Default); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadFile(0);
|
|
||||||
|
|
||||||
int inst = Platform::InstanceID();
|
int inst = Platform::InstanceID();
|
||||||
|
|
||||||
|
bool ret = LoadFile(0, inst);
|
||||||
if (inst > 0)
|
if (inst > 0)
|
||||||
LoadFile(inst);
|
ret = LoadFile(inst, inst);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Save()
|
void Save()
|
||||||
|
|
|
@ -204,7 +204,7 @@ extern bool GdbARM7BreakOnStartup;
|
||||||
extern bool GdbARM9BreakOnStartup;
|
extern bool GdbARM9BreakOnStartup;
|
||||||
|
|
||||||
|
|
||||||
void Load();
|
bool Load();
|
||||||
void Save();
|
void Save();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -380,6 +380,12 @@ void EmuSettingsDialog::on_btnFirmwareBrowse_clicked()
|
||||||
|
|
||||||
if (file.isEmpty()) return;
|
if (file.isEmpty()) return;
|
||||||
|
|
||||||
|
if (!Platform::CheckFileWritable(file.toStdString()))
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, "melonDS", "Unable to write to firmware file.\nPlease check file/folder write permissions.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
updateLastBIOSFolder(file);
|
updateLastBIOSFolder(file);
|
||||||
|
|
||||||
ui->txtFirmwarePath->setText(file);
|
ui->txtFirmwarePath->setText(file);
|
||||||
|
@ -436,6 +442,12 @@ void EmuSettingsDialog::on_btnDLDISDBrowse_clicked()
|
||||||
|
|
||||||
if (file.isEmpty()) return;
|
if (file.isEmpty()) return;
|
||||||
|
|
||||||
|
if (!Platform::CheckFileWritable(file.toStdString()))
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, "melonDS", "Unable to write to DLDI SD image.\nPlease check file/folder write permissions.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
updateLastBIOSFolder(file);
|
updateLastBIOSFolder(file);
|
||||||
|
|
||||||
ui->txtDLDISDPath->setText(file);
|
ui->txtDLDISDPath->setText(file);
|
||||||
|
@ -468,6 +480,13 @@ void EmuSettingsDialog::on_btnDSiFirmwareBrowse_clicked()
|
||||||
|
|
||||||
if (file.isEmpty()) return;
|
if (file.isEmpty()) return;
|
||||||
|
|
||||||
|
if (!Platform::CheckFileWritable(file.toStdString()))
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, "melonDS", "Unable to write to DSi firmware file.\nPlease check file/folder write permissions.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
updateLastBIOSFolder(file);
|
updateLastBIOSFolder(file);
|
||||||
|
|
||||||
ui->txtDSiFirmwarePath->setText(file);
|
ui->txtDSiFirmwarePath->setText(file);
|
||||||
|
@ -482,6 +501,13 @@ void EmuSettingsDialog::on_btnDSiNANDBrowse_clicked()
|
||||||
|
|
||||||
if (file.isEmpty()) return;
|
if (file.isEmpty()) return;
|
||||||
|
|
||||||
|
if (!Platform::CheckFileWritable(file.toStdString()))
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, "melonDS", "Unable to write to DSi NAND image.\nPlease check file/folder write permissions.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
updateLastBIOSFolder(file);
|
updateLastBIOSFolder(file);
|
||||||
|
|
||||||
ui->txtDSiNANDPath->setText(file);
|
ui->txtDSiNANDPath->setText(file);
|
||||||
|
@ -510,6 +536,12 @@ void EmuSettingsDialog::on_btnDSiSDBrowse_clicked()
|
||||||
|
|
||||||
if (file.isEmpty()) return;
|
if (file.isEmpty()) return;
|
||||||
|
|
||||||
|
if (!Platform::CheckFileWritable(file.toStdString()))
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, "melonDS", "Unable to write to DSi SD image.\nPlease check file/folder write permissions.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
updateLastBIOSFolder(file);
|
updateLastBIOSFolder(file);
|
||||||
|
|
||||||
ui->txtDSiSDPath->setText(file);
|
ui->txtDSiSDPath->setText(file);
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QTemporaryFile>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
@ -37,6 +38,7 @@ extern bool RunningSomething;
|
||||||
|
|
||||||
bool PathSettingsDialog::needsReset = false;
|
bool PathSettingsDialog::needsReset = false;
|
||||||
|
|
||||||
|
constexpr char errordialog[] = "melonDS cannot write to that directory.";
|
||||||
|
|
||||||
PathSettingsDialog::PathSettingsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::PathSettingsDialog)
|
PathSettingsDialog::PathSettingsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::PathSettingsDialog)
|
||||||
{
|
{
|
||||||
|
@ -101,6 +103,12 @@ void PathSettingsDialog::on_btnSaveFileBrowse_clicked()
|
||||||
QString::fromStdString(EmuDirectory));
|
QString::fromStdString(EmuDirectory));
|
||||||
|
|
||||||
if (dir.isEmpty()) return;
|
if (dir.isEmpty()) return;
|
||||||
|
|
||||||
|
if (!QTemporaryFile(dir).open())
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, "melonDS", errordialog);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ui->txtSaveFilePath->setText(dir);
|
ui->txtSaveFilePath->setText(dir);
|
||||||
}
|
}
|
||||||
|
@ -112,6 +120,12 @@ void PathSettingsDialog::on_btnSavestateBrowse_clicked()
|
||||||
QString::fromStdString(EmuDirectory));
|
QString::fromStdString(EmuDirectory));
|
||||||
|
|
||||||
if (dir.isEmpty()) return;
|
if (dir.isEmpty()) return;
|
||||||
|
|
||||||
|
if (!QTemporaryFile(dir).open())
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, "melonDS", errordialog);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ui->txtSavestatePath->setText(dir);
|
ui->txtSavestatePath->setText(dir);
|
||||||
}
|
}
|
||||||
|
@ -123,6 +137,12 @@ void PathSettingsDialog::on_btnCheatFileBrowse_clicked()
|
||||||
QString::fromStdString(EmuDirectory));
|
QString::fromStdString(EmuDirectory));
|
||||||
|
|
||||||
if (dir.isEmpty()) return;
|
if (dir.isEmpty()) return;
|
||||||
|
|
||||||
|
if (!QTemporaryFile(dir).open())
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, "melonDS", errordialog);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ui->txtCheatFilePath->setText(dir);
|
ui->txtCheatFilePath->setText(dir);
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,6 +217,10 @@ std::string InstanceFileSuffix()
|
||||||
|
|
||||||
constexpr char AccessMode(FileMode mode, bool file_exists)
|
constexpr char AccessMode(FileMode mode, bool file_exists)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (mode & FileMode::Append)
|
||||||
|
return 'a';
|
||||||
|
|
||||||
if (!(mode & FileMode::Write))
|
if (!(mode & FileMode::Write))
|
||||||
// If we're only opening the file for reading...
|
// If we're only opening the file for reading...
|
||||||
return 'r';
|
return 'r';
|
||||||
|
@ -255,7 +259,7 @@ static std::string GetModeString(FileMode mode, bool file_exists)
|
||||||
|
|
||||||
FileHandle* OpenFile(const std::string& path, FileMode mode)
|
FileHandle* OpenFile(const std::string& path, FileMode mode)
|
||||||
{
|
{
|
||||||
if ((mode & FileMode::ReadWrite) == FileMode::None)
|
if ((mode & (FileMode::ReadWrite | FileMode::Append)) == FileMode::None)
|
||||||
{ // If we aren't reading or writing, then we can't open the file
|
{ // If we aren't reading or writing, then we can't open the file
|
||||||
Log(LogLevel::Error, "Attempted to open \"%s\" in neither read nor write mode (FileMode 0x%x)\n", path.c_str(), mode);
|
Log(LogLevel::Error, "Attempted to open \"%s\" in neither read nor write mode (FileMode 0x%x)\n", path.c_str(), mode);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -327,6 +331,28 @@ bool LocalFileExists(const std::string& name)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CheckFileWritable(const std::string& filepath)
|
||||||
|
{
|
||||||
|
FileHandle* file = Platform::OpenFile(filepath.c_str(), FileMode::Append);
|
||||||
|
if (file)
|
||||||
|
{
|
||||||
|
Platform::CloseFile(file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckLocalFileWritable(const std::string& name)
|
||||||
|
{
|
||||||
|
FileHandle* file = Platform::OpenLocalFile(name.c_str(), FileMode::Append);
|
||||||
|
if (file)
|
||||||
|
{
|
||||||
|
Platform::CloseFile(file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool FileSeek(FileHandle* file, s64 offset, FileSeekOrigin origin)
|
bool FileSeek(FileHandle* file, s64 offset, FileSeekOrigin origin)
|
||||||
{
|
{
|
||||||
int stdorigin;
|
int stdorigin;
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include <zstd.h>
|
#include <zstd.h>
|
||||||
#ifdef ARCHIVE_SUPPORT_ENABLED
|
#ifdef ARCHIVE_SUPPORT_ENABLED
|
||||||
|
@ -210,6 +211,9 @@ QString VerifyDSFirmware()
|
||||||
f = Platform::OpenLocalFile(Config::FirmwarePath, FileMode::Read);
|
f = Platform::OpenLocalFile(Config::FirmwarePath, FileMode::Read);
|
||||||
if (!f) return "DS firmware was not found or could not be accessed. Check your emu settings.";
|
if (!f) return "DS firmware was not found or could not be accessed. Check your emu settings.";
|
||||||
|
|
||||||
|
if (!Platform::CheckFileWritable(Config::FirmwarePath))
|
||||||
|
return "DS firmware is unable to be written to.\nPlease check file/folder write permissions.";
|
||||||
|
|
||||||
len = FileLength(f);
|
len = FileLength(f);
|
||||||
if (len == 0x20000)
|
if (len == 0x20000)
|
||||||
{
|
{
|
||||||
|
@ -237,6 +241,9 @@ QString VerifyDSiFirmware()
|
||||||
f = Platform::OpenLocalFile(Config::DSiFirmwarePath, FileMode::Read);
|
f = Platform::OpenLocalFile(Config::DSiFirmwarePath, FileMode::Read);
|
||||||
if (!f) return "DSi firmware was not found or could not be accessed. Check your emu settings.";
|
if (!f) return "DSi firmware was not found or could not be accessed. Check your emu settings.";
|
||||||
|
|
||||||
|
if (!Platform::CheckFileWritable(Config::FirmwarePath))
|
||||||
|
return "DSi firmware is unable to be written to.\nPlease check file/folder write permissions.";
|
||||||
|
|
||||||
len = FileLength(f);
|
len = FileLength(f);
|
||||||
if (len != 0x20000)
|
if (len != 0x20000)
|
||||||
{
|
{
|
||||||
|
@ -259,6 +266,9 @@ QString VerifyDSiNAND()
|
||||||
f = Platform::OpenLocalFile(Config::DSiNANDPath, FileMode::ReadWriteExisting);
|
f = Platform::OpenLocalFile(Config::DSiNANDPath, FileMode::ReadWriteExisting);
|
||||||
if (!f) return "DSi NAND was not found or could not be accessed. Check your emu settings.";
|
if (!f) return "DSi NAND was not found or could not be accessed. Check your emu settings.";
|
||||||
|
|
||||||
|
if (!Platform::CheckFileWritable(Config::FirmwarePath))
|
||||||
|
return "DSi NAND is unable to be written to.\nPlease check file/folder write permissions.";
|
||||||
|
|
||||||
// TODO: some basic checks
|
// TODO: some basic checks
|
||||||
// check that it has the nocash footer, and all
|
// check that it has the nocash footer, and all
|
||||||
|
|
||||||
|
@ -1276,7 +1286,18 @@ bool LoadROMData(const QStringList& filepath, std::unique_ptr<u8[]>& filedata, u
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadROM(EmuThread* emuthread, QStringList filepath, bool reset)
|
QString GetSavErrorString(std::string& filepath, bool gba)
|
||||||
|
{
|
||||||
|
std::string console = gba ? "GBA" : "DS";
|
||||||
|
std::string err1 = "Unable to write to ";
|
||||||
|
std::string err2 = " save.\nPlease check file/folder write permissions.\n\nAttempted to Access:\n";
|
||||||
|
|
||||||
|
err1 += console + err2 + filepath;
|
||||||
|
|
||||||
|
return QString::fromStdString(err1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoadROM(QMainWindow* mainWindow, EmuThread* emuthread, QStringList filepath, bool reset)
|
||||||
{
|
{
|
||||||
unique_ptr<u8[]> filedata = nullptr;
|
unique_ptr<u8[]> filedata = nullptr;
|
||||||
u32 filelen;
|
u32 filelen;
|
||||||
|
@ -1284,7 +1305,10 @@ bool LoadROM(EmuThread* emuthread, QStringList filepath, bool reset)
|
||||||
std::string romname;
|
std::string romname;
|
||||||
|
|
||||||
if (!LoadROMData(filepath, filedata, filelen, basepath, romname))
|
if (!LoadROMData(filepath, filedata, filelen, basepath, romname))
|
||||||
|
{
|
||||||
|
QMessageBox::critical(mainWindow, "melonDS", "Failed to load the DS ROM.");
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
NDSSave = nullptr;
|
NDSSave = nullptr;
|
||||||
|
|
||||||
|
@ -1300,7 +1324,22 @@ bool LoadROM(EmuThread* emuthread, QStringList filepath, bool reset)
|
||||||
savname += Platform::InstanceFileSuffix();
|
savname += Platform::InstanceFileSuffix();
|
||||||
|
|
||||||
FileHandle* sav = Platform::OpenFile(savname, FileMode::Read);
|
FileHandle* sav = Platform::OpenFile(savname, FileMode::Read);
|
||||||
if (!sav) sav = Platform::OpenFile(origsav, FileMode::Read);
|
if (!sav)
|
||||||
|
{
|
||||||
|
if (!Platform::CheckFileWritable(origsav))
|
||||||
|
{
|
||||||
|
QMessageBox::critical(mainWindow, "melonDS", GetSavErrorString(origsav, false));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sav = Platform::OpenFile(origsav, FileMode::Read);
|
||||||
|
}
|
||||||
|
else if (!Platform::CheckFileWritable(savname))
|
||||||
|
{
|
||||||
|
QMessageBox::critical(mainWindow, "melonDS", GetSavErrorString(savname, false));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (sav)
|
if (sav)
|
||||||
{
|
{
|
||||||
savelen = (u32)Platform::FileLength(sav);
|
savelen = (u32)Platform::FileLength(sav);
|
||||||
|
@ -1322,13 +1361,19 @@ bool LoadROM(EmuThread* emuthread, QStringList filepath, bool reset)
|
||||||
|
|
||||||
auto cart = NDSCart::ParseROM(std::move(filedata), filelen, std::move(cartargs));
|
auto cart = NDSCart::ParseROM(std::move(filedata), filelen, std::move(cartargs));
|
||||||
if (!cart)
|
if (!cart)
|
||||||
|
{
|
||||||
// If we couldn't parse the ROM...
|
// If we couldn't parse the ROM...
|
||||||
|
QMessageBox::critical(mainWindow, "melonDS", "Failed to load the DS ROM.");
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (reset)
|
if (reset)
|
||||||
{
|
{
|
||||||
if (!emuthread->UpdateConsole(std::move(cart), Keep {}))
|
if (!emuthread->UpdateConsole(std::move(cart), Keep {}))
|
||||||
|
{
|
||||||
|
QMessageBox::critical(mainWindow, "melonDS", "Failed to load the DS ROM.");
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
InitFirmwareSaveManager(emuthread);
|
InitFirmwareSaveManager(emuthread);
|
||||||
emuthread->NDS->Reset();
|
emuthread->NDS->Reset();
|
||||||
|
@ -1351,7 +1396,7 @@ bool LoadROM(EmuThread* emuthread, QStringList filepath, bool reset)
|
||||||
NDSSave = std::make_unique<SaveManager>(savname);
|
NDSSave = std::make_unique<SaveManager>(savname);
|
||||||
LoadCheats(*emuthread->NDS);
|
LoadCheats(*emuthread->NDS);
|
||||||
|
|
||||||
return true;
|
return true; // success
|
||||||
}
|
}
|
||||||
|
|
||||||
void EjectCart(NDS& nds)
|
void EjectCart(NDS& nds)
|
||||||
|
@ -1388,9 +1433,13 @@ QString CartLabel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LoadGBAROM(NDS& nds, QStringList filepath)
|
bool LoadGBAROM(QMainWindow* mainWindow, NDS& nds, QStringList filepath)
|
||||||
{
|
{
|
||||||
if (nds.ConsoleType == 1) return false; // DSi doesn't have a GBA slot
|
if (nds.ConsoleType == 1)
|
||||||
|
{
|
||||||
|
QMessageBox::critical(mainWindow, "melonDS", "The DSi doesn't have a GBA slot.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
unique_ptr<u8[]> filedata = nullptr;
|
unique_ptr<u8[]> filedata = nullptr;
|
||||||
u32 filelen;
|
u32 filelen;
|
||||||
|
@ -1398,7 +1447,10 @@ bool LoadGBAROM(NDS& nds, QStringList filepath)
|
||||||
std::string romname;
|
std::string romname;
|
||||||
|
|
||||||
if (!LoadROMData(filepath, filedata, filelen, basepath, romname))
|
if (!LoadROMData(filepath, filedata, filelen, basepath, romname))
|
||||||
|
{
|
||||||
|
QMessageBox::critical(mainWindow, "melonDS", "Failed to load the GBA ROM.");
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
GBASave = nullptr;
|
GBASave = nullptr;
|
||||||
|
|
||||||
|
@ -1414,7 +1466,22 @@ bool LoadGBAROM(NDS& nds, QStringList filepath)
|
||||||
savname += Platform::InstanceFileSuffix();
|
savname += Platform::InstanceFileSuffix();
|
||||||
|
|
||||||
FileHandle* sav = Platform::OpenFile(savname, FileMode::Read);
|
FileHandle* sav = Platform::OpenFile(savname, FileMode::Read);
|
||||||
if (!sav) sav = Platform::OpenFile(origsav, FileMode::Read);
|
if (!sav)
|
||||||
|
{
|
||||||
|
if (!Platform::CheckFileWritable(origsav))
|
||||||
|
{
|
||||||
|
QMessageBox::critical(mainWindow, "melonDS", GetSavErrorString(origsav, true));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sav = Platform::OpenFile(origsav, FileMode::Read);
|
||||||
|
}
|
||||||
|
else if (!Platform::CheckFileWritable(savname))
|
||||||
|
{
|
||||||
|
QMessageBox::critical(mainWindow, "melonDS", GetSavErrorString(savname, true));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (sav)
|
if (sav)
|
||||||
{
|
{
|
||||||
savelen = (u32)FileLength(sav);
|
savelen = (u32)FileLength(sav);
|
||||||
|
@ -1430,7 +1497,10 @@ bool LoadGBAROM(NDS& nds, QStringList filepath)
|
||||||
|
|
||||||
auto cart = GBACart::ParseROM(std::move(filedata), filelen, std::move(savedata), savelen);
|
auto cart = GBACart::ParseROM(std::move(filedata), filelen, std::move(savedata), savelen);
|
||||||
if (!cart)
|
if (!cart)
|
||||||
|
{
|
||||||
|
QMessageBox::critical(mainWindow, "melonDS", "Failed to load the GBA ROM.");
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
nds.SetGBACart(std::move(cart));
|
nds.SetGBACart(std::move(cart));
|
||||||
GBACartType = 0;
|
GBACartType = 0;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "SaveManager.h"
|
#include "SaveManager.h"
|
||||||
#include "AREngine.h"
|
#include "AREngine.h"
|
||||||
#include "DSi_NAND.h"
|
#include "DSi_NAND.h"
|
||||||
|
#include <QMainWindow>
|
||||||
|
|
||||||
#include "MemConstants.h"
|
#include "MemConstants.h"
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
@ -72,12 +73,12 @@ std::optional<Firmware> LoadFirmware(int type) noexcept;
|
||||||
std::optional<DSi_NAND::NANDImage> LoadNAND(const std::array<u8, DSiBIOSSize>& arm7ibios) noexcept;
|
std::optional<DSi_NAND::NANDImage> LoadNAND(const std::array<u8, DSiBIOSSize>& arm7ibios) noexcept;
|
||||||
|
|
||||||
/// Inserts a ROM into the emulated console.
|
/// Inserts a ROM into the emulated console.
|
||||||
bool LoadROM(EmuThread*, QStringList filepath, bool reset);
|
bool LoadROM(QMainWindow* mainWindow, EmuThread*, QStringList filepath, bool reset);
|
||||||
void EjectCart(NDS& nds);
|
void EjectCart(NDS& nds);
|
||||||
bool CartInserted();
|
bool CartInserted();
|
||||||
QString CartLabel();
|
QString CartLabel();
|
||||||
|
|
||||||
bool LoadGBAROM(NDS& nds, QStringList filepath);
|
bool LoadGBAROM(QMainWindow* mainWindow, NDS& nds, QStringList filepath);
|
||||||
void LoadGBAAddon(NDS& nds, int type);
|
void LoadGBAAddon(NDS& nds, int type);
|
||||||
void EjectGBACart(NDS& nds);
|
void EjectGBACart(NDS& nds);
|
||||||
bool GBACartInserted();
|
bool GBACartInserted();
|
||||||
|
|
|
@ -865,10 +865,8 @@ void MainWindow::dropEvent(QDropEvent* event)
|
||||||
|
|
||||||
if (isNdsRom)
|
if (isNdsRom)
|
||||||
{
|
{
|
||||||
if (!ROMManager::LoadROM(emuThread, file, true))
|
if (!ROMManager::LoadROM(mainWindow, emuThread, file, true))
|
||||||
{
|
{
|
||||||
// TODO: better error reporting?
|
|
||||||
QMessageBox::critical(this, "melonDS", "Failed to load the DS ROM.");
|
|
||||||
emuThread->emuUnpause();
|
emuThread->emuUnpause();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -886,10 +884,8 @@ void MainWindow::dropEvent(QDropEvent* event)
|
||||||
}
|
}
|
||||||
else if (isGbaRom)
|
else if (isGbaRom)
|
||||||
{
|
{
|
||||||
if (!ROMManager::LoadGBAROM(*emuThread->NDS, file))
|
if (!ROMManager::LoadGBAROM(mainWindow, *emuThread->NDS, file))
|
||||||
{
|
{
|
||||||
// TODO: better error reporting?
|
|
||||||
QMessageBox::critical(this, "melonDS", "Failed to load the GBA ROM.");
|
|
||||||
emuThread->emuUnpause();
|
emuThread->emuUnpause();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -952,12 +948,7 @@ bool MainWindow::preloadROMs(QStringList file, QStringList gbafile, bool boot)
|
||||||
bool gbaloaded = false;
|
bool gbaloaded = false;
|
||||||
if (!gbafile.isEmpty())
|
if (!gbafile.isEmpty())
|
||||||
{
|
{
|
||||||
if (!ROMManager::LoadGBAROM(*emuThread->NDS, gbafile))
|
if (!ROMManager::LoadGBAROM(mainWindow, *emuThread->NDS, gbafile)) return false;
|
||||||
{
|
|
||||||
// TODO: better error reporting?
|
|
||||||
QMessageBox::critical(this, "melonDS", "Failed to load the GBA ROM.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
gbaloaded = true;
|
gbaloaded = true;
|
||||||
}
|
}
|
||||||
|
@ -965,12 +956,8 @@ bool MainWindow::preloadROMs(QStringList file, QStringList gbafile, bool boot)
|
||||||
bool ndsloaded = false;
|
bool ndsloaded = false;
|
||||||
if (!file.isEmpty())
|
if (!file.isEmpty())
|
||||||
{
|
{
|
||||||
if (!ROMManager::LoadROM(emuThread, file, true))
|
if (!ROMManager::LoadROM(mainWindow, emuThread, file, true)) return false;
|
||||||
{
|
|
||||||
// TODO: better error reporting?
|
|
||||||
QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
recentFileList.removeAll(file.join("|"));
|
recentFileList.removeAll(file.join("|"));
|
||||||
recentFileList.prepend(file.join("|"));
|
recentFileList.prepend(file.join("|"));
|
||||||
updateRecentFilesMenu();
|
updateRecentFilesMenu();
|
||||||
|
@ -1173,11 +1160,9 @@ void MainWindow::onOpenFile()
|
||||||
emuThread->emuUnpause();
|
emuThread->emuUnpause();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ROMManager::LoadROM(emuThread, file, true))
|
if (!ROMManager::LoadROM(mainWindow, emuThread, file, true))
|
||||||
{
|
{
|
||||||
// TODO: better error reporting?
|
|
||||||
QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
|
|
||||||
emuThread->emuUnpause();
|
emuThread->emuUnpause();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1272,11 +1257,9 @@ void MainWindow::onClickRecentFile()
|
||||||
emuThread->emuUnpause();
|
emuThread->emuUnpause();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ROMManager::LoadROM(emuThread, file, true))
|
if (!ROMManager::LoadROM(mainWindow, emuThread, file, true))
|
||||||
{
|
{
|
||||||
// TODO: better error reporting?
|
|
||||||
QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
|
|
||||||
emuThread->emuUnpause();
|
emuThread->emuUnpause();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1326,10 +1309,8 @@ void MainWindow::onInsertCart()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ROMManager::LoadROM(emuThread, file, false))
|
if (!ROMManager::LoadROM(mainWindow, emuThread, file, false))
|
||||||
{
|
{
|
||||||
// TODO: better error reporting?
|
|
||||||
QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
|
|
||||||
emuThread->emuUnpause();
|
emuThread->emuUnpause();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1361,10 +1342,8 @@ void MainWindow::onInsertGBACart()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ROMManager::LoadGBAROM(*emuThread->NDS, file))
|
if (!ROMManager::LoadGBAROM(mainWindow, *emuThread->NDS, file))
|
||||||
{
|
{
|
||||||
// TODO: better error reporting?
|
|
||||||
QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
|
|
||||||
emuThread->emuUnpause();
|
emuThread->emuUnpause();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -337,7 +337,7 @@ int main(int argc, char** argv)
|
||||||
SDL_InitSubSystem(SDL_INIT_VIDEO);
|
SDL_InitSubSystem(SDL_INIT_VIDEO);
|
||||||
SDL_EnableScreenSaver(); SDL_DisableScreenSaver();
|
SDL_EnableScreenSaver(); SDL_DisableScreenSaver();
|
||||||
|
|
||||||
Config::Load();
|
if (!Config::Load()) QMessageBox::critical(NULL, "melonDS", "Unable to write to config.\nPlease check the write permissions of the folder you placed melonDS in.");
|
||||||
|
|
||||||
#define SANITIZE(var, min, max) { var = std::clamp(var, min, max); }
|
#define SANITIZE(var, min, max) { var = std::clamp(var, min, max); }
|
||||||
SANITIZE(Config::ConsoleType, 0, 1);
|
SANITIZE(Config::ConsoleType, 0, 1);
|
||||||
|
|
Loading…
Reference in New Issue