aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorpatata <patataofcourse@gmail.com>2022-10-28 12:27:55 +0200
committerGitHub <noreply@github.com>2022-10-28 12:27:55 +0200
commit561781b9542fb5667ed43a38ac28c6b90a318405 (patch)
treef3d90129e80f5021f8b260b071c586037dab124e /src
parent936011964ce69158367654cbcdbc30bb0d06376a (diff)
CLI 2.0: Electric Boogaloo (#1546)
* CLI: begin QT reimplementation * Add first batch of parameters * ROM loading (no archives yet) * --fullscreen * --boot (non-functional???) * fix --boot * archives! * Add disclaimer that a.zip|b.nds is kind of fucky * remove shit7 debugging * Apply requested changes
Diffstat (limited to 'src')
-rw-r--r--src/frontend/qt_sdl/CLI.cpp135
-rw-r--r--src/frontend/qt_sdl/CLI.h41
-rw-r--r--src/frontend/qt_sdl/CMakeLists.txt3
-rw-r--r--src/frontend/qt_sdl/ROMManager.cpp17
-rw-r--r--src/frontend/qt_sdl/main.cpp72
-rw-r--r--src/frontend/qt_sdl/main.h2
6 files changed, 235 insertions, 35 deletions
diff --git a/src/frontend/qt_sdl/CLI.cpp b/src/frontend/qt_sdl/CLI.cpp
new file mode 100644
index 0000000..5d8ebd1
--- /dev/null
+++ b/src/frontend/qt_sdl/CLI.cpp
@@ -0,0 +1,135 @@
+/*
+ Copyright 2021-2022 melonDS team
+
+ This file is part of melonDS.
+
+ melonDS is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with melonDS. If not, see http://www.gnu.org/licenses/.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <QApplication>
+#include <QCommandLineParser>
+#include <QStringList>
+
+#include "CLI.h"
+
+namespace CLI
+{
+
+CommandLineOptions* ManageArgs(QApplication& melon)
+{
+ QCommandLineParser parser;
+ parser.addHelpOption();
+
+ parser.addPositionalArgument("nds", "Nintendo DS ROM (or an archive file which contains it) to load into Slot-1");
+ parser.addPositionalArgument("gba", "GBA ROM (or an archive file which contains it) to load into Slot-2");
+
+ parser.addOption(QCommandLineOption({"b", "boot"}, "Whether to boot firmware on startup. Defaults to \"auto\" (boot if NDS rom given)", "auto/always/never", "auto"));
+ parser.addOption(QCommandLineOption({"f", "fullscreen"}, "Start melonDS in fullscreen mode"));
+
+#ifdef ARCHIVE_SUPPORT_ENABLED
+ parser.addOption(QCommandLineOption({"a", "archive-file"}, "Specify file to load inside an archive given (NDS)", "rom"));
+ parser.addOption(QCommandLineOption({"A", "archive-file-gba"}, "Specify file to load inside an archive given (GBA)", "rom"));
+#endif
+
+ parser.process(melon);
+
+ CommandLineOptions* options = new CommandLineOptions;
+
+ options->fullscreen = parser.isSet("fullscreen");
+
+ QStringList posargs = parser.positionalArguments();
+ switch (posargs.size())
+ {
+ default:
+ printf("Too many positional arguments; ignoring 3 onwards\n");
+ case 2:
+ options->gbaRomPath = QStringList(posargs[1]);
+ case 1:
+ options->dsRomPath = QStringList(posargs[0]);
+ case 0:
+ break;
+ }
+
+ QString bootMode = parser.value("boot");
+ if (bootMode == "auto")
+ {
+ options->boot = posargs.size() > 0;
+ }
+ else if (bootMode == "always")
+ {
+ options->boot = true;
+ }
+ else if (bootMode == "never")
+ {
+ options->boot = false;
+ }
+ else
+ {
+ printf("ERROR: -b/--boot only accepts auto/always/never as arguments\n");
+ exit(1);
+ }
+
+#ifdef ARCHIVE_SUPPORT_ENABLED
+ if (parser.isSet("archive-file"))
+ {
+ if (options->dsRomPath.isEmpty())
+ {
+ options->errorsToDisplay += "Option -a/--archive-file given, but no archive specified!";
+ }
+ else
+ {
+ options->dsRomPath += parser.value("archive-file");
+ }
+ }
+ else if (!options->dsRomPath.isEmpty())
+ {
+ //TODO-CLI: try to automatically find ROM
+ QStringList paths = options->dsRomPath[0].split("|");
+ if (paths.size() >= 2)
+ {
+ printf("Warning: use the a.zip|b.nds format at your own risk!\n");
+ options->dsRomPath = paths;
+ }
+ }
+
+ if (parser.isSet("archive-file-gba"))
+ {
+ if (options->gbaRomPath.isEmpty())
+ {
+ options->errorsToDisplay += "Option -A/--archive-file-gba given, but no archive specified!";
+ }
+ else
+ {
+ options->gbaRomPath += parser.value("archive-file-gba");
+ }
+ }
+ else if (!options->gbaRomPath.isEmpty())
+ {
+ //TODO-CLI: try to automatically find ROM
+ QStringList paths = options->gbaRomPath[0].split("|");
+ if (paths.size() >= 2)
+ {
+ printf("Warning: use the a.zip|b.gba format at your own risk!\n");
+ options->gbaRomPath = paths;
+ }
+ }
+#endif
+
+ return options;
+}
+
+} \ No newline at end of file
diff --git a/src/frontend/qt_sdl/CLI.h b/src/frontend/qt_sdl/CLI.h
new file mode 100644
index 0000000..18520fa
--- /dev/null
+++ b/src/frontend/qt_sdl/CLI.h
@@ -0,0 +1,41 @@
+/*
+ Copyright 2021-2022 melonDS team
+
+ This file is part of melonDS.
+
+ melonDS is free software: you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or (at your option)
+ any later version.
+
+ melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with melonDS. If not, see http://www.gnu.org/licenses/.
+*/
+
+#ifndef CLI_H
+#define CLI_H
+
+#include <QApplication>
+#include <QStringList>
+
+namespace CLI {
+
+struct CommandLineOptions
+{
+ QStringList errorsToDisplay = {};
+
+ QStringList dsRomPath;
+ QStringList gbaRomPath;
+ bool fullscreen;
+ bool boot;
+};
+
+extern CommandLineOptions* ManageArgs(QApplication& melon);
+
+}
+
+#endif
diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt
index bfa58bf..6b964f3 100644
--- a/src/frontend/qt_sdl/CMakeLists.txt
+++ b/src/frontend/qt_sdl/CMakeLists.txt
@@ -49,6 +49,9 @@ set(SOURCES_QT_SDL
../duckstation/gl/context.cpp
${CMAKE_SOURCE_DIR}/res/melon.qrc
+
+ CLI.h
+ CLI.cpp
)
if (APPLE)
diff --git a/src/frontend/qt_sdl/ROMManager.cpp b/src/frontend/qt_sdl/ROMManager.cpp
index 716a454..e5479b2 100644
--- a/src/frontend/qt_sdl/ROMManager.cpp
+++ b/src/frontend/qt_sdl/ROMManager.cpp
@@ -503,6 +503,7 @@ bool LoadROM(QStringList filepath, bool reset)
if (len > 0x40000000)
{
fclose(f);
+ delete[] filedata;
return false;
}
@@ -528,14 +529,14 @@ bool LoadROM(QStringList filepath, bool reset)
{
// file inside archive
- u32 lenread = Archive::ExtractFileFromArchive(filepath.at(0), filepath.at(1), &filedata, &filelen);
- if (lenread < 0) return false;
- if (!filedata) return false;
- if (lenread != filelen)
- {
- delete[] filedata;
- return false;
- }
+ s32 lenread = Archive::ExtractFileFromArchive(filepath.at(0), filepath.at(1), &filedata, &filelen);
+ if (lenread < 0) return false;
+ if (!filedata) return false;
+ if (lenread != filelen)
+ {
+ delete[] filedata;
+ return false;
+ }
std::string std_archivepath = filepath.at(0).toStdString();
basepath = std_archivepath.substr(0, LastSep(std_archivepath));
diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp
index bea8c6d..e8e30a7 100644
--- a/src/frontend/qt_sdl/main.cpp
+++ b/src/frontend/qt_sdl/main.cpp
@@ -36,6 +36,7 @@
#include <QKeyEvent>
#include <QMimeData>
#include <QVector>
+#include <QCommandLineParser>
#ifndef _WIN32
#include <QGuiApplication>
#include <QSocketNotifier>
@@ -94,6 +95,8 @@
#include "ArchiveUtil.h"
#include "CameraManager.h"
+#include "CLI.h"
+
// TODO: uniform variable spelling
bool RunningSomething;
@@ -2126,7 +2129,7 @@ bool MainWindow::verifySetup()
return true;
}
-bool MainWindow::preloadROMs(QString filename, QString gbafilename)
+bool MainWindow::preloadROMs(QStringList file, QStringList gbafile, bool boot)
{
if (!verifySetup())
{
@@ -2134,9 +2137,8 @@ bool MainWindow::preloadROMs(QString filename, QString gbafilename)
}
bool gbaloaded = false;
- if (!gbafilename.isEmpty())
+ if (!gbafile.isEmpty())
{
- QStringList gbafile = gbafilename.split('|');
if (!ROMManager::LoadGBAROM(gbafile))
{
// TODO: better error reporting?
@@ -2147,20 +2149,33 @@ bool MainWindow::preloadROMs(QString filename, QString gbafilename)
gbaloaded = true;
}
- QStringList file = filename.split('|');
- if (!ROMManager::LoadROM(file, true))
+ bool ndsloaded = false;
+ if (!file.isEmpty())
{
- // TODO: better error reporting?
- QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
- return false;
+ if (!ROMManager::LoadROM(file, true))
+ {
+ // TODO: better error reporting?
+ QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
+ return false;
+ }
+ recentFileList.removeAll(file.join("|"));
+ recentFileList.prepend(file.join("|"));
+ updateRecentFilesMenu();
+ ndsloaded = true;
}
- recentFileList.removeAll(filename);
- recentFileList.prepend(filename);
- updateRecentFilesMenu();
-
- NDS::Start();
- emuThread->emuRun();
+ if (boot)
+ {
+ if (ndsloaded)
+ {
+ NDS::Start();
+ emuThread->emuRun();
+ }
+ else
+ {
+ onBootFirmware();
+ }
+ }
updateCartInserted(false);
@@ -2428,7 +2443,7 @@ void MainWindow::onBootFirmware()
}
if (!ROMManager::LoadBIOS())
- {
+{
// TODO: better error reporting?
QMessageBox::critical(this, "melonDS", "This firmware is not bootable.");
emuThread->emuUnpause();
@@ -3115,8 +3130,7 @@ void MainWindow::onTitleUpdate(QString title)
setWindowTitle(title);
}
-void MainWindow::onFullscreenToggled()
-{
+void ToggleFullscreen(MainWindow* mainWindow) {
if (!mainWindow->isFullScreen())
{
mainWindow->showFullScreen();
@@ -3130,6 +3144,11 @@ void MainWindow::onFullscreenToggled()
}
}
+void MainWindow::onFullscreenToggled()
+{
+ ToggleFullscreen(this);
+}
+
void MainWindow::onEmuStart()
{
for (int i = 1; i < 9; i++)
@@ -3217,7 +3236,7 @@ bool MelonApplication::event(QEvent *event)
QFileOpenEvent *openEvent = static_cast<QFileOpenEvent*>(event);
emuThread->emuPause();
- if (!mainWindow->preloadROMs(openEvent->file(), ""))
+ if (!mainWindow->preloadROMs(openEvent->file().split("|"), {}, true))
emuThread->emuUnpause();
}
@@ -3233,10 +3252,16 @@ int main(int argc, char** argv)
printf("melonDS " MELONDS_VERSION "\n");
printf(MELONDS_URL "\n");
+ // easter egg - not worth checking other cases for something so dumb
+ if (argc != 0 && (!strcasecmp(argv[0], "derpDS") || !strcasecmp(argv[0], "./derpDS")))
+ printf("did you just call me a derp???\n");
+
Platform::Init(argc, argv);
MelonApplication melon(argc, argv);
+ CLI::CommandLineOptions* options = CLI::ManageArgs(melon);
+
// http://stackoverflow.com/questions/14543333/joystick-wont-work-using-sdl
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
@@ -3339,6 +3364,8 @@ int main(int argc, char** argv)
Input::OpenJoystick();
mainWindow = new MainWindow();
+ if (options->fullscreen)
+ ToggleFullscreen(mainWindow);
emuThread = new EmuThread();
emuThread->start();
@@ -3348,14 +3375,7 @@ int main(int argc, char** argv)
QObject::connect(&melon, &QApplication::applicationStateChanged, mainWindow, &MainWindow::onAppStateChanged);
- if (argc > 1)
- {
- QString file = argv[1];
- QString gbafile = "";
- if (argc > 2) gbafile = argv[2];
-
- mainWindow->preloadROMs(file, gbafile);
- }
+ mainWindow->preloadROMs(options->dsRomPath, options->gbaRomPath, options->boot);
int ret = melon.exec();
diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h
index 2e2a9ab..9f9fc7c 100644
--- a/src/frontend/qt_sdl/main.h
+++ b/src/frontend/qt_sdl/main.h
@@ -238,7 +238,7 @@ public:
bool hasOGL;
GL::Context* getOGLContext();
- bool preloadROMs(QString filename, QString gbafilename);
+ bool preloadROMs(QStringList file, QStringList gbafile, bool boot);
void onAppStateChanged(Qt::ApplicationState state);