mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Merge pull request #21949 from hrydgard/cmdline-parse-refactor
Start work on unifying command line parsing
This commit is contained in:
24 files changed
+427
-274
No files matched your search
@@ -2142,6 +2142,8 @@ endif()
|
||||
add_library(${CoreLibName} ${CoreLinkType}
|
||||
${CoreExtra}
|
||||
${CommonJIT}
|
||||
Core/CmdLine.cpp
|
||||
Core/CmdLine.h
|
||||
Core/Config.cpp
|
||||
Core/Config.h
|
||||
Core/ConfigSettings.cpp
|
||||
|
||||
@@ -40,10 +40,12 @@ void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, boo
|
||||
// Otherwise, just return false.
|
||||
bool NativeIsAtTopLevel();
|
||||
|
||||
struct CommandLineOptions;
|
||||
|
||||
// The very first function to be called after NativeGetAppInfo. Even NativeMix is not called
|
||||
// before this, although it may be called at any point in time afterwards (on any thread!)
|
||||
// This functions must NOT call OpenGL. Main thread.
|
||||
void NativeInit(int argc, const char *argv[], const char *savegame_dir, const char *external_dir, const char *cache_dir);
|
||||
void NativeInit(int argc, const char *argv[], const CommandLineOptions &cmdLineOptions, const char *savegame_dir, const char *external_dir, const char *cache_dir);
|
||||
void NativeSetAchievementsHostOverride(std::string_view host);
|
||||
void NativeClearAchievementsHostOverride();
|
||||
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
#include "Core/Config.h"
|
||||
#include "Core/CmdLine.h"
|
||||
#include "Common/StringUtils.h"
|
||||
|
||||
#ifdef HAVE_LIBRETRO_VFS
|
||||
|
||||
// Actually, this probably shouldn't be built at all for libretro! But let's add the guard.
|
||||
|
||||
#define PRINT_STDOUT(...) printf(__VA_ARGS__)
|
||||
#define PRINT_STDERR(...) printf(__VA_ARGS__)
|
||||
|
||||
#else
|
||||
|
||||
#define PRINT_STDOUT(...) printf(__VA_ARGS__)
|
||||
#define PRINT_STDERR(...) fprintf(stderr, __VA_ARGS__)
|
||||
|
||||
#endif
|
||||
|
||||
static int printUsage(int argc, const char *argv[]) {
|
||||
// NOTE: by convention, --help outputs to stdout,
|
||||
// not to stderr, since it is intended output in this
|
||||
// case (usage printed under different circumstances,
|
||||
// say in response to error during parsing commandline,
|
||||
// may go to stderr).
|
||||
const char *progname = argc > 0 ? argv[0] : "ppsspp";
|
||||
// NOTE: wording largely taken from
|
||||
// https://www.ppsspp.org/docs/reference/command-line/
|
||||
PRINT_STDOUT("PPSSPP - a PSP emulator (SDL build)\n");
|
||||
PRINT_STDOUT("Usage: %s [options] [FILE]\n\n", progname);
|
||||
PRINT_STDOUT("Launches FILE (e.g. ISO image) if present.\n");
|
||||
PRINT_STDOUT("Options (some of these are specific to SDL backend):\n");
|
||||
PRINT_STDOUT(" -h, --help show this message and exit\n");
|
||||
PRINT_STDOUT(" --version show version information and exit\n");
|
||||
|
||||
PRINT_STDOUT(" -d set the log level to debug\n");
|
||||
PRINT_STDOUT(" -v set the log level to verbose\n");
|
||||
PRINT_STDOUT(" --loglevel=INTEGER set the log level to specified value\n");
|
||||
PRINT_STDOUT(" --log=FILE output log to FILE\n");
|
||||
PRINT_STDOUT(" --state=FILE load state from FILE\n");
|
||||
|
||||
PRINT_STDOUT(" -i use the interpreter\n");
|
||||
PRINT_STDOUT(" -r use IR interpreter\n");
|
||||
PRINT_STDOUT(" -j use JIT\n");
|
||||
PRINT_STDOUT(" -J use IR JIT\n");
|
||||
|
||||
PRINT_STDOUT(" --fullscreen force full screen mode, ignoring saved configuration\n");
|
||||
PRINT_STDOUT(" --windowed force windowed mode, ignoring saved configuration\n");
|
||||
PRINT_STDOUT(" --xres PIXELS set X resolution\n");
|
||||
PRINT_STDOUT(" --yres PIXELS set Y resolution\n");
|
||||
PRINT_STDOUT(" --dpi FACTOR set DPI\n");
|
||||
PRINT_STDOUT(" --scale FACTOR set scale\n");
|
||||
PRINT_STDOUT(" --ipad set resolution to 1024x768\n");
|
||||
PRINT_STDOUT(" --portrait portrait mode\n");
|
||||
PRINT_STDOUT(" --graphics=BACKEND use a different gpu backend\n");
|
||||
PRINT_STDOUT(" options: gles, software, etc. (also opengl3.1, etc.)\n");
|
||||
|
||||
PRINT_STDOUT(" --pause-menu-exit change \"Exit to menu\" in pause menu to \"Exit\"\n");
|
||||
PRINT_STDOUT(" --escape-exit escape key exits the application\n");
|
||||
PRINT_STDOUT(" --gamesettings go directly to settings\n");
|
||||
PRINT_STDOUT(" --touchscreentest go directly to the touchscreentest screen\n");
|
||||
PRINT_STDOUT(" --appendconfig=FILE merge config FILE into the current configuration\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Logging should be done with plain printf here.
|
||||
// Error reporting is done with PRINT_STDERR(....).
|
||||
// Actually might want to reconsider given Android...
|
||||
CommandLineParseResult CommandLineOptions::Parse(int argc, const char *argv[]) {
|
||||
constexpr std::string_view gpuBackendStr = "--graphics=";
|
||||
constexpr std::string_view configOption = "--config=";
|
||||
constexpr std::string_view controlsOption = "--controlconfig=";
|
||||
|
||||
#ifdef _DEBUG
|
||||
enableLogging = true;
|
||||
#endif
|
||||
|
||||
// The rest is handled in NativeInit().
|
||||
// NOTE: We don't increment i here, as we'll sometimes handle options that read the next argument.
|
||||
for (size_t i = 1; i < argc; ) {
|
||||
const size_t len = strlen(argv[i]);
|
||||
|
||||
if (len > 0 && argv[i][0] != '-') {
|
||||
// This is a filename to boot.
|
||||
if (!bootFilename.has_value()) {
|
||||
bootFilename = std::string(argv[i]);
|
||||
} else {
|
||||
// Already have a filename.
|
||||
PRINT_STDERR("Warning: Ignoring extra boot filename '%s'.\n", argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// single char commands, like -l, -s, -d
|
||||
if (len == 2) {
|
||||
switch (argv[i][1]) {
|
||||
case 'l':
|
||||
showLogWindow = true;
|
||||
enableLogging = true;
|
||||
break;
|
||||
case 's':
|
||||
optionS = true;
|
||||
break;
|
||||
case 'd':
|
||||
debugLogLevel = true;
|
||||
break;
|
||||
case 'h':
|
||||
printUsage(argc, argv);
|
||||
return CommandLineParseResult::Exit;
|
||||
case 'v':
|
||||
printf("%s\n", PPSSPP_GIT_VERSION);
|
||||
return CommandLineParseResult::Exit;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__APPLE__)
|
||||
// On Apple system debugged executable may get -NSDocumentRevisionsDebugMode YES in argv.
|
||||
if (equals(argv[i], "-NSDocumentRevisionsDebugMode")) {
|
||||
// Ignore
|
||||
}
|
||||
#endif
|
||||
// Simple bool commands
|
||||
|
||||
// NOTE: We need to parse --fullscreen early, before we create the window.
|
||||
if (equals(argv[i], "--help")) {
|
||||
printUsage(argc, argv);
|
||||
return CommandLineParseResult::Exit;
|
||||
} else if (equals(argv[i], "--version")) {
|
||||
printf("%s\n", PPSSPP_GIT_VERSION);
|
||||
return CommandLineParseResult::Exit;
|
||||
} else if (equals(argv[i], "--fullscreen")) {
|
||||
fullscreen = true;
|
||||
} else if (equals(argv[i], "--windowed")) {
|
||||
fullscreen = false;
|
||||
// Commands with parameters. TODO: Should support both space and equals, like --config=foo.ini and --config foo.ini
|
||||
} else if (startsWith(argv[i], gpuBackendStr)) {
|
||||
const std::string_view restOfOption = argv[i] + gpuBackendStr.size();
|
||||
// Force software rendering off, as picking gles implies HW acceleration.
|
||||
// We could add more options for software such as "software-gles",
|
||||
// "software-vulkan" and "software-d3d11", or something similar.
|
||||
// For now, software rendering force-activates OpenGL.
|
||||
if (restOfOption == "directx11" || restOfOption == "d3d11") {
|
||||
gpuBackend = GPUBackend::DIRECT3D11;
|
||||
softwareRendering = false;
|
||||
} else if (restOfOption == "gles") {
|
||||
gpuBackend = GPUBackend::OPENGL;
|
||||
softwareRendering = false;
|
||||
} else if (restOfOption == "vulkan") {
|
||||
gpuBackend = GPUBackend::VULKAN;
|
||||
softwareRendering = false;
|
||||
} else if (restOfOption == "software") {
|
||||
gpuBackend = GPUBackend::OPENGL;
|
||||
softwareRendering = true;
|
||||
}
|
||||
} else if (startsWith(argv[i], configOption)) {
|
||||
configFilename = std::string(argv[i] + configOption.size());
|
||||
} else if (startsWith(argv[i], controlsOption)) {
|
||||
controlsConfigFilename = std::string(argv[i] + controlsOption.size());
|
||||
} else {
|
||||
// Report unknown argument later once this is complete.
|
||||
}
|
||||
|
||||
// To the next argument.
|
||||
i++;
|
||||
}
|
||||
return CommandLineParseResult::Continue;
|
||||
}
|
||||
|
||||
void CommandLineOptions::ApplyToConfig() const {
|
||||
if (fullscreen.has_value()) {
|
||||
g_Config.bFullScreen = fullscreen.value();
|
||||
g_Config.DoNotSaveSetting(&g_Config.bFullScreen);
|
||||
}
|
||||
if (gpuBackend.has_value()) {
|
||||
g_Config.iGPUBackend = (int)gpuBackend.value();
|
||||
g_Config.DoNotSaveSetting(&g_Config.iGPUBackend);
|
||||
}
|
||||
if (softwareRendering.has_value()) {
|
||||
g_Config.bSoftwareRendering = softwareRendering.value();
|
||||
g_Config.DoNotSaveSetting(&g_Config.bSoftwareRendering);
|
||||
}
|
||||
if (enableLogging.has_value()) {
|
||||
g_Config.bEnableLogging = enableLogging.value();
|
||||
g_Config.DoNotSaveSetting(&g_Config.bEnableLogging);
|
||||
}
|
||||
if (optionS) {
|
||||
g_Config.bAutoRun = false;
|
||||
g_Config.bSaveSettings = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include "Core/ConfigValues.h"
|
||||
|
||||
enum class CommandLineParseResult {
|
||||
Continue,
|
||||
Exit,
|
||||
Error,
|
||||
};
|
||||
|
||||
// We collect command line options in this struct, then we apply it to the config after it's been loaded.
|
||||
struct CommandLineOptions {
|
||||
std::optional<bool> fullscreen;
|
||||
std::optional<GPUBackend> gpuBackend;
|
||||
std::optional<bool> softwareRendering;
|
||||
std::optional<bool> enableLogging;
|
||||
|
||||
std::optional<std::string> bootFilename;
|
||||
|
||||
#ifndef _DEBUG
|
||||
bool showLogWindow = false;
|
||||
#else
|
||||
bool showLogWindow = true;
|
||||
#endif
|
||||
bool debugLogLevel = false;
|
||||
std::string configFilename = "";
|
||||
std::string controlsConfigFilename = "";
|
||||
|
||||
bool optionS = true; // a legacy option
|
||||
|
||||
// If returns CommandLineParseResult::Exit or ::Error, the program should exit immediately (with an error return code if Error).
|
||||
CommandLineParseResult Parse(int argc, const char *argv[]);
|
||||
void ApplyToConfig() const;
|
||||
};
|
||||
+4
-2
@@ -1254,11 +1254,13 @@ void Config::Reload() {
|
||||
// really think of any other legit uses).
|
||||
void Config::UpdateIniLocation(const char *iniFileName, const char *controllerIniFilename) {
|
||||
const bool useIniFilename = iniFileName != nullptr && strlen(iniFileName) > 0;
|
||||
const bool useControllerIniFilename = controllerIniFilename != nullptr && strlen(controllerIniFilename) > 0;
|
||||
|
||||
const char *ppssppIniFilename = IsVREnabled() ? "ppssppvr.ini" : "ppsspp.ini";
|
||||
const char *controlsIniFilename = IsVREnabled() ? "controlsvr.ini" : "controls.ini";
|
||||
|
||||
bool exists;
|
||||
iniFilename_ = FindConfigFile(searchPath_, useIniFilename ? iniFileName : ppssppIniFilename, &exists);
|
||||
const bool useControllerIniFilename = controllerIniFilename != nullptr && strlen(controllerIniFilename) > 0;
|
||||
const char *controlsIniFilename = IsVREnabled() ? "controlsvr.ini" : "controls.ini";
|
||||
controllerIniFilename_ = FindConfigFile(searchPath_, useControllerIniFilename ? controllerIniFilename : controlsIniFilename, &exists);
|
||||
}
|
||||
|
||||
|
||||
@@ -437,6 +437,7 @@
|
||||
<ClCompile Include="..\ext\udis86\syn-intel.c" />
|
||||
<ClCompile Include="..\ext\udis86\syn.c" />
|
||||
<ClCompile Include="..\ext\udis86\udis86.c" />
|
||||
<ClCompile Include="CmdLine.cpp" />
|
||||
<ClCompile Include="ConfigSettings.cpp" />
|
||||
<ClCompile Include="ControlMapper.cpp" />
|
||||
<ClCompile Include="AVIDump.cpp" />
|
||||
@@ -971,6 +972,7 @@
|
||||
<ClInclude Include="..\ext\udis86\types.h" />
|
||||
<ClInclude Include="..\ext\udis86\udint.h" />
|
||||
<ClInclude Include="..\ext\udis86\udis86.h" />
|
||||
<ClInclude Include="CmdLine.h" />
|
||||
<ClInclude Include="ConfigSettings.h" />
|
||||
<ClInclude Include="ControlMapper.h" />
|
||||
<ClInclude Include="AVIDump.h" />
|
||||
|
||||
@@ -1390,6 +1390,9 @@
|
||||
<ClCompile Include="Util\VideoPlayer.cpp">
|
||||
<Filter>Util</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CmdLine.cpp">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ELF\ElfReader.h">
|
||||
@@ -2250,6 +2253,9 @@
|
||||
<ClInclude Include="Util\VideoPlayer.h">
|
||||
<Filter>Util</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CmdLine.h">
|
||||
<Filter>Core</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\LICENSE.TXT" />
|
||||
|
||||
+12
-6
@@ -49,6 +49,7 @@
|
||||
#include "Common/TimeUtil.h"
|
||||
#include "Common/Log/LogManager.h"
|
||||
|
||||
#include "Core/CmdLine.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/ConfigValues.h"
|
||||
#include "Core/HW/Camera.h"
|
||||
@@ -857,11 +858,16 @@ int main(int argc, char *argv[])
|
||||
|
||||
g_logManager.EnableOutput(LogOutput::Stdio);
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "--version")) {
|
||||
printf("%s\n", PPSSPP_GIT_VERSION);
|
||||
return 0;
|
||||
}
|
||||
CommandLineOptions cmdLineOptions;
|
||||
CommandLineParseResult parseResult = cmdLineOptions.Parse(argc, (const char **)argv);
|
||||
switch (parseResult) {
|
||||
case CommandLineParseResult::Exit:
|
||||
return 0;
|
||||
case CommandLineParseResult::Error:
|
||||
return 1;
|
||||
default:
|
||||
// Continue with launch.
|
||||
break;
|
||||
}
|
||||
|
||||
// Ignore sigpipe.
|
||||
@@ -909,7 +915,7 @@ int main(int argc, char *argv[])
|
||||
savegame_dir += "/";
|
||||
external_dir += "/";
|
||||
|
||||
NativeInit(argc, (const char **)argv, savegame_dir.c_str(), external_dir.c_str(), nullptr);
|
||||
NativeInit(argc, (const char **)argv, cmdLineOptions, savegame_dir.c_str(), external_dir.c_str(), nullptr);
|
||||
|
||||
g_mainWindow = new MainWindow(nullptr, g_Config.bFullScreen);
|
||||
g_mainWindow->show();
|
||||
|
||||
+14
-59
@@ -28,6 +28,7 @@ SDLJoystick *joystick = NULL;
|
||||
#include "Common/System/Request.h"
|
||||
#include "Common/System/NativeApp.h"
|
||||
#include "Common/Audio/AudioBackend.h"
|
||||
#include "Core/CmdLine.h"
|
||||
#include "ext/glslang/glslang/Public/ShaderLang.h"
|
||||
#include "Common/Data/Format/PNGLoad.h"
|
||||
#include "Common/Net/Resolve.h"
|
||||
@@ -1382,70 +1383,24 @@ void UpdateSDLCursor() {
|
||||
#endif
|
||||
}
|
||||
|
||||
static int printUsage(const char *progname)
|
||||
{
|
||||
// NOTE: by convention, --help outputs to stdout,
|
||||
// not to stderr, since it is intended output in this
|
||||
// case (usage printed under different circumstances,
|
||||
// say in response to error during parsing commandline,
|
||||
// may go to stderr).
|
||||
FILE *dst = stdout;
|
||||
|
||||
// NOTE: wording largely taken from
|
||||
// https://www.ppsspp.org/docs/reference/command-line/
|
||||
fprintf(dst, "PPSSPP - a PSP emulator (SDL build)\n");
|
||||
fprintf(dst, "Usage: %s [options] [FILE]\n\n", progname);
|
||||
fprintf(dst, "Launches FILE (e.g. ISO image) if present.\n");
|
||||
fprintf(dst, "Options (some of these are specific to SDL backend):\n");
|
||||
fprintf(dst, " -h, --help show this message and exit\n");
|
||||
fprintf(dst, " --version show version information and exit\n");
|
||||
|
||||
fprintf(dst, " -d set the log level to debug\n");
|
||||
fprintf(dst, " -v set the log level to verbose\n");
|
||||
fprintf(dst, " --loglevel=INTEGER set the log level to specified value\n");
|
||||
fprintf(dst, " --log=FILE output log to FILE\n");
|
||||
fprintf(dst, " --state=FILE load state from FILE\n");
|
||||
|
||||
fprintf(dst, " -i use the interpreter\n");
|
||||
fprintf(dst, " -r use IR interpreter\n");
|
||||
fprintf(dst, " -j use JIT\n");
|
||||
fprintf(dst, " -J use IR JIT\n");
|
||||
|
||||
fprintf(dst, " --fullscreen force full screen mode, ignoring saved configuration\n");
|
||||
fprintf(dst, " --windowed force windowed mode, ignoring saved configuration\n");
|
||||
fprintf(dst, " --xres PIXELS set X resolution\n");
|
||||
fprintf(dst, " --yres PIXELS set Y resolution\n");
|
||||
fprintf(dst, " --dpi FACTOR set DPI\n");
|
||||
fprintf(dst, " --scale FACTOR set scale\n");
|
||||
fprintf(dst, " --ipad set resolution to 1024x768\n");
|
||||
fprintf(dst, " --portrait portrait mode\n");
|
||||
fprintf(dst, " --graphics=BACKEND use a different gpu backend\n");
|
||||
fprintf(dst, " options: gles, software, etc. (also opengl3.1, etc.)\n");
|
||||
|
||||
fprintf(dst, " --pause-menu-exit change \"Exit to menu\" in pause menu to \"Exit\"\n");
|
||||
fprintf(dst, " --escape-exit escape key exits the application\n");
|
||||
fprintf(dst, " --gamesettings go directly to settings\n");
|
||||
fprintf(dst, " --touchscreentest go directly to the touchscreentest screen\n");
|
||||
fprintf(dst, " --appendconfig=FILE merge config FILE into the current configuration\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#undef main
|
||||
#endif
|
||||
int main(int argc, char *argv[]) {
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h"))
|
||||
return printUsage(argv[0]);
|
||||
else if (!strcmp(argv[i], "--version")) {
|
||||
printf("%s\n", PPSSPP_GIT_VERSION);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
TimeInit();
|
||||
|
||||
CommandLineOptions cmdLineOptions;
|
||||
CommandLineParseResult parseResult = cmdLineOptions.Parse(argc, (const char **)argv);
|
||||
switch (parseResult) {
|
||||
case CommandLineParseResult::Exit:
|
||||
return 0;
|
||||
case CommandLineParseResult::Error:
|
||||
return 1;
|
||||
default:
|
||||
// Continue with launch.
|
||||
break;
|
||||
}
|
||||
|
||||
g_logManager.EnableOutput(LogOutput::Stdio);
|
||||
|
||||
#ifdef HAVE_LIBNX
|
||||
@@ -1681,7 +1636,7 @@ int main(int argc, char *argv[]) {
|
||||
#else
|
||||
const char *external_dir = "/tmp";
|
||||
#endif
|
||||
NativeInit(remain_argc, (const char **)remain_argv, path, external_dir, nullptr);
|
||||
NativeInit(remain_argc, (const char **)remain_argv, cmdLineOptions, path, external_dir, nullptr);
|
||||
|
||||
// Use the setting from the config when initing the window.
|
||||
if (g_Config.bFullScreen) {
|
||||
|
||||
+14
-5
@@ -90,6 +90,7 @@
|
||||
#include "Common/Thread/ThreadManager.h"
|
||||
#include "Common/Audio/AudioBackend.h"
|
||||
#include "Common/UI/PopupScreens.h"
|
||||
#include "Core/CmdLine.h"
|
||||
#include "Core/ControlMapper.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/ConfigValues.h"
|
||||
@@ -393,7 +394,7 @@ static void ClearFailedGPUBackends() {
|
||||
File::Delete(failedBackendsFile);
|
||||
}
|
||||
|
||||
void NativeInit(int argc, const char *argv[], const char *savegame_dir, const char *external_dir, const char *cache_dir) {
|
||||
void NativeInit(int argc, const char *argv[], const CommandLineOptions &cmdLineOptions, const char *savegame_dir, const char *external_dir, const char *cache_dir) {
|
||||
net::Init(); // This needs to happen before we load the config. So on Windows we also run it in Main. It's fine to call multiple times.
|
||||
|
||||
g_Config.Init();
|
||||
@@ -437,6 +438,10 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
|
||||
g_VFS.Register("", new DirectoryReader(Path("/usr/local/share/games/ppsspp/assets")));
|
||||
g_VFS.Register("", new DirectoryReader(Path("/usr/share/ppsspp/assets")));
|
||||
g_VFS.Register("", new DirectoryReader(Path("/usr/share/games/ppsspp/assets")));
|
||||
#elif defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
|
||||
const Path &exePath = File::GetExeDirectory();
|
||||
g_VFS.Register("", new DirectoryReader(exePath / "assets"));
|
||||
g_VFS.Register("", new DirectoryReader(exePath));
|
||||
#endif
|
||||
|
||||
#if PPSSPP_PLATFORM(SWITCH)
|
||||
@@ -578,6 +583,9 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
|
||||
System_Notify(SystemNotification::CONFIG_LOADED);
|
||||
#endif
|
||||
|
||||
// Apply parsed command line options to config.
|
||||
cmdLineOptions.ApplyToConfig();
|
||||
|
||||
const char *fileToLog = nullptr;
|
||||
Path stateToLoad;
|
||||
|
||||
@@ -619,19 +627,19 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
|
||||
break;
|
||||
case 'j':
|
||||
g_Config.iCpuCore = (int)CPUCore::JIT;
|
||||
g_Config.bSaveSettings = false;
|
||||
g_Config.DoNotSaveSetting(&g_Config.iCpuCore);
|
||||
break;
|
||||
case 'i':
|
||||
g_Config.iCpuCore = (int)CPUCore::INTERPRETER;
|
||||
g_Config.bSaveSettings = false;
|
||||
g_Config.DoNotSaveSetting(&g_Config.iCpuCore);
|
||||
break;
|
||||
case 'r':
|
||||
g_Config.iCpuCore = (int)CPUCore::IR_INTERPRETER;
|
||||
g_Config.bSaveSettings = false;
|
||||
g_Config.DoNotSaveSetting(&g_Config.iCpuCore);
|
||||
break;
|
||||
case 'J':
|
||||
g_Config.iCpuCore = (int)CPUCore::JIT_IR;
|
||||
g_Config.bSaveSettings = false;
|
||||
g_Config.DoNotSaveSetting(&g_Config.iCpuCore);
|
||||
break;
|
||||
case '-':
|
||||
if (!strncmp(argv[i], "--loglevel=", strlen("--loglevel=")) && strlen(argv[i]) > strlen("--loglevel="))
|
||||
@@ -649,6 +657,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
|
||||
g_Config.bFullScreen = true;
|
||||
}
|
||||
if (!strncmp(argv[i], "--root=", strlen("--root=")) && strlen(argv[i]) > strlen("--root=")) {
|
||||
g_Config.DoNotSaveSetting(&g_Config.mountRoot);
|
||||
g_Config.mountRoot = Path(argv[i] + strlen("--root="));
|
||||
}
|
||||
if (!strcmp(argv[i], "--windowed")) {
|
||||
|
||||
+7
-2
@@ -15,6 +15,7 @@
|
||||
#include "Common/System/NativeApp.h"
|
||||
#include "Common/System/System.h"
|
||||
#include "Common/Log/LogManager.h"
|
||||
#include "Core/CmdLine.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/Core.h"
|
||||
@@ -86,7 +87,8 @@ void App::InitialPPSSPP() {
|
||||
|
||||
// Since we don't have any async operation in `NativeInit`
|
||||
// it's better to call it here
|
||||
const char* argv[2] = { "fake", nullptr };
|
||||
int argc = 1;
|
||||
const char* argv[2] = { "ppsspp", nullptr };
|
||||
std::string cacheFolder = ConvertWStringToUTF8(
|
||||
std::wstring(winrt::Windows::Storage::ApplicationData::Current().TemporaryFolder().Path())
|
||||
);
|
||||
@@ -94,7 +96,10 @@ void App::InitialPPSSPP() {
|
||||
// since launch parameters usually handled by `OnActivated`
|
||||
// and `OnActivated` will be invoked later, even after `PPSSPP_UWPMain(..)`
|
||||
// so we are handling launch cases using `LaunchItem`
|
||||
NativeInit(1, argv, "", "", cacheFolder.c_str());
|
||||
|
||||
CommandLineOptions cmdLineOptions;
|
||||
cmdLineOptions.Parse(argc, argv);
|
||||
NativeInit(1, argv, cmdLineOptions, "", "", cacheFolder.c_str());
|
||||
|
||||
// Override backend, `DIRECT3D11` is the only way for UWP apps
|
||||
g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D11;
|
||||
|
||||
@@ -86,6 +86,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\Core\AVIDump.h" />
|
||||
<ClInclude Include="..\..\Core\CmdLine.h" />
|
||||
<ClInclude Include="..\..\Core\Compatibility.h" />
|
||||
<ClInclude Include="..\..\Core\Config.h" />
|
||||
<ClInclude Include="..\..\Core\ConfigSettings.h" />
|
||||
@@ -359,6 +360,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\Core\AVIDump.cpp" />
|
||||
<ClCompile Include="..\..\Core\CmdLine.cpp" />
|
||||
<ClCompile Include="..\..\Core\Compatibility.cpp" />
|
||||
<ClCompile Include="..\..\Core\Config.cpp" />
|
||||
<ClCompile Include="..\..\Core\ConfigSettings.cpp" />
|
||||
|
||||
@@ -411,6 +411,7 @@
|
||||
<ClCompile Include="..\..\Core\Util\PathUtil.cpp" />
|
||||
<ClCompile Include="..\..\Core\SaveStateRewind.cpp" />
|
||||
<ClCompile Include="..\..\Core\Util\VideoPlayer.cpp" />
|
||||
<ClCompile Include="..\..\Core\CmdLine.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\Core\AVIDump.h" />
|
||||
@@ -684,6 +685,7 @@
|
||||
<ClInclude Include="..\..\Core\Util\PathUtil.h" />
|
||||
<ClInclude Include="..\..\Core\SaveStateRewind.h" />
|
||||
<ClInclude Include="..\..\Core\Util\VideoPlayer.h" />
|
||||
<ClInclude Include="..\..\Core\CmdLine.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\ext\gason\LICENSE" />
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "Core/System.h"
|
||||
#include "Core/Loaders.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/CmdLine.h"
|
||||
|
||||
#include "Windows/InputDevice.h"
|
||||
#include "Windows/XinputDevice.h"
|
||||
|
||||
+6
-15
@@ -43,24 +43,16 @@ static std::thread mainThread;
|
||||
static std::string g_error_message;
|
||||
static bool g_inLoop;
|
||||
|
||||
static const char** g_argv;
|
||||
static int g_argc;
|
||||
|
||||
extern std::vector<std::wstring> GetWideCmdLine();
|
||||
|
||||
class GraphicsContext;
|
||||
static GraphicsContext *g_graphicsContext;
|
||||
|
||||
void MainThreadFunc(int argc, const char *argv[]);
|
||||
void MainThreadFunc();
|
||||
|
||||
void MainThread_Start(int argc, const char *argv[]) {
|
||||
// This is just to survive WM_USER_RESTART_EMUTHREAD.
|
||||
if (g_argc == 0) {
|
||||
g_argc = argc;
|
||||
g_argv = argv;
|
||||
}
|
||||
void MainThread_Start() {
|
||||
mainThread = std::thread([]() {
|
||||
MainThreadFunc(g_argc, g_argv);
|
||||
MainThreadFunc();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -153,7 +145,7 @@ bool CreateGraphicsBackend(std::string *error_message, GraphicsContext **ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
void MainThreadFunc(int argc, const char *argv[]) {
|
||||
void MainThreadFunc() {
|
||||
const bool useEmuThread = g_Config.iGPUBackend == (int)GPUBackend::OPENGL;
|
||||
|
||||
SetCurrentThreadName(useEmuThread ? "RenderThread" : "EmuThread");
|
||||
@@ -161,7 +153,6 @@ void MainThreadFunc(int argc, const char *argv[]) {
|
||||
System_SetWindowTitle("");
|
||||
|
||||
const bool performingRestart = NativeIsRestarting();
|
||||
NativeInit(argc, argv, "", "", nullptr);
|
||||
|
||||
if (g_Config.sFailedGPUBackends.find("ALL") != std::string::npos) {
|
||||
Reporting::ReportMessage("Graphics init error: %s", "ALL");
|
||||
@@ -249,6 +240,7 @@ void MainThreadFunc(int argc, const char *argv[]) {
|
||||
graphicsContext->ThreadStart();
|
||||
|
||||
if (useEmuThread) {
|
||||
// Again, this thread becomes the render thread.
|
||||
while (true) {
|
||||
if (equals_any(g_emuThreadState, EmuThreadState::QUIT_REQUESTED, EmuThreadState::STOPPED)) {
|
||||
break;
|
||||
@@ -259,6 +251,7 @@ void MainThreadFunc(int argc, const char *argv[]) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Same contents as EmuThread.
|
||||
while (GetUIState() != UISTATE_EXIT) { // && GetUIState() != UISTATE_EXCEPTION
|
||||
// We're here again, so the game quit. Restart Run() which controls the UI.
|
||||
// This way they can load a new game.
|
||||
@@ -297,7 +290,5 @@ void MainThreadFunc(int argc, const char *argv[]) {
|
||||
delete g_graphicsContext;
|
||||
g_graphicsContext = nullptr;
|
||||
|
||||
NativeShutdown();
|
||||
|
||||
PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_UPDATE_UI, 0, 0);
|
||||
}
|
||||
+1
-3
@@ -17,8 +17,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
void MainThread_Start(int argc, const char *argv[]);
|
||||
void MainThread_Start();
|
||||
void MainThread_Stop();
|
||||
bool MainThread_Ready();
|
||||
|
||||
void MainThreadFunc(int argc, const char *argv[]);
|
||||
+6
-10
@@ -507,7 +507,7 @@ namespace MainWindow {
|
||||
|
||||
WINDOWPLACEMENT placement{sizeof(WINDOWPLACEMENT)};
|
||||
if ((g_Config.iWindowX == -1 && g_Config.iWindowY == -1) || g_Config.iWindowWidth < 20 || g_Config.iWindowHeight < 20) {
|
||||
RECT rc = DetermineDefaultWindowRectangle();
|
||||
const RECT rc = DetermineDefaultWindowRectangle();
|
||||
// Should be a first boot, or just bad parameters. Reset.
|
||||
g_Config.iWindowSizeState = (int)WindowSizeState::Normal;
|
||||
g_Config.iWindowX = rc.left;
|
||||
@@ -1097,15 +1097,6 @@ namespace MainWindow {
|
||||
UpdateWindowTitle();
|
||||
break;
|
||||
|
||||
case WM_USER_RESTART_EMUTHREAD:
|
||||
NativeSetRestarting();
|
||||
g_InputManager.StopPolling();
|
||||
MainThread_Stop();
|
||||
UpdateUIState(UISTATE_MENU);
|
||||
MainThread_Start(0, nullptr);
|
||||
g_InputManager.BeginPolling();
|
||||
break;
|
||||
|
||||
case WM_USER_SWITCHUMD_UPDATED:
|
||||
UpdateSwitchUMD();
|
||||
break;
|
||||
@@ -1114,6 +1105,11 @@ namespace MainWindow {
|
||||
DestroyWindow(hWnd);
|
||||
break;
|
||||
|
||||
case WM_USER_SHOW_DISASM:
|
||||
CreateDisasmWindow();
|
||||
disasmWindow->Show(g_Config.bShowDebuggerOnLoad, false);
|
||||
break;
|
||||
|
||||
case WM_INITMENUPOPUP:
|
||||
// Called when a menu or submenu is about to be opened.
|
||||
UpdateMenus((HMENU)wParam);
|
||||
|
||||
@@ -17,10 +17,10 @@ namespace MainWindow
|
||||
WM_USER_UPDATE_UI = WM_USER + 101,
|
||||
WM_USER_WINDOW_TITLE_CHANGED = WM_USER + 103,
|
||||
WM_USER_APPLY_FULLSCREEN = WM_USER + 105,
|
||||
WM_USER_RESTART_EMUTHREAD = WM_USER + 106,
|
||||
WM_USER_SWITCHUMD_UPDATED = WM_USER + 107,
|
||||
WM_USER_RUN_CALLBACK = WM_USER + 108,
|
||||
WM_USER_DESTROY = WM_USER + 109,
|
||||
WM_USER_SHOW_DISASM = WM_USER + 110,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
||||
@@ -446,12 +446,8 @@ namespace MainWindow {
|
||||
}
|
||||
|
||||
static void RestartApp() {
|
||||
if (System_GetPropertyBool(SYSPROP_DEBUGGER_PRESENT)) {
|
||||
PostMessage(MainWindow::GetHWND(), WM_USER_RESTART_EMUTHREAD, 0, 0);
|
||||
} else {
|
||||
g_Config.bRestartRequired = true;
|
||||
PostMessage(MainWindow::GetHWND(), WM_USER_DESTROY, 0, 0);
|
||||
}
|
||||
g_Config.bRestartRequired = true;
|
||||
PostMessage(MainWindow::GetHWND(), WM_USER_DESTROY, 0, 0);
|
||||
}
|
||||
|
||||
void MainWindowMenu_Process(HWND hWnd, WPARAM wParam) {
|
||||
|
||||
+84
-160
@@ -22,7 +22,7 @@
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
|
||||
#include <optional>
|
||||
#include <mmsystem.h>
|
||||
#include <shellapi.h>
|
||||
#include <Wbemidl.h>
|
||||
@@ -50,6 +50,7 @@
|
||||
|
||||
#include "Core/Config.h"
|
||||
#include "Core/ConfigValues.h"
|
||||
#include "Core/CmdLine.h"
|
||||
#include "Core/SaveState.h"
|
||||
#include "Core/Instance.h"
|
||||
#include "Core/HLE/Plugins.h"
|
||||
@@ -104,6 +105,7 @@ extern "C" {
|
||||
extern "C" {
|
||||
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
||||
}
|
||||
|
||||
#if PPSSPP_API(ANY_GL)
|
||||
CGEDebugger* geDebuggerWindow = nullptr;
|
||||
#endif
|
||||
@@ -112,19 +114,19 @@ CDisasm *disasmWindow = nullptr;
|
||||
CMemoryDlg *memoryWindow = nullptr;
|
||||
CVFPUDlg *vfpudlg = nullptr;
|
||||
|
||||
static std::string langRegion;
|
||||
static std::string osName;
|
||||
static std::string osVersion;
|
||||
static std::string gpuDriverVersion;
|
||||
static std::string computerName;
|
||||
static std::string g_langRegion;
|
||||
static std::string g_osName;
|
||||
static std::string g_osVersionString;
|
||||
static std::string g_gpuDriverVersion;
|
||||
static std::string g_computerName;
|
||||
|
||||
static std::string restartArgs;
|
||||
static std::string g_restartArgs;
|
||||
|
||||
int g_activeWindow = 0;
|
||||
int g_lastNumInstances = 0;
|
||||
|
||||
float mouseDeltaX_ = 0;
|
||||
float mouseDeltaY_ = 0;
|
||||
float g_mouseDeltaX = 0;
|
||||
float g_mouseDeltaY = 0;
|
||||
|
||||
static double g_lastActivity = 0.0;
|
||||
static double g_lastKeepAwake = 0.0;
|
||||
@@ -161,26 +163,27 @@ void System_Vibrate(int length_ms) {
|
||||
}
|
||||
|
||||
static void AddDebugRestartArgs() {
|
||||
if (g_logManager.GetConsoleListener()->IsOpen())
|
||||
restartArgs += " -l";
|
||||
if (g_logManager.GetConsoleListener()->IsOpen()) {
|
||||
g_restartArgs += " -l";
|
||||
}
|
||||
}
|
||||
|
||||
static void PollControllers() {
|
||||
// Disabled by default, needs a workaround to map to psp keys.
|
||||
if (g_Config.bMouseControl) {
|
||||
NativeMouseDelta(mouseDeltaX_, mouseDeltaY_);
|
||||
NativeMouseDelta(g_mouseDeltaX, g_mouseDeltaY);
|
||||
}
|
||||
|
||||
mouseDeltaX_ *= g_Config.fMouseSmoothing;
|
||||
mouseDeltaY_ *= g_Config.fMouseSmoothing;
|
||||
g_mouseDeltaX *= g_Config.fMouseSmoothing;
|
||||
g_mouseDeltaY *= g_Config.fMouseSmoothing;
|
||||
|
||||
HLEPlugins::PluginDataAxis[JOYSTICK_AXIS_MOUSE_REL_X] = mouseDeltaX_;
|
||||
HLEPlugins::PluginDataAxis[JOYSTICK_AXIS_MOUSE_REL_Y] = mouseDeltaY_;
|
||||
HLEPlugins::PluginDataAxis[JOYSTICK_AXIS_MOUSE_REL_X] = g_mouseDeltaX;
|
||||
HLEPlugins::PluginDataAxis[JOYSTICK_AXIS_MOUSE_REL_Y] = g_mouseDeltaY;
|
||||
}
|
||||
|
||||
// Adapted mostly as-is from http://www.gamedev.net/topic/495075-how-to-retrieve-info-about-videocard/?view=findpost&p=4229170
|
||||
// so credit goes to that post's author, and in turn, the author of the site mentioned in that post (which seems to be down?).
|
||||
std::string GetVideoCardDriverVersion() {
|
||||
static std::string GetVideoCardDriverVersion() {
|
||||
std::string retvalue = "";
|
||||
|
||||
HRESULT hr;
|
||||
@@ -240,11 +243,11 @@ std::string System_GetProperty(SystemProperty prop) {
|
||||
static bool hasCheckedGPUDriverVersion = false;
|
||||
switch (prop) {
|
||||
case SYSPROP_NAME:
|
||||
return osName;
|
||||
return g_osName;
|
||||
case SYSPROP_SYSTEMBUILD:
|
||||
return osVersion;
|
||||
return g_osVersionString;
|
||||
case SYSPROP_LANGREGION:
|
||||
return langRegion;
|
||||
return g_langRegion;
|
||||
case SYSPROP_CLIPBOARD_TEXT:
|
||||
{
|
||||
std::string retval;
|
||||
@@ -263,24 +266,24 @@ std::string System_GetProperty(SystemProperty prop) {
|
||||
case SYSPROP_GPUDRIVER_VERSION:
|
||||
if (!hasCheckedGPUDriverVersion) {
|
||||
hasCheckedGPUDriverVersion = true;
|
||||
gpuDriverVersion = GetVideoCardDriverVersion();
|
||||
g_gpuDriverVersion = GetVideoCardDriverVersion();
|
||||
}
|
||||
return gpuDriverVersion;
|
||||
return g_gpuDriverVersion;
|
||||
case SYSPROP_BUILD_VERSION:
|
||||
return PPSSPP_GIT_VERSION;
|
||||
case SYSPROP_USER_DOCUMENTS_DIR:
|
||||
return Path(W32Util::UserDocumentsPath()).ToString(); // this'll reverse the slashes.
|
||||
case SYSPROP_COMPUTER_NAME:
|
||||
if (computerName.empty()) {
|
||||
if (g_computerName.empty()) {
|
||||
wchar_t nameBuf[MAX_COMPUTERNAME_LENGTH + 1];
|
||||
DWORD size = ARRAY_SIZE(nameBuf);
|
||||
if (GetComputerNameW(nameBuf, &size)) {
|
||||
computerName = ConvertWStringToUTF8(std::wstring(nameBuf, size));
|
||||
g_computerName = ConvertWStringToUTF8(std::wstring(nameBuf, size));
|
||||
} else {
|
||||
computerName = "(N/A)";
|
||||
g_computerName = "(N/A)";
|
||||
}
|
||||
}
|
||||
return computerName;
|
||||
return g_computerName;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
@@ -654,15 +657,12 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
|
||||
return true;
|
||||
case SystemRequestType::RESTART_APP:
|
||||
{
|
||||
restartArgs = param1;
|
||||
if (!restartArgs.empty())
|
||||
g_restartArgs = param1;
|
||||
if (!g_restartArgs.empty()) {
|
||||
AddDebugRestartArgs();
|
||||
if (false) { // This doesn't really work anymore: System_GetPropertyBool(SYSPROP_DEBUGGER_PRESENT)) {
|
||||
PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_RESTART_EMUTHREAD, 0, 0);
|
||||
} else {
|
||||
g_Config.bRestartRequired = true;
|
||||
PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_DESTROY, 0, 0);
|
||||
}
|
||||
g_Config.bRestartRequired = true;
|
||||
PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_DESTROY, 0, 0);
|
||||
return true;
|
||||
}
|
||||
case SystemRequestType::COPY_TO_CLIPBOARD:
|
||||
@@ -908,10 +908,10 @@ static bool DetectVulkanInExternalProcess() {
|
||||
std::vector<std::wstring> GetWideCmdLine() {
|
||||
wchar_t **wargv;
|
||||
int wargc = -1;
|
||||
if (!restartArgs.empty()) {
|
||||
std::wstring wargs = ConvertUTF8ToWString("PPSSPP " + restartArgs);
|
||||
if (!g_restartArgs.empty()) {
|
||||
std::wstring wargs = ConvertUTF8ToWString("PPSSPP " + g_restartArgs);
|
||||
wargv = CommandLineToArgvW(wargs.c_str(), &wargc);
|
||||
restartArgs.clear();
|
||||
g_restartArgs.clear();
|
||||
} else {
|
||||
wargv = CommandLineToArgvW(GetCommandLineW(), &wargc);
|
||||
}
|
||||
@@ -1016,13 +1016,12 @@ static void WinMainCleanup() {
|
||||
if (g_Config.bUpdatedInstanceCounter) {
|
||||
ShutdownInstanceCounter();
|
||||
}
|
||||
W32Util::ExitAndRestart(!restartArgs.empty(), restartArgs);
|
||||
W32Util::ExitAndRestart(!g_restartArgs.empty(), g_restartArgs);
|
||||
}
|
||||
}
|
||||
|
||||
int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow) {
|
||||
const std::vector<std::wstring> wideArgs = GetWideCmdLine();
|
||||
|
||||
// Check for the Vulkan workaround before any serious init.
|
||||
for (size_t i = 1; i < wideArgs.size(); ++i) {
|
||||
if (wideArgs[i][0] == L'-') {
|
||||
@@ -1039,51 +1038,47 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
||||
}
|
||||
}
|
||||
|
||||
// We convert command line arguments to UTF-8.
|
||||
std::vector<std::string> argsUTF8;
|
||||
for (const auto &string : wideArgs) {
|
||||
argsUTF8.push_back(ConvertWStringToUTF8(string));
|
||||
}
|
||||
std::vector<const char *> args;
|
||||
for (const auto &string : argsUTF8) {
|
||||
args.push_back(string.c_str());
|
||||
}
|
||||
|
||||
// args provide argc and argv.
|
||||
CommandLineOptions cmdLineOptions;
|
||||
CommandLineParseResult parseResult = cmdLineOptions.Parse((int)args.size(), args.data());
|
||||
switch (parseResult) {
|
||||
case CommandLineParseResult::Exit:
|
||||
return 0;
|
||||
case CommandLineParseResult::Error:
|
||||
return 1;
|
||||
default:
|
||||
// Continue with launch.
|
||||
break;
|
||||
}
|
||||
|
||||
if (iCmdShow == SW_MAXIMIZE) {
|
||||
// Consider this to mean --fullscreen. I guess frontends might use it?
|
||||
cmdLineOptions.fullscreen = true;
|
||||
}
|
||||
|
||||
SetCurrentThreadName("Main");
|
||||
|
||||
TimeInit();
|
||||
WinMainInit();
|
||||
|
||||
#ifndef _DEBUG
|
||||
bool showLog = false;
|
||||
#else
|
||||
bool showLog = true;
|
||||
#endif
|
||||
|
||||
const Path &exePath = File::GetExeDirectory();
|
||||
g_VFS.Register("", new DirectoryReader(exePath / "assets"));
|
||||
g_VFS.Register("", new DirectoryReader(exePath));
|
||||
|
||||
langRegion = GetDefaultLangRegion();
|
||||
osName = GetWindowsVersion() + " " + GetWindowsSystemArchitecture();
|
||||
g_langRegion = GetDefaultLangRegion();
|
||||
g_osName = GetWindowsVersion() + " " + GetWindowsSystemArchitecture();
|
||||
|
||||
// OS Build
|
||||
uint32_t outMajor = 0, outMinor = 0, outBuild = 0;
|
||||
if (GetVersionFromKernel32(outMajor, outMinor, outBuild)) {
|
||||
// Builds with (service pack) don't show OS Build for now
|
||||
osVersion = std::to_string(outMajor) + "." + std::to_string(outMinor) + "." + std::to_string(outBuild);
|
||||
}
|
||||
|
||||
std::string configFilename = "";
|
||||
const std::wstring configOption = L"--config=";
|
||||
|
||||
std::string controlsConfigFilename = "";
|
||||
const std::wstring controlsOption = L"--controlconfig=";
|
||||
|
||||
for (size_t i = 1; i < wideArgs.size(); ++i) {
|
||||
if (wideArgs[i][0] == L'\0')
|
||||
continue;
|
||||
if (wideArgs[i][0] == L'-') {
|
||||
if (wideArgs[i].find(configOption) != std::wstring::npos && wideArgs[i].size() > configOption.size()) {
|
||||
const std::wstring tempWide = wideArgs[i].substr(configOption.size());
|
||||
configFilename = ConvertWStringToUTF8(tempWide);
|
||||
}
|
||||
|
||||
if (wideArgs[i].find(controlsOption) != std::wstring::npos && wideArgs[i].size() > controlsOption.size()) {
|
||||
const std::wstring tempWide = wideArgs[i].substr(controlsOption.size());
|
||||
controlsConfigFilename = ConvertWStringToUTF8(tempWide);
|
||||
}
|
||||
}
|
||||
g_osVersionString = std::to_string(outMajor) + "." + std::to_string(outMinor) + "." + std::to_string(outBuild);
|
||||
}
|
||||
|
||||
// This will be overridden by the actual config. But we do want to log during startup.
|
||||
@@ -1099,70 +1094,9 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
||||
// Load config up here, because those changes below would be overwritten
|
||||
// if it's not loaded here first.
|
||||
g_Config.SetSearchPath(GetSysDirectory(DIRECTORY_SYSTEM));
|
||||
g_Config.Load(configFilename.c_str(), controlsConfigFilename.c_str());
|
||||
g_Config.Load(cmdLineOptions.configFilename.c_str(), cmdLineOptions.controlsConfigFilename.c_str());
|
||||
System_Notify(SystemNotification::CONFIG_LOADED);
|
||||
|
||||
bool debugLogLevel = false;
|
||||
|
||||
const std::wstring gpuBackend = L"--graphics=";
|
||||
|
||||
// The rest is handled in NativeInit().
|
||||
for (size_t i = 1; i < wideArgs.size(); ++i) {
|
||||
if (wideArgs[i][0] == L'\0')
|
||||
continue;
|
||||
|
||||
if (wideArgs[i][0] == L'-') {
|
||||
switch (wideArgs[i][1]) {
|
||||
case L'l':
|
||||
showLog = true;
|
||||
g_Config.bEnableLogging = true;
|
||||
break;
|
||||
case L's':
|
||||
g_Config.bAutoRun = false;
|
||||
g_Config.bSaveSettings = false;
|
||||
break;
|
||||
case L'd':
|
||||
debugLogLevel = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// NOTE: We need to parse --fullscreen early, before we create the window.
|
||||
if (!wcscmp(wideArgs[i].c_str(), L"--fullscreen")) {
|
||||
g_Config.bFullScreen = true;
|
||||
g_Config.DoNotSaveSetting(&g_Config.bFullScreen);
|
||||
} else if (!wcscmp(wideArgs[i].c_str(), L"--windowed")) {
|
||||
g_Config.bFullScreen = false;
|
||||
g_Config.DoNotSaveSetting(&g_Config.bFullScreen);
|
||||
}
|
||||
|
||||
if (wideArgs[i].find(gpuBackend) != std::wstring::npos && wideArgs[i].size() > gpuBackend.size()) {
|
||||
const std::wstring restOfOption = wideArgs[i].substr(gpuBackend.size());
|
||||
|
||||
// Force software rendering off, as picking gles implies HW acceleration.
|
||||
// We could add more options for software such as "software-gles",
|
||||
// "software-vulkan" and "software-d3d11", or something similar.
|
||||
// For now, software rendering force-activates OpenGL.
|
||||
if (restOfOption == L"directx11") {
|
||||
g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D11;
|
||||
g_Config.bSoftwareRendering = false;
|
||||
} else if (restOfOption == L"gles") {
|
||||
g_Config.iGPUBackend = (int)GPUBackend::OPENGL;
|
||||
g_Config.bSoftwareRendering = false;
|
||||
} else if (restOfOption == L"vulkan") {
|
||||
g_Config.iGPUBackend = (int)GPUBackend::VULKAN;
|
||||
g_Config.bSoftwareRendering = false;
|
||||
} else if (restOfOption == L"software") {
|
||||
g_Config.iGPUBackend = (int)GPUBackend::OPENGL;
|
||||
g_Config.bSoftwareRendering = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
g_Config.bEnableLogging = true;
|
||||
#endif
|
||||
|
||||
#ifndef _DEBUG
|
||||
// See #11719 - too many Vulkan drivers crash on basic init.
|
||||
if (g_Config.IsBackendEnabled(GPUBackend::VULKAN)) {
|
||||
@@ -1170,18 +1104,14 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
||||
}
|
||||
#endif
|
||||
|
||||
if (iCmdShow == SW_MAXIMIZE) {
|
||||
// Consider this to mean --fullscreen.
|
||||
g_Config.bFullScreen = true;
|
||||
g_Config.DoNotSaveSetting(&g_Config.bFullScreen);
|
||||
}
|
||||
NativeInit((int)args.size(), args.data(), cmdLineOptions, "", "", nullptr);
|
||||
|
||||
// Consider at least the following cases before changing this code:
|
||||
// - By default in Release, the console should be hidden by default even if logging is enabled.
|
||||
// - By default in Debug, the console should be shown by default.
|
||||
// - The -l switch is expected to show the log console, REGARDLESS of config settings.
|
||||
// - It should be possible to log to a file without showing the console.
|
||||
g_logManager.GetConsoleListener()->Init(showLog, 150, 120);
|
||||
g_logManager.GetConsoleListener()->Init(cmdLineOptions.showLogWindow, 150, 120);
|
||||
|
||||
// Move the console into position.
|
||||
const HWND console = GetConsoleWindow();
|
||||
@@ -1189,11 +1119,11 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
||||
SetWindowPos(console, NULL, g_Config.iConsoleWindowX, g_Config.iConsoleWindowY, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
|
||||
}
|
||||
|
||||
if (debugLogLevel) {
|
||||
if (cmdLineOptions.debugLogLevel) {
|
||||
g_logManager.SetAllLogLevels(LogLevel::LDEBUG);
|
||||
}
|
||||
|
||||
// Media foundation
|
||||
// Windows Media Foundation - used for camera and (currently, but not later) microphone support (we'll move to WASAPI for audio input later)
|
||||
if (!RegisterCMPTMFApis()) {
|
||||
ERROR_LOG(Log::System, "Failed to load Media Foundation functions");
|
||||
// Let's unregister again.
|
||||
@@ -1215,8 +1145,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
||||
#endif
|
||||
|
||||
if (g_Config.bShowDebuggerOnLoad) {
|
||||
MainWindow::CreateDisasmWindow();
|
||||
disasmWindow->Show(g_Config.bShowDebuggerOnLoad, false);
|
||||
PostMessage(hwndMain, MainWindow::WM_USER_SHOW_DISASM, 0, 0);
|
||||
}
|
||||
|
||||
const bool minimized = iCmdShow == SW_MINIMIZE || iCmdShow == SW_SHOWMINIMIZED || iCmdShow == SW_SHOWMINNOACTIVE;
|
||||
@@ -1225,20 +1154,10 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
||||
}
|
||||
|
||||
// Emu thread (and render thread, if any) is always running!
|
||||
// Only OpenGL uses an externally managed render thread (due to GL's single-threaded context design). Vulkan
|
||||
// manages its own render thread.
|
||||
|
||||
// We convert command line arguments to UTF-8.
|
||||
std::vector<std::string> argsUTF8;
|
||||
for (const auto &string : wideArgs) {
|
||||
argsUTF8.push_back(ConvertWStringToUTF8(string));
|
||||
}
|
||||
std::vector<const char *> args;
|
||||
for (const auto &string : argsUTF8) {
|
||||
args.push_back(string.c_str());
|
||||
}
|
||||
|
||||
MainThread_Start((int)args.size(), args.data());
|
||||
// OpenGL uses an externally managed render thread (due to GL's single-threaded context design).
|
||||
// Vulkan manages its own render thread. Our D3D backend doesn't have a render thread.
|
||||
// The Emu thread calls NativeInit() and NativeMain() etc.
|
||||
MainThread_Start();
|
||||
|
||||
g_InputManager.BeginPolling();
|
||||
|
||||
@@ -1252,8 +1171,9 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
||||
MainWindow::UpdateCommands();
|
||||
|
||||
//hack to make it possible to get to main window from floating windows with Esc
|
||||
if (msg.hwnd != hwndMain && msg.wParam == VK_ESCAPE)
|
||||
if (msg.hwnd != hwndMain && msg.wParam == VK_ESCAPE) {
|
||||
BringWindowToTop(hwndMain);
|
||||
}
|
||||
}
|
||||
|
||||
// Translate accelerators and dialog messages...
|
||||
@@ -1284,6 +1204,10 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
||||
}
|
||||
}
|
||||
|
||||
// When we've exited the loop, MainThread_Stop has already been called.
|
||||
// So it's safe to call NativeShutdown.
|
||||
NativeShutdown();
|
||||
|
||||
g_VFS.Clear();
|
||||
|
||||
// g_InputManager.StopPolling() is called in WM_DESTROY
|
||||
|
||||
@@ -608,6 +608,7 @@ EXEC_AND_LIB_FILES := \
|
||||
$(SRC)/Core/ControlMapper.cpp \
|
||||
$(SRC)/Core/Core.cpp \
|
||||
$(SRC)/Core/Compatibility.cpp \
|
||||
$(SRC)/Core/CmdLine.cpp \
|
||||
$(SRC)/Core/Config.cpp \
|
||||
$(SRC)/Core/ConfigSettings.cpp \
|
||||
$(SRC)/Core/CoreTiming.cpp \
|
||||
|
||||
@@ -95,10 +95,10 @@ struct JNIEnv {};
|
||||
#include "AndroidVulkanContext.h"
|
||||
#include "AndroidJavaGLContext.h"
|
||||
|
||||
#include "Core/CmdLine.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/ConfigValues.h"
|
||||
#include "Core/Loaders.h"
|
||||
#include "Core/FileLoaders/LocalFileLoader.h"
|
||||
#include "Core/KeyMap.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/HLE/sceUsbCam.h"
|
||||
@@ -826,10 +826,24 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init
|
||||
}
|
||||
}
|
||||
|
||||
CommandLineOptions cmdLineOptions;
|
||||
CommandLineParseResult parseResult = cmdLineOptions.Parse((int)args.size(), args.data());
|
||||
switch (parseResult) {
|
||||
case CommandLineParseResult::Exit:
|
||||
EARLY_LOG("Command line parse said to exit - mobile, so ignoring.");
|
||||
break;
|
||||
case CommandLineParseResult::Error:
|
||||
EARLY_LOG("Command line parse reported error - mobile, so ignoring.");
|
||||
break;
|
||||
default:
|
||||
// Continue with launch.
|
||||
break;
|
||||
}
|
||||
|
||||
EARLY_LOG("Calling NativeInit with user_data_path %s, externalStorageDir %s, cacheDir %s", user_data_path.c_str(), externalStorageDir.c_str(), cacheDir.c_str());
|
||||
|
||||
// TODO: We should be able to do the Vulkan init in parallel with NativeInit.
|
||||
NativeInit((int)args.size(), &args[0], user_data_path.c_str(), externalStorageDir.c_str(), cacheDir.c_str());
|
||||
NativeInit((int)args.size(), &args[0], cmdLineOptions, user_data_path.c_str(), externalStorageDir.c_str(), cacheDir.c_str());
|
||||
|
||||
bFirstResume = true;
|
||||
|
||||
|
||||
@@ -415,7 +415,7 @@ int main(int argc, const char* argv[])
|
||||
// There used to be a separate "null" rendering core - just use software.
|
||||
else if (!strcasecmp(gpuName, "software") || !strcasecmp(gpuName, "null"))
|
||||
gpuCore = GPUCORE_SOFTWARE;
|
||||
else if (!strcasecmp(gpuName, "directx11"))
|
||||
else if (!strcasecmp(gpuName, "directx11") || !strcasecmp(gpuName, "d3d11"))
|
||||
gpuCore = GPUCORE_DIRECTX11;
|
||||
else if (!strcasecmp(gpuName, "vulkan"))
|
||||
gpuCore = GPUCORE_VULKAN;
|
||||
|
||||
+16
-1
@@ -14,6 +14,7 @@
|
||||
#import "Common/Log.h"
|
||||
#import "IAPManager.h"
|
||||
#include "Core/Util/PathUtil.h"
|
||||
#include "Core/CmdLine.h"
|
||||
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#include <string>
|
||||
@@ -149,9 +150,23 @@ static NSString *ExtractGameInfoScheme(NSURL *url) {
|
||||
NSLog(@"SceneDelegate: startup path passed to argv: %s", gStartupArgStorage.c_str());
|
||||
}
|
||||
|
||||
CommandLineOptions cmdLineOptions;
|
||||
CommandLineParseResult parseResult = cmdLineOptions.Parse(argc, (const char **)argv);
|
||||
switch (parseResult) {
|
||||
case CommandLineParseResult::Exit:
|
||||
INFO_LOG(Log::System, "Command line parse said to exit - mobile, so ignoring.");
|
||||
break;
|
||||
case CommandLineParseResult::Error:
|
||||
INFO_LOG(Log::System, "Command line parse reported error - mobile, so ignoring.");
|
||||
break;
|
||||
default:
|
||||
// Continue with launch.
|
||||
break;
|
||||
}
|
||||
|
||||
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
|
||||
NSString *bundlePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/assets/"];
|
||||
NativeInit(argc, (const char**)argv, documentsPath.UTF8String, bundlePath.UTF8String, NULL);
|
||||
NativeInit(argc, (const char**)argv, cmdLineOptions, documentsPath.UTF8String, bundlePath.UTF8String, NULL);
|
||||
|
||||
// If we were cold-started by a library export request, serve it now that
|
||||
// the config (and recent games list) has been loaded by NativeInit.
|
||||
|
||||
Reference in new issue
Block a user