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
This commit is contained in:
patata 2022-10-28 12:27:55 +02:00 committed by GitHub
parent 936011964c
commit 561781b954
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 235 additions and 35 deletions

135
src/frontend/qt_sdl/CLI.cpp Normal file
View File

@ -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;
}
}

41
src/frontend/qt_sdl/CLI.h Normal file
View File

@ -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

View File

@ -49,6 +49,9 @@ set(SOURCES_QT_SDL
../duckstation/gl/context.cpp
${CMAKE_SOURCE_DIR}/res/melon.qrc
CLI.h
CLI.cpp
)
if (APPLE)

View File

@ -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));

View File

@ -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();

View File

@ -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);