Frontends: Add shared command line interface

Also provides batch mode and automatic fullscreen switching.

  -help: Displays this information and exits.
  -version: Displays version information and exits.
  -batch: Enables batch mode (exits after powering off)
  -fastboot: Force fast boot for provided filename
  -slowboot: Force slow boot for provided filename
  -resume: Load resume save state. If a boot filename is provided,
    that game's resume state will be loaded, otherwise the most
    recent resume save state will be loaded.
  -state <index>: Loads specified save state by index. If a boot
    filename is provided, a per-game state will be loaded, otherwise
    a global state will be loaded.
  -statefile <filename>: Loads state from the specified filename.
    No boot filename is required with this option.
  -fullscreen: Enters fullscreen mode immediately after starting.
  -nofullscreen: Prevents fullscreen mode from triggering if enabled.
  -portable: Forces "portable mode", data in same directory.
  --: Signals that no more arguments will follow and the remaining
    parameters make up the filename. Use when the filename contains
    spaces or starts with a dash.
This commit is contained in:
Connor McLaughlin
2020-04-13 22:13:46 +10:00
parent 6a03bb2d15
commit 81cf4b469f
12 changed files with 365 additions and 80 deletions

View File

@ -5,70 +5,8 @@
#include "sdl_host_interface.h"
#include <SDL.h>
#include <cstdio>
#include <cstdlib>
static int Run(int argc, char* argv[])
{
// parameters
std::optional<s32> state_index;
bool state_is_global = false;
const char* boot_filename = nullptr;
for (int i = 1; i < argc; i++)
{
#define CHECK_ARG(str) !std::strcmp(argv[i], str)
#define CHECK_ARG_PARAM(str) (!std::strcmp(argv[i], str) && ((i + 1) < argc))
if (CHECK_ARG_PARAM("-state") || CHECK_ARG_PARAM("-gstate"))
{
state_is_global = argv[i][1] == 'g';
state_index = std::atoi(argv[++i]);
}
else if (CHECK_ARG_PARAM("-resume"))
{
state_index = -1;
}
else
{
boot_filename = argv[i];
}
#undef CHECK_ARG
#undef CHECK_ARG_PARAM
}
// create display and host interface
std::unique_ptr<SDLHostInterface> host_interface = SDLHostInterface::Create();
if (!host_interface->Initialize())
{
host_interface->Shutdown();
Panic("Failed to initialize host interface");
SDL_Quit();
return -1;
}
// boot/load state
if (boot_filename)
{
SystemBootParameters boot_params;
boot_params.filename = boot_filename;
if (host_interface->BootSystem(boot_params) && state_index.has_value())
host_interface->LoadState(state_is_global, state_index.value());
}
else if (state_index.has_value())
{
host_interface->LoadState(true, state_index.value());
}
// run
host_interface->Run();
// done
host_interface->Shutdown();
host_interface.reset();
SDL_Quit();
return 0;
}
// SDL requires the entry point declared without c++ decoration
#undef main
int main(int argc, char* argv[])
{
@ -91,6 +29,38 @@ int main(int argc, char* argv[])
FrontendCommon::EnsureSDLInitialized();
// return NoGUITest();
return Run(argc, argv);
std::unique_ptr<SDLHostInterface> host_interface = SDLHostInterface::Create();
std::unique_ptr<SystemBootParameters> boot_params;
if (!host_interface->ParseCommandLineParameters(argc, argv, &boot_params))
{
SDL_Quit();
return EXIT_FAILURE;
}
if (!host_interface->Initialize())
{
host_interface->Shutdown();
SDL_Quit();
return EXIT_FAILURE;
}
if (boot_params)
{
if (!host_interface->BootSystem(*boot_params) && host_interface->InBatchMode())
{
host_interface->Shutdown();
host_interface.reset();
SDL_Quit();
return EXIT_FAILURE;
}
boot_params.reset();
}
host_interface->Run();
host_interface->Shutdown();
host_interface.reset();
SDL_Quit();
return EXIT_SUCCESS;
}

View File

@ -34,6 +34,11 @@ SDLHostInterface::SDLHostInterface()
SDLHostInterface::~SDLHostInterface() = default;
const char* SDLHostInterface::GetFrontendName() const
{
return "DuckStation SDL/ImGui Frontend";
}
float SDLHostInterface::GetDPIScaleFactor(SDL_Window* window)
{
#ifdef __APPLE__
@ -191,10 +196,6 @@ bool SDLHostInterface::AcquireHostDisplay()
}
#endif
// Switch to fullscreen if requested.
if (m_settings.start_fullscreen)
SetFullscreen(true);
return true;
}
@ -274,6 +275,11 @@ void SDLHostInterface::OnRunningGameChanged()
SDL_SetWindowTitle(m_window, "DuckStation");
}
void SDLHostInterface::RequestExit()
{
m_quit_request = true;
}
void SDLHostInterface::RunLater(std::function<void()> callback)
{
SDL_Event ev = {};

View File

@ -25,6 +25,8 @@ public:
static std::unique_ptr<SDLHostInterface> Create();
const char* GetFrontendName() const override;
void ReportError(const char* message) override;
void ReportMessage(const char* message) override;
bool ConfirmMessage(const char* message) override;
@ -47,6 +49,8 @@ protected:
void OnSystemDestroyed() override;
void OnRunningGameChanged() override;
void RequestExit() override;
std::optional<HostKeyCode> GetHostKeyCode(const std::string_view key_code) const override;
void UpdateInputMap() override;