aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/qt_sdl/main.cpp
diff options
context:
space:
mode:
authorArisotura <thetotalworm@gmail.com>2022-01-07 14:00:43 +0100
committerGitHub <noreply@github.com>2022-01-07 14:00:43 +0100
commite665e25bd3ea4b9af932e182b1c93e77b762ccb0 (patch)
tree06b5ceb336e42868806113cbf1f45add2b56a3e8 /src/frontend/qt_sdl/main.cpp
parentc4cd9da674bcfb8dca89086ce3ffa2d3b03438eb (diff)
Custom path support (#1333)
also including: * getting rid of shitty strings * all new, cleaner ROM handling code * base for DSi savestates * GBA slot addons (for now, memory cart)
Diffstat (limited to 'src/frontend/qt_sdl/main.cpp')
-rw-r--r--src/frontend/qt_sdl/main.cpp855
1 files changed, 488 insertions, 367 deletions
diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp
index bf7c261..5711a05 100644
--- a/src/frontend/qt_sdl/main.cpp
+++ b/src/frontend/qt_sdl/main.cpp
@@ -56,6 +56,7 @@
#include "VideoSettingsDialog.h"
#include "AudioSettingsDialog.h"
#include "FirmwareSettingsDialog.h"
+#include "PathSettingsDialog.h"
#include "WifiSettingsDialog.h"
#include "InterfaceSettingsDialog.h"
#include "ROMInfoDialog.h"
@@ -80,6 +81,7 @@
#include "main_shaders.h"
+#include "ROMManager.h"
#include "ArchiveUtil.h"
// TODO: uniform variable spelling
@@ -180,7 +182,7 @@ void micClose()
micDevice = 0;
}
-void micLoadWav(const char* name)
+void micLoadWav(std::string name)
{
SDL_AudioSpec format;
memset(&format, 0, sizeof(SDL_AudioSpec));
@@ -191,7 +193,7 @@ void micLoadWav(const char* name)
u8* buf;
u32 len;
- if (!SDL_LoadWAV(name, &format, &buf, &len))
+ if (!SDL_LoadWAV(name.c_str(), &format, &buf, &len))
return;
const u64 dstfreq = 44100;
@@ -541,6 +543,12 @@ void EmuThread::run()
// emulate
u32 nlines = NDS::RunFrame();
+ if (ROMManager::NDSSave)
+ ROMManager::NDSSave->CheckFlush();
+
+ if (ROMManager::GBASave)
+ ROMManager::GBASave->CheckFlush();
+
FrontBufferLock.lock();
FrontBuffer = GPU::FrontBuffer;
#ifdef OGLRENDERER_ENABLED
@@ -1281,7 +1289,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
oldW = Config::WindowWidth;
oldH = Config::WindowHeight;
- oldMax = Config::WindowMaximized!=0;
+ oldMax = Config::WindowMaximized;
setWindowTitle("melonDS " MELONDS_VERSION);
setAttribute(Qt::WA_DeleteOnClose);
@@ -1295,16 +1303,16 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
connect(actOpenROM, &QAction::triggered, this, &MainWindow::onOpenFile);
actOpenROM->setShortcut(QKeySequence(QKeySequence::StandardKey::Open));
- actOpenROMArchive = menu->addAction("Open ROM inside archive...");
+ /*actOpenROMArchive = menu->addAction("Open ROM inside archive...");
connect(actOpenROMArchive, &QAction::triggered, this, &MainWindow::onOpenFileArchive);
- actOpenROMArchive->setShortcut(QKeySequence(Qt::Key_O | Qt::CTRL | Qt::SHIFT));
+ actOpenROMArchive->setShortcut(QKeySequence(Qt::Key_O | Qt::CTRL | Qt::SHIFT));*/
recentMenu = menu->addMenu("Open recent");
for (int i = 0; i < 10; ++i)
{
- char* item = Config::RecentROMList[i];
- if (strlen(item) > 0)
- recentFileList.push_back(item);
+ std::string item = Config::RecentROMList[i];
+ if (!item.empty())
+ recentFileList.push_back(QString::fromStdString(item));
}
updateRecentFilesMenu();
@@ -1314,6 +1322,41 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
menu->addSeparator();
+ actCurrentCart = menu->addAction("DS slot: " + ROMManager::CartLabel());
+ actCurrentCart->setEnabled(false);
+
+ actInsertCart = menu->addAction("Insert cart...");
+ connect(actInsertCart, &QAction::triggered, this, &MainWindow::onInsertCart);
+
+ actEjectCart = menu->addAction("Eject cart");
+ connect(actEjectCart, &QAction::triggered, this, &MainWindow::onEjectCart);
+
+ menu->addSeparator();
+
+ actCurrentGBACart = menu->addAction("GBA slot: " + ROMManager::GBACartLabel());
+ actCurrentGBACart->setEnabled(false);
+
+ actInsertGBACart = menu->addAction("Insert ROM cart...");
+ connect(actInsertGBACart, &QAction::triggered, this, &MainWindow::onInsertGBACart);
+
+ {
+ QMenu* submenu = menu->addMenu("Insert add-on cart");
+
+ actInsertGBAAddon[0] = submenu->addAction("Memory expansion");
+ actInsertGBAAddon[0]->setData(QVariant(NDS::GBAAddon_RAMExpansion));
+ connect(actInsertGBAAddon[0], &QAction::triggered, this, &MainWindow::onInsertGBAAddon);
+ }
+
+ actEjectGBACart = menu->addAction("Eject cart");
+ connect(actEjectGBACart, &QAction::triggered, this, &MainWindow::onEjectGBACart);
+
+ menu->addSeparator();
+
+ actImportSavefile = menu->addAction("Import savefile");
+ connect(actImportSavefile, &QAction::triggered, this, &MainWindow::onImportSavefile);
+
+ menu->addSeparator();
+
{
QMenu* submenu = menu->addMenu("Save state");
@@ -1351,9 +1394,6 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
actUndoStateLoad->setShortcut(QKeySequence(Qt::Key_F12));
connect(actUndoStateLoad, &QAction::triggered, this, &MainWindow::onUndoStateLoad);
- actImportSavefile = menu->addAction("Import savefile");
- connect(actImportSavefile, &QAction::triggered, this, &MainWindow::onImportSavefile);
-
menu->addSeparator();
actQuit = menu->addAction("Quit");
@@ -1422,6 +1462,9 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
actFirmwareSettings = menu->addAction("Firmware settings");
connect(actFirmwareSettings, &QAction::triggered, this, &MainWindow::onOpenFirmwareSettings);
+ actPathSettings = menu->addAction("Path settings");
+ connect(actPathSettings, &QAction::triggered, this, &MainWindow::onOpenPathSettings);
+
{
QMenu* submenu = menu->addMenu("Savestate settings");
@@ -1588,6 +1631,16 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
createScreenPanel();
+ actEjectCart->setEnabled(false);
+ actEjectGBACart->setEnabled(false);
+
+ if (Config::ConsoleType == 1)
+ {
+ actInsertGBACart->setEnabled(false);
+ for (int i = 0; i < 1; i++)
+ actInsertGBAAddon[i]->setEnabled(false);
+ }
+
for (int i = 0; i < 9; i++)
{
actSaveState[i]->setEnabled(false);
@@ -1602,13 +1655,13 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
actFrameStep->setEnabled(false);
actSetupCheats->setEnabled(false);
- actTitleManager->setEnabled(strlen(Config::DSiNANDPath) > 0);
+ actTitleManager->setEnabled(!Config::DSiNANDPath.empty());
- actEnableCheats->setChecked(Config::EnableCheats != 0);
+ actEnableCheats->setChecked(Config::EnableCheats);
actROMInfo->setEnabled(false);
- actSavestateSRAMReloc->setChecked(Config::SavestateRelocSRAM != 0);
+ actSavestateSRAMReloc->setChecked(Config::SavestateRelocSRAM);
actScreenRotation[Config::ScreenRotation]->setChecked(true);
@@ -1623,18 +1676,18 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
actScreenLayout[Config::ScreenLayout]->setChecked(true);
actScreenSizing[Config::ScreenSizing]->setChecked(true);
- actIntegerScaling->setChecked(Config::IntegerScaling != 0);
+ actIntegerScaling->setChecked(Config::IntegerScaling);
- actScreenSwap->setChecked(Config::ScreenSwap != 0);
+ actScreenSwap->setChecked(Config::ScreenSwap);
actScreenAspectTop[Config::ScreenAspectTop]->setChecked(true);
actScreenAspectBot[Config::ScreenAspectBot]->setChecked(true);
- actScreenFiltering->setChecked(Config::ScreenFilter != 0);
- actShowOSD->setChecked(Config::ShowOSD != 0);
+ actScreenFiltering->setChecked(Config::ScreenFilter);
+ actShowOSD->setChecked(Config::ShowOSD);
- actLimitFramerate->setChecked(Config::LimitFPS != 0);
- actAudioSync->setChecked(Config::AudioSync != 0);
+ actLimitFramerate->setChecked(Config::LimitFPS);
+ actAudioSync->setChecked(Config::AudioSync);
}
MainWindow::~MainWindow()
@@ -1755,9 +1808,9 @@ void MainWindow::dragEnterEvent(QDragEnterEvent* event)
QStringList acceptedExts{".nds", ".srl", ".dsi", ".gba", ".rar",
".zip", ".7z", ".tar", ".tar.gz", ".tar.xz", ".tar.bz2"};
- for(const QString &ext : acceptedExts)
+ for (const QString &ext : acceptedExts)
{
- if(filename.endsWith(ext, Qt::CaseInsensitive))
+ if (filename.endsWith(ext, Qt::CaseInsensitive))
event->acceptProposedAction();
}
}
@@ -1769,66 +1822,66 @@ void MainWindow::dropEvent(QDropEvent* event)
QList<QUrl> urls = event->mimeData()->urls();
if (urls.count() > 1) return; // not handling more than one file at once
- emuThread->emuPause();
-
QString filename = urls.at(0).toLocalFile();
- QString ext = filename.right(3).toLower();
+ QStringList arcexts{".zip", ".7z", ".rar", ".tar", ".tar.gz", ".tar.xz", ".tar.bz2"};
- recentFileList.removeAll(filename);
- recentFileList.prepend(filename);
- updateRecentFilesMenu();
-
- char _filename[1024];
- strncpy(_filename, filename.toStdString().c_str(), 1023); _filename[1023] = '\0';
+ emuThread->emuPause();
- int slot; int res;
- if (ext == "gba")
- {
- slot = 1;
- res = Frontend::LoadROM(_filename, Frontend::ROMSlot_GBA);
- }
- else if(ext == "nds" || ext == "srl" || ext == "dsi")
+ if (!verifySetup())
{
- slot = 0;
- res = Frontend::LoadROM(_filename, Frontend::ROMSlot_NDS);
+ emuThread->emuUnpause();
+ return;
}
- else
+
+ for (const QString &ext : arcexts)
{
- QByteArray romBuffer;
- QString romFileName = pickAndExtractFileFromArchive(_filename, &romBuffer);
- if(romFileName.isEmpty())
+ if (filename.endsWith(ext, Qt::CaseInsensitive))
{
- res = Frontend::Load_ROMLoadError;
- }
- else
- {
- slot = (romFileName.endsWith(".gba", Qt::CaseInsensitive) ? 1 : 0);
- QString sramFileName = QFileInfo(_filename).absolutePath() + QDir::separator() + QFileInfo(romFileName).completeBaseName() + ".sav";
-
- if(slot == 0)
- strncpy(Frontend::NDSROMExtension, QFileInfo(romFileName).suffix().toStdString().c_str(), 4);
+ QString arcfile = pickFileFromArchive(filename);
+ if (arcfile.isEmpty())
+ {
+ emuThread->emuUnpause();
+ return;
+ }
- res = Frontend::LoadROM((const u8*)romBuffer.constData(), romBuffer.size(),
- _filename, romFileName.toStdString().c_str(), sramFileName.toStdString().c_str(),
- slot);
+ filename += "|" + arcfile;
}
}
- if (res != Frontend::Load_OK)
- {
- QMessageBox::critical(this,
- "melonDS",
- loadErrorStr(res));
- emuThread->emuUnpause();
- }
- else if (slot == 1)
+ QStringList file = filename.split('|');
+
+ if (filename.endsWith(".gba", Qt::CaseInsensitive))
{
- // checkme
+ if (!ROMManager::LoadGBAROM(file))
+ {
+ // TODO: better error reporting?
+ QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
+ emuThread->emuUnpause();
+ return;
+ }
+
emuThread->emuUnpause();
+
+ updateCartInserted(true);
}
else
{
+ if (!ROMManager::LoadROM(file, true))
+ {
+ // TODO: better error reporting?
+ QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
+ emuThread->emuUnpause();
+ return;
+ }
+
+ recentFileList.removeAll(filename);
+ recentFileList.prepend(filename);
+ updateRecentFilesMenu();
+
+ NDS::Start();
emuThread->emuRun();
+
+ updateCartInserted(false);
}
}
@@ -1846,145 +1899,178 @@ void MainWindow::onAppStateChanged(Qt::ApplicationState state)
}
}
-QString MainWindow::loadErrorStr(int error)
+bool MainWindow::verifySetup()
{
- switch (error)
+ QString res = ROMManager::VerifySetup();
+ if (!res.isEmpty())
{
- case Frontend::Load_BIOS9Missing:
- return "DS ARM9 BIOS was not found or could not be accessed. Check your emu settings.";
- case Frontend::Load_BIOS9Bad:
- return "DS ARM9 BIOS is not a valid BIOS dump.";
+ QMessageBox::critical(this, "melonDS", res);
+ return false;
+ }
- case Frontend::Load_BIOS7Missing:
- return "DS ARM7 BIOS was not found or could not be accessed. Check your emu settings.";
- case Frontend::Load_BIOS7Bad:
- return "DS ARM7 BIOS is not a valid BIOS dump.";
+ return true;
+}
- case Frontend::Load_FirmwareMissing:
- return "DS firmware was not found or could not be accessed. Check your emu settings.";
- case Frontend::Load_FirmwareBad:
- return "DS firmware is not a valid firmware dump.";
- case Frontend::Load_FirmwareNotBootable:
- return "DS firmware is not bootable.";
+bool MainWindow::preloadROMs(QString filename, QString gbafilename)
+{
+ if (!verifySetup())
+ {
+ return false;
+ }
- case Frontend::Load_DSiBIOS9Missing:
- return "DSi ARM9 BIOS was not found or could not be accessed. Check your emu settings.";
- case Frontend::Load_DSiBIOS9Bad:
- return "DSi ARM9 BIOS is not a valid BIOS dump.";
+ bool gbaloaded = false;
+ if (!gbafilename.isEmpty())
+ {
+ QStringList gbafile = gbafilename.split('|');
+ if (!ROMManager::LoadGBAROM(gbafile))
+ {
+ // TODO: better error reporting?
+ QMessageBox::critical(this, "melonDS", "Failed to load the GBA ROM.");
+ return false;
+ }
- case Frontend::Load_DSiBIOS7Missing:
- return "DSi ARM7 BIOS was not found or could not be accessed. Check your emu settings.";
- case Frontend::Load_DSiBIOS7Bad:
- return "DSi ARM7 BIOS is not a valid BIOS dump.";
+ gbaloaded = true;
+ }
- case Frontend::Load_DSiNANDMissing:
- return "DSi NAND was not found or could not be accessed. Check your emu settings.";
- case Frontend::Load_DSiNANDBad:
- return "DSi NAND is not a valid NAND dump.";
+ QStringList file = filename.split('|');
+ if (!ROMManager::LoadROM(file, true))
+ {
+ // TODO: better error reporting?
+ QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
+ return false;
+ }
+
+ recentFileList.removeAll(filename);
+ recentFileList.prepend(filename);
+ updateRecentFilesMenu();
+
+ NDS::Start();
+ emuThread->emuRun();
- case Frontend::Load_ROMLoadError:
- return "Failed to load the ROM. Make sure the file is accessible and isn't used by another application.";
+ updateCartInserted(false);
- default: return "Unknown error during launch; smack Arisotura.";
+ if (gbaloaded)
+ {
+ updateCartInserted(true);
}
+
+ return true;
}
-void MainWindow::loadROM(QByteArray *romData, QString archiveFileName, QString romFileName)
+QString MainWindow::pickFileFromArchive(QString archiveFileName)
{
- recentFileList.removeAll(archiveFileName);
- recentFileList.prepend(archiveFileName);
- updateRecentFilesMenu();
+ QVector<QString> archiveROMList = Archive::ListArchive(archiveFileName);
- // Strip entire archive name and get folder path
- strncpy(Config::LastROMFolder, QFileInfo(archiveFileName).absolutePath().toStdString().c_str(), 1024);
+ QString romFileName = ""; // file name inside archive
- QString sramFileName = QFileInfo(archiveFileName).absolutePath() + QDir::separator() + QFileInfo(romFileName).completeBaseName() + ".sav";
+ if (archiveROMList.size() > 2)
+ {
+ archiveROMList.removeFirst();
- int slot; int res;
- if (romFileName.endsWith("gba"))
+ bool ok;
+ QString toLoad = QInputDialog::getItem(this, "melonDS",
+ "This archive contains multiple files. Select which ROM you want to load.", archiveROMList.toList(), 0, false, &ok);
+ if (!ok) // User clicked on cancel
+ return QString();
+
+ romFileName = toLoad;
+ }
+ else if (archiveROMList.size() == 2)
{
- slot = 1;
- res = Frontend::LoadROM((const u8*)romData->constData(), romData->size(),
- archiveFileName.toStdString().c_str(),
- romFileName.toStdString().c_str(), sramFileName.toStdString().c_str(),
- Frontend::ROMSlot_GBA);
+ romFileName = archiveROMList.at(1);
}
- else
+ else if ((archiveROMList.size() == 1) && (archiveROMList[0] == QString("OK")))
{
- strncpy(Frontend::NDSROMExtension, QFileInfo(romFileName).suffix().toStdString().c_str(), 4);
- slot = 0;
- res = Frontend::LoadROM((const u8*)romData->constData(), romData->size(),
- archiveFileName.toStdString().c_str(),
- romFileName.toStdString().c_str(), sramFileName.toStdString().c_str(),
- Frontend::ROMSlot_NDS);
+ QMessageBox::warning(this, "melonDS", "This archive is empty.");
}
-
- if (res != Frontend::Load_OK)
+ else
{
- QMessageBox::critical(this,
- "melonDS",
- loadErrorStr(res));
- emuThread->emuUnpause();
+ QMessageBox::critical(this, "melonDS", "This archive could not be read. It may be corrupt or you don't have the permissions.");
}
- else if (slot == 1)
+
+ return romFileName;
+}
+
+QStringList MainWindow::pickROM(bool gba)
+{
+ QString console;
+ QStringList romexts;
+ QStringList arcexts{"*.zip", "*.7z", "*.rar", "*.tar", "*.tar.gz", "*.tar.xz", "*.tar.bz2"};
+ QStringList ret;
+
+ if (gba)
{
- // checkme
- emuThread->emuUnpause();
+ console = "GBA";
+ romexts.append("*.gba");
}
else
{
- emuThread->emuRun();
+ console = "DS";
+ romexts.append({"*.nds", "*.dsi", "*.ids", "*.srl"});
}
-}
-void MainWindow::loadROM(QString filename)
-{
- recentFileList.removeAll(filename);
- recentFileList.prepend(filename);
- updateRecentFilesMenu();
+ QString filter = romexts.join(' ') + " " + arcexts.join(' ');
+ filter = console + " ROMs (" + filter + ");;Any file (*.*)";
- // TODO: validate the input file!!
- // * check that it is a proper ROM
- // * ensure the binary offsets are sane
- // * etc
+ QString filename = QFileDialog::getOpenFileName(this,
+ "Open "+console+" ROM",
+ QString::fromStdString(Config::LastROMFolder),
+ filter);
+ if (filename.isEmpty())
+ return ret;
- // this shit is stupid
- char file[1024];
- strncpy(file, filename.toStdString().c_str(), 1023); file[1023] = '\0';
+ int pos = filename.length() - 1;
+ while (filename[pos] != '/' && filename[pos] != '\\' && pos > 0) pos--;
+ QString path_dir = filename.left(pos);
+ QString path_file = filename.mid(pos+1);
- int pos = strlen(file)-1;
- while (file[pos] != '/' && file[pos] != '\\' && pos > 0) pos--;
- strncpy(Config::LastROMFolder, file, pos);
- Config::LastROMFolder[pos] = '\0';
- char* ext = &file[strlen(file)-3];
+ Config::LastROMFolder = path_dir.toStdString();
- int slot; int res;
- if (!strcasecmp(ext, "gba"))
+ bool isarc = false;
+ for (const auto& ext : arcexts)
{
- slot = 1;
- res = Frontend::LoadROM(file, Frontend::ROMSlot_GBA);
+ int l = ext.length() - 1;
+ if (path_file.right(l).toLower() == ext.right(l))
+ {
+ isarc = true;
+ break;
+ }
+ }
+
+ if (isarc)
+ {
+ path_file = pickFileFromArchive(filename);
+ if (path_file.isEmpty())
+ return ret;
+
+ ret.append(filename);
+ ret.append(path_file);
}
else
{
- slot = 0;
- res = Frontend::LoadROM(file, Frontend::ROMSlot_NDS);
+ ret.append(filename);
}
- if (res != Frontend::Load_OK)
+ return ret;
+}
+
+void MainWindow::updateCartInserted(bool gba)
+{
+ bool inserted;
+ if (gba)
{
- QMessageBox::critical(this,
- "melonDS",
- loadErrorStr(res));
- emuThread->emuUnpause();
- }
- else if (slot == 1)
- {
- // checkme
- emuThread->emuUnpause();
+ inserted = ROMManager::GBACartInserted() && (Config::ConsoleType == 0);
+ actCurrentGBACart->setText("GBA slot: " + ROMManager::GBACartLabel());
+ actEjectGBACart->setEnabled(inserted);
}
else
{
- emuThread->emuRun();
+ inserted = ROMManager::CartInserted();
+ actCurrentCart->setText("DS slot: " + ROMManager::CartLabel());
+ actEjectCart->setEnabled(inserted);
+ actImportSavefile->setEnabled(inserted);
+ actSetupCheats->setEnabled(inserted);
+ actROMInfo->setEnabled(inserted);
}
}
@@ -1992,99 +2078,43 @@ void MainWindow::onOpenFile()
{
emuThread->emuPause();
- QString filename = QFileDialog::getOpenFileName(this,
- "Open ROM",
- Config::LastROMFolder,
- "DS ROMs (*.nds *.dsi *.srl);;GBA ROMs (*.gba *.zip);;Any file (*.*)");
- if (filename.isEmpty())
+ if (!verifySetup())
{
emuThread->emuUnpause();
return;
}
- loadROM(filename);
-}
-
-void MainWindow::onOpenFileArchive()
-{
- emuThread->emuPause();
-
- QString archiveFileName = QFileDialog::getOpenFileName(this,
- "Open ROM Archive",
- Config::LastROMFolder,
- "Archived ROMs (*.zip *.7z *.rar *.tar *.tar.gz *.tar.xz *.tar.bz2);;Any file (*.*)");
- if (archiveFileName.isEmpty())
+ QStringList file = pickROM(false);
+ if (file.isEmpty())
{
emuThread->emuUnpause();
return;
}
- QByteArray romBuffer;
- QString romFileName = pickAndExtractFileFromArchive(archiveFileName, &romBuffer);
- if(!romFileName.isEmpty())
+ if (!ROMManager::LoadROM(file, true))
{
- loadROM(&romBuffer, archiveFileName, romFileName);
+ // TODO: better error reporting?
+ QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
+ emuThread->emuUnpause();
+ return;
}
-}
-
-QString MainWindow::pickAndExtractFileFromArchive(QString archiveFileName, QByteArray *romBuffer)
-{
- printf("Finding list of ROMs...\n");
- QVector<QString> archiveROMList = Archive::ListArchive(archiveFileName.toUtf8().constData());
-
-
- QString romFileName; // file name inside archive
- if (archiveROMList.size() > 2)
- {
- archiveROMList.removeFirst();
+ QString filename = file.join('|');
+ recentFileList.removeAll(filename);
+ recentFileList.prepend(filename);
+ updateRecentFilesMenu();
- bool ok;
- QString toLoad = QInputDialog::getItem(this, "melonDS",
- "The archive was found to have multiple files. Select which ROM you want to load.", archiveROMList.toList(), 0, false, &ok);
- if(!ok) // User clicked on cancel
- return QString();
+ NDS::Start();
+ emuThread->emuRun();
- printf("Extracting '%s'\n", toLoad.toUtf8().constData());
- QVector<QString> extractResult = Archive::ExtractFileFromArchive(archiveFileName.toUtf8().constData(), toLoad.toUtf8().constData(), romBuffer);
- if (extractResult[0] != QString("Err"))
- {
- romFileName = extractResult[0];
- }
- else
- {
- QMessageBox::critical(this, "melonDS", QString("There was an error while trying to extract the ROM from the archive: ") + extractResult[1]);
- }
- }
- else if (archiveROMList.size() == 2)
- {
- printf("Extracting the only ROM in archive\n");
- QVector<QString> extractResult = Archive::ExtractFileFromArchive(archiveFileName.toUtf8().constData(), archiveROMList.at(1).toUtf8().constData(), romBuffer);
- if (extractResult[0] != QString("Err"))
- {
- romFileName = extractResult[0];
- }
- else
- {
- QMessageBox::critical(this, "melonDS", QString("There was an error while trying to extract the ROM from the archive: ") + extractResult[1]);
- }
- }
- else if ((archiveROMList.size() == 1) && (archiveROMList[0] == QString("OK")))
- {
- QMessageBox::warning(this, "melonDS", "The archive is intact, but there are no files inside.");
- }
- else
- {
- QMessageBox::critical(this, "melonDS", "The archive could not be read. It may be corrupt or you don't have the permissions.");
- }
-
- return romFileName;
+ updateCartInserted(false);
}
void MainWindow::onClearRecentFiles()
{
recentFileList.clear();
- memset(Config::RecentROMList, 0, 10 * 1024);
+ for (int i = 0; i < 10; i++)
+ Config::RecentROMList[i] = "";
updateRecentFilesMenu();
}
@@ -2092,8 +2122,10 @@ void MainWindow::updateRecentFilesMenu()
{
recentMenu->clear();
- for(int i = 0; i < recentFileList.size(); ++i)
+ for (int i = 0; i < recentFileList.size(); ++i)
{
+ if (i >= 10) break;
+
QString item_full = recentFileList.at(i);
QString item_display = item_full;
int itemlen = item_full.length();
@@ -2120,16 +2152,18 @@ void MainWindow::updateRecentFilesMenu()
actRecentFile_i->setData(item_full);
connect(actRecentFile_i, &QAction::triggered, this, &MainWindow::onClickRecentFile);
- if(i < 10)
- strncpy(Config::RecentROMList[i], recentFileList.at(i).toStdString().c_str(), 1024);
+ Config::RecentROMList[i] = recentFileList.at(i).toStdString();
}
+ while (recentFileList.size() > 10)
+ recentFileList.removeLast();
+
recentMenu->addSeparator();
QAction *actClearRecentList = recentMenu->addAction("Clear");
connect(actClearRecentList, &QAction::triggered, this, &MainWindow::onClearRecentFiles);
- if(recentFileList.empty())
+ if (recentFileList.empty())
actClearRecentList->setEnabled(false);
Config::Save();
@@ -2138,48 +2172,139 @@ void MainWindow::updateRecentFilesMenu()
void MainWindow::onClickRecentFile()
{
QAction *act = (QAction *)sender();
- QString fileName = act->data().toString();
+ QString filename = act->data().toString();
+ QStringList file = filename.split('|');
+
+ emuThread->emuPause();
- if (fileName.endsWith(".gba", Qt::CaseInsensitive) ||
- fileName.endsWith(".nds", Qt::CaseInsensitive) ||
- fileName.endsWith(".srl", Qt::CaseInsensitive) ||
- fileName.endsWith(".dsi", Qt::CaseInsensitive))
+ if (!verifySetup())
{
- emuThread->emuPause();
- loadROM(fileName);
+ emuThread->emuUnpause();
+ return;
}
- else
+
+ if (!ROMManager::LoadROM(file, true))
{
- // Archives
- QString archiveFileName = fileName;
- QByteArray romBuffer;
- QString romFileName = MainWindow::pickAndExtractFileFromArchive(archiveFileName, &romBuffer);
- if(!romFileName.isEmpty())
- {
- emuThread->emuPause();
- loadROM(&romBuffer, archiveFileName, romFileName);
- }
+ // TODO: better error reporting?
+ QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
+ emuThread->emuUnpause();
+ return;
}
+
+ recentFileList.removeAll(filename);
+ recentFileList.prepend(filename);
+ updateRecentFilesMenu();
+
+ NDS::Start();
+ emuThread->emuRun();
+
+ updateCartInserted(false);
}
void MainWindow::onBootFirmware()
{
- // TODO: check the whole GBA cart shito
+ emuThread->emuPause();
+ if (!verifySetup())
+ {
+ emuThread->emuUnpause();
+ return;
+ }
+
+ if (!ROMManager::LoadBIOS())
+ {
+ // TODO: better error reporting?
+ QMessageBox::critical(this, "melonDS", "This firmware is not bootable.");
+ emuThread->emuUnpause();
+ return;
+ }
+
+ NDS::Start();
+ emuThread->emuRun();
+}
+
+void MainWindow::onInsertCart()
+{
emuThread->emuPause();
- int res = Frontend::LoadBIOS();
- if (res != Frontend::Load_OK)
+ QStringList file = pickROM(false);
+ if (file.isEmpty())
{
- QMessageBox::critical(this,
- "melonDS",
- loadErrorStr(res));
emuThread->emuUnpause();
+ return;
}
- else
+
+ if (!ROMManager::LoadROM(file, false))
{
- emuThread->emuRun();
+ // TODO: better error reporting?
+ QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
+ emuThread->emuUnpause();
+ return;
+ }
+
+ emuThread->emuUnpause();
+
+ updateCartInserted(false);
+}
+
+void MainWindow::onEjectCart()
+{
+ emuThread->emuPause();
+
+ ROMManager::EjectCart();
+
+ emuThread->emuUnpause();
+
+ updateCartInserted(false);
+}
+
+void MainWindow::onInsertGBACart()
+{
+ emuThread->emuPause();
+
+ QStringList file = pickROM(true);
+ if (file.isEmpty())
+ {
+ emuThread->emuUnpause();
+ return;
+ }
+
+ if (!ROMManager::LoadGBAROM(file))
+ {
+ // TODO: better error reporting?
+ QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
+ emuThread->emuUnpause();
+ return;
}
+
+ emuThread->emuUnpause();
+
+ updateCartInserted(true);
+}
+
+void MainWindow::onInsertGBAAddon()
+{
+ QAction* act = (QAction*)sender();
+ int type = act->data().toInt();
+
+ emuThread->emuPause();
+
+ ROMManager::LoadGBAAddon(type);
+
+ emuThread->emuUnpause();
+
+ updateCartInserted(true);
+}
+
+void MainWindow::onEjectGBACart()
+{
+ emuThread->emuPause();
+
+ ROMManager::EjectGBACart();
+
+ emuThread->emuUnpause();
+
+ updateCartInserted(true);
}
void MainWindow::onSaveState()
@@ -2188,17 +2313,17 @@ void MainWindow::onSaveState()
emuThread->emuPause();
- char filename[1024];
+ std::string filename;
if (slot > 0)
{
- Frontend::GetSavestateName(slot, filename, 1024);
+ filename = ROMManager::GetSavestateName(slot);
}
else
{
// TODO: specific 'last directory' for savestate files?
QString qfilename = QFileDialog::getSaveFileName(this,
"Save state",
- Config::LastROMFolder,
+ QString::fromStdString(Config::LastROMFolder),
"melonDS savestates (*.mln);;Any file (*.*)");
if (qfilename.isEmpty())
{
@@ -2206,10 +2331,10 @@ void MainWindow::onSaveState()
return;
}
- strncpy(filename, qfilename.toStdString().c_str(), 1023); filename[1023] = '\0';
+ filename = qfilename.toStdString();
}
- if (Frontend::SaveState(filename))
+ if (ROMManager::SaveState(filename))
{
char msg[64];
if (slot > 0) sprintf(msg, "State saved to slot %d", slot);
@@ -2232,17 +2357,17 @@ void MainWindow::onLoadState()
emuThread->emuPause();
- char filename[1024];
+ std::string filename;
if (slot > 0)
{
- Frontend::GetSavestateName(slot, filename, 1024);
+ filename = ROMManager::GetSavestateName(slot);
}
else
{
// TODO: specific 'last directory' for savestate files?
QString qfilename = QFileDialog::getOpenFileName(this,
"Load state",
- Config::LastROMFolder,
+ QString::fromStdString(Config::LastROMFolder),
"melonDS savestates (*.ml*);;Any file (*.*)");
if (qfilename.isEmpty())
{
@@ -2250,7 +2375,7 @@ void MainWindow::onLoadState()
return;
}
- strncpy(filename, qfilename.toStdString().c_str(), 1023); filename[1023] = '\0';
+ filename = qfilename.toStdString();
}
if (!Platform::FileExists(filename))
@@ -2264,7 +2389,7 @@ void MainWindow::onLoadState()
return;
}
- if (Frontend::LoadState(filename))
+ if (ROMManager::LoadState(filename))
{
char msg[64];
if (slot > 0) sprintf(msg, "State loaded from slot %d", slot);
@@ -2284,7 +2409,7 @@ void MainWindow::onLoadState()
void MainWindow::onUndoStateLoad()
{
emuThread->emuPause();
- Frontend::UndoStateLoad();
+ ROMManager::UndoStateLoad();
emuThread->emuUnpause();
OSD::AddMessage(0, "State load undone");
@@ -2292,36 +2417,52 @@ void MainWindow::onUndoStateLoad()
void MainWindow::onImportSavefile()
{
- if (!RunningSomething) return;
-
emuThread->emuPause();
QString path = QFileDialog::getOpenFileName(this,
"Select savefile",
- Config::LastROMFolder,
+ QString::fromStdString(Config::LastROMFolder),
"Savefiles (*.sav *.bin *.dsv);;Any file (*.*)");
- if (!path.isEmpty())
+ if (path.isEmpty())
+ {
+ emuThread->emuUnpause();
+ return;
+ }
+
+ FILE* f = Platform::OpenFile(path.toStdString(), "rb", true);
+ if (!f)
+ {
+ QMessageBox::critical(this, "melonDS", "Could not open the given savefile.");
+ emuThread->emuUnpause();
+ return;
+ }
+
+ if (RunningSomething)
{
if (QMessageBox::warning(this,
- "Emulation will be reset and data overwritten",
+ "melonDS",
"The emulation will be reset and the current savefile overwritten.",
- QMessageBox::Ok, QMessageBox::Cancel) == QMessageBox::Ok)
+ QMessageBox::Ok, QMessageBox::Cancel) != QMessageBox::Ok)
{
- int res = Frontend::Reset();
- if (res != Frontend::Load_OK)
- {
- QMessageBox::critical(this, "melonDS", "Reset failed\n" + loadErrorStr(res));
- }
- else
- {
- int diff = Frontend::ImportSRAM(path.toStdString().c_str());
- if (diff > 0)
- OSD::AddMessage(0, "Trimmed savefile");
- else if (diff < 0)
- OSD::AddMessage(0, "Savefile shorter than SRAM");
- }
+ emuThread->emuUnpause();
+ return;
}
+
+ ROMManager::Reset();
}
+
+ u32 len;
+ fseek(f, 0, SEEK_END);
+ len = (u32)ftell(f);
+
+ u8* data = new u8[len];
+ fseek(f, 0, SEEK_SET);
+ fread(data, len, 1, f);
+
+ NDS::LoadSave(data, len);
+ delete[] data;
+
+ fclose(f);
emuThread->emuUnpause();
}
@@ -2360,19 +2501,10 @@ void MainWindow::onReset()
actUndoStateLoad->setEnabled(false);
- int res = Frontend::Reset();
- if (res != Frontend::Load_OK)
- {
- QMessageBox::critical(this,
- "melonDS",
- loadErrorStr(res));
- emuThread->emuUnpause();
- }
- else
- {
- OSD::AddMessage(0, "Reset");
- emuThread->emuRun();
- }
+ ROMManager::Reset();
+
+ OSD::AddMessage(0, "Reset");
+ emuThread->emuRun();
}
void MainWindow::onStop()
@@ -2393,7 +2525,7 @@ void MainWindow::onFrameStep()
void MainWindow::onEnableCheats(bool checked)
{
Config::EnableCheats = checked?1:0;
- Frontend::EnableCheats(Config::EnableCheats != 0);
+ ROMManager::EnableCheats(Config::EnableCheats != 0);
}
void MainWindow::onSetupCheats()
@@ -2431,11 +2563,28 @@ void MainWindow::onEmuSettingsDialogFinished(int res)
{
emuThread->emuUnpause();
+ if (Config::ConsoleType == 1)
+ {
+ actInsertGBACart->setEnabled(false);
+ for (int i = 0; i < 1; i++)
+ actInsertGBAAddon[i]->setEnabled(false);
+ actEjectGBACart->setEnabled(false);
+ }
+ else
+ {
+ actInsertGBACart->setEnabled(true);
+ for (int i = 0; i < 1; i++)
+ actInsertGBAAddon[i]->setEnabled(true);
+ actEjectGBACart->setEnabled(ROMManager::GBACartInserted());
+ }
+
if (EmuSettingsDialog::needsReset)
onReset();
+ actCurrentGBACart->setText("GBA slot: " + ROMManager::GBACartLabel());
+
if (!RunningSomething)
- actTitleManager->setEnabled(strlen(Config::DSiNANDPath) > 0);
+ actTitleManager->setEnabled(!Config::DSiNANDPath.empty());
}
void MainWindow::onOpenInputConfig()
@@ -2480,6 +2629,22 @@ void MainWindow::onFirmwareSettingsFinished(int res)
emuThread->emuUnpause();
}
+void MainWindow::onOpenPathSettings()
+{
+ emuThread->emuPause();
+
+ PathSettingsDialog* dlg = PathSettingsDialog::openDlg(this);
+ connect(dlg, &PathSettingsDialog::finished, this, &MainWindow::onPathSettingsFinished);
+}
+
+void MainWindow::onPathSettingsFinished(int res)
+{
+ if (PathSettingsDialog::needsReset)
+ onReset();
+
+ emuThread->emuUnpause();
+}
+
void MainWindow::onUpdateAudioSettings()
{
SPU::SetInterpolation(Config::AudioInterp);
@@ -2678,39 +2843,22 @@ void MainWindow::onFullscreenToggled()
void MainWindow::onEmuStart()
{
- // TODO: make savestates work in DSi mode!!
- if (Config::ConsoleType == 1)
- {
- for (int i = 0; i < 9; i++)
- {
- actSaveState[i]->setEnabled(false);
- actLoadState[i]->setEnabled(false);
- }
- actUndoStateLoad->setEnabled(false);
- }
- else
+ for (int i = 1; i < 9; i++)
{
- for (int i = 1; i < 9; i++)
- {
- actSaveState[i]->setEnabled(true);
- actLoadState[i]->setEnabled(Frontend::SavestateExists(i));
- }
- actSaveState[0]->setEnabled(true);
- actLoadState[0]->setEnabled(true);
- actUndoStateLoad->setEnabled(false);
+ actSaveState[i]->setEnabled(true);
+ actLoadState[i]->setEnabled(ROMManager::SavestateExists(i));
}
+ actSaveState[0]->setEnabled(true);
+ actLoadState[0]->setEnabled(true);
+ actUndoStateLoad->setEnabled(false);
actPause->setEnabled(true);
actPause->setChecked(false);
actReset->setEnabled(true);
actStop->setEnabled(true);
actFrameStep->setEnabled(true);
- actImportSavefile->setEnabled(true);
- actSetupCheats->setEnabled(true);
actTitleManager->setEnabled(false);
-
- actROMInfo->setEnabled(true);
}
void MainWindow::onEmuStop()
@@ -2723,17 +2871,13 @@ void MainWindow::onEmuStop()
actLoadState[i]->setEnabled(false);
}
actUndoStateLoad->setEnabled(false);
- actImportSavefile->setEnabled(false);
actPause->setEnabled(false);
actReset->setEnabled(false);
actStop->setEnabled(false);
actFrameStep->setEnabled(false);
- actSetupCheats->setEnabled(false);
- actTitleManager->setEnabled(strlen(Config::DSiNANDPath) > 0);
-
- actROMInfo->setEnabled(false);
+ actTitleManager->setEnabled(!Config::DSiNANDPath.empty());
}
void MainWindow::onUpdateVideoSettings(bool glchange)
@@ -2767,9 +2911,6 @@ void emuStop()
{
RunningSomething = false;
- Frontend::UnloadROM(Frontend::ROMSlot_NDS);
- Frontend::UnloadROM(Frontend::ROMSlot_GBA);
-
emit emuThread->windowEmuStop();
OSD::AddMessage(0xFFC040, "Shutdown");
@@ -2788,7 +2929,8 @@ bool MelonApplication::event(QEvent *event)
QFileOpenEvent *openEvent = static_cast<QFileOpenEvent*>(event);
emuThread->emuPause();
- mainWindow->loadROM(openEvent->file());
+ if (!mainWindow->preloadROMs(openEvent->file(), ""))
+ emuThread->emuUnpause();
}
return QApplication::event(event);
@@ -2886,8 +3028,7 @@ int main(int argc, char** argv)
micExtBufferWritePos = 0;
micWavBuffer = nullptr;
- Frontend::Init_ROM();
- Frontend::EnableCheats(Config::EnableCheats != 0);
+ ROMManager::EnableCheats(Config::EnableCheats != 0);
Frontend::Init_Audio(audioFreq);
@@ -2914,29 +3055,11 @@ int main(int argc, char** argv)
if (argc > 1)
{
- char* file = argv[1];
- char* ext = &file[strlen(file)-3];
-
- if (!strcasecmp(ext, "nds") || !strcasecmp(ext, "srl") || !strcasecmp(ext, "dsi"))
- {
- int res = Frontend::LoadROM(file, Frontend::ROMSlot_NDS);
+ QString file = argv[1];
+ QString gbafile = "";
+ if (argc > 2) gbafile = argv[2];
- if (res == Frontend::Load_OK)
- {
- if (argc > 2)
- {
- file = argv[2];
- ext = &file[strlen(file)-3];
-
- if (!strcasecmp(ext, "gba"))
- {
- Frontend::LoadROM(file, Frontend::ROMSlot_GBA);
- }
- }
-
- emuThread->emuRun();
- }
- }
+ mainWindow->preloadROMs(file, gbafile);
}
int ret = melon.exec();
@@ -2947,8 +3070,6 @@ int main(int argc, char** argv)
Input::CloseJoystick();
- Frontend::DeInit_ROM();
-
if (audioDevice) SDL_CloseAudioDevice(audioDevice);
micClose();