Skip to content

Commit

Permalink
CLI 2.0: Electric Boogaloo (melonDS-emu#1546)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
patataofcourse authored Oct 28, 2022
1 parent 9360119 commit 561781b
Show file tree
Hide file tree
Showing 6 changed files with 235 additions and 35 deletions.
135 changes: 135 additions & 0 deletions src/frontend/qt_sdl/CLI.cpp
Original file line number Diff line number Diff line change
@@ -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 changes: 41 additions & 0 deletions src/frontend/qt_sdl/CLI.h
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions src/frontend/qt_sdl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ set(SOURCES_QT_SDL
../duckstation/gl/context.cpp

${CMAKE_SOURCE_DIR}/res/melon.qrc

CLI.h
CLI.cpp
)

if (APPLE)
Expand Down
17 changes: 9 additions & 8 deletions src/frontend/qt_sdl/ROMManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,7 @@ bool LoadROM(QStringList filepath, bool reset)
if (len > 0x40000000)
{
fclose(f);
delete[] filedata;
return false;
}

Expand All @@ -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));
Expand Down
72 changes: 46 additions & 26 deletions src/frontend/qt_sdl/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <QKeyEvent>
#include <QMimeData>
#include <QVector>
#include <QCommandLineParser>
#ifndef _WIN32
#include <QGuiApplication>
#include <QSocketNotifier>
Expand Down Expand Up @@ -94,6 +95,8 @@
#include "ArchiveUtil.h"
#include "CameraManager.h"

#include "CLI.h"

// TODO: uniform variable spelling

bool RunningSomething;
Expand Down Expand Up @@ -2126,17 +2129,16 @@ bool MainWindow::verifySetup()
return true;
}

bool MainWindow::preloadROMs(QString filename, QString gbafilename)
bool MainWindow::preloadROMs(QStringList file, QStringList gbafile, bool boot)
{
if (!verifySetup())
{
return false;
}

bool gbaloaded = false;
if (!gbafilename.isEmpty())
if (!gbafile.isEmpty())
{
QStringList gbafile = gbafilename.split('|');
if (!ROMManager::LoadGBAROM(gbafile))
{
// TODO: better error reporting?
Expand All @@ -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);

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -3115,8 +3130,7 @@ void MainWindow::onTitleUpdate(QString title)
setWindowTitle(title);
}

void MainWindow::onFullscreenToggled()
{
void ToggleFullscreen(MainWindow* mainWindow) {
if (!mainWindow->isFullScreen())
{
mainWindow->showFullScreen();
Expand All @@ -3130,6 +3144,11 @@ void MainWindow::onFullscreenToggled()
}
}

void MainWindow::onFullscreenToggled()
{
ToggleFullscreen(this);
}

void MainWindow::onEmuStart()
{
for (int i = 1; i < 9; i++)
Expand Down Expand Up @@ -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();
}

Expand All @@ -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");

Expand Down Expand Up @@ -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();
Expand All @@ -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();

Expand Down
2 changes: 1 addition & 1 deletion src/frontend/qt_sdl/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ class MainWindow : public QMainWindow
bool hasOGL;
GL::Context* getOGLContext();

bool preloadROMs(QString filename, QString gbafilename);
bool preloadROMs(QStringList file, QStringList gbafile, bool boot);

void onAppStateChanged(Qt::ApplicationState state);

Expand Down

0 comments on commit 561781b

Please sign in to comment.