mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-08-23 10:40:36 -05:00
add in extra command line flags for testing, usage
fixes #1958 this adds in a series of extra command line flags that should make it easier to run games directly from the command line. these flags include: - a way to mount extra host directories (for one off runs where you want to write to a temporary directory) - a way to forward OSReport/etc. to stderr. - a way to specify the arguments to a game when launching it directly through the command line.
This commit is contained in:
@@ -685,6 +685,22 @@ namespace CafeSystem
|
||||
fsc_unmount("/cemuBossStorage/", FSC_PRIORITY_BASE);
|
||||
}
|
||||
|
||||
void MountExtras()
|
||||
{
|
||||
for (const auto& [host_path, emulatedPath] : LaunchSettings::ExtraMounts())
|
||||
{
|
||||
FSCDeviceHostFS_Mount(boost::nowide::narrow(emulatedPath), _pathToUtf8(host_path), FSC_PRIORITY_BASE);
|
||||
}
|
||||
}
|
||||
|
||||
void UnmountExtras()
|
||||
{
|
||||
for (const auto& [_, emulatedPath] : LaunchSettings::ExtraMounts())
|
||||
{
|
||||
fsc_unmount(boost::nowide::narrow(emulatedPath), FSC_PRIORITY_BASE);
|
||||
}
|
||||
}
|
||||
|
||||
PREPARE_STATUS_CODE LoadAndMountForegroundTitle(TitleId titleId)
|
||||
{
|
||||
cemuLog_log(LogType::Force, "Mounting title {:016x}", (uint64)titleId);
|
||||
@@ -838,6 +854,7 @@ namespace CafeSystem
|
||||
if (r != PREPARE_STATUS_CODE::SUCCESS)
|
||||
return r;
|
||||
InitVirtualMlcStorage();
|
||||
MountExtras();
|
||||
return PREPARE_STATUS_CODE::SUCCESS;
|
||||
}
|
||||
|
||||
@@ -881,6 +898,7 @@ namespace CafeSystem
|
||||
// load executable
|
||||
PrepareExecutable();
|
||||
InitVirtualMlcStorage();
|
||||
MountExtras();
|
||||
return PREPARE_STATUS_CODE::SUCCESS;
|
||||
}
|
||||
|
||||
@@ -961,7 +979,12 @@ namespace CafeSystem
|
||||
std::string GetForegroundTitleArgStr()
|
||||
{
|
||||
if (sLaunchModeIsStandalone)
|
||||
{
|
||||
auto optional_arguments = LaunchSettings::StandaloneTitleArguments();
|
||||
if (optional_arguments.has_value())
|
||||
return *optional_arguments;
|
||||
return "";
|
||||
}
|
||||
auto& update = sGameInfo_ForegroundTitle.GetUpdate();
|
||||
if (update.IsValid())
|
||||
return update.GetArgStr();
|
||||
@@ -1059,6 +1082,7 @@ namespace CafeSystem
|
||||
PPCRecompiler_Shutdown();
|
||||
GraphicPack2::Reset();
|
||||
UnmountCurrentTitle();
|
||||
UnmountExtras();
|
||||
MlcStorageUnmountAllTitles();
|
||||
UnmountBaseDirectories();
|
||||
DestroyMemorySpace();
|
||||
|
||||
@@ -4,8 +4,11 @@
|
||||
#include "Cafe/OS/libs/coreinit/coreinit_OSScreen.h"
|
||||
#include "Cafe/CafeSystem.h"
|
||||
#include "Cafe/Filesystem/fsc.h"
|
||||
#include "config/LaunchSettings.h"
|
||||
#include <pugixml.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace coreinit
|
||||
{
|
||||
sint32 ppc_vcprintf_pad(char* strOut, sint32 maxLength, sint32 padLength, char padChar)
|
||||
@@ -544,15 +547,18 @@ namespace coreinit
|
||||
}
|
||||
|
||||
std::mutex sCafeConsoleMutex;
|
||||
bool s_forwardConsoleLogs;
|
||||
|
||||
void WriteCafeConsole(CafeLogType cafeLogType, const char* msg, sint32 len)
|
||||
{
|
||||
std::unique_lock _l(sCafeConsoleMutex);
|
||||
CafeLogBuffer& logBuffer = getLogBuffer(cafeLogType);
|
||||
// once a line is full or \n is written it will be posted to log
|
||||
auto flushLine = [](CafeLogBuffer& cafeLogBuffer, std::string_view cafeLogName) -> void
|
||||
auto flushLine = [](CafeLogBuffer& cafeLogBuffer, std::string_view cafeLogName, bool forwardToConsole) -> void
|
||||
{
|
||||
cemuLog_log(LogType::CoreinitLogging, "[{0}] {1}", cafeLogName, std::basic_string_view(cafeLogBuffer.lineBuffer.data(), cafeLogBuffer.lineLength));
|
||||
if (forwardToConsole)
|
||||
std::cerr << fmt::format("{0}\n", std::basic_string_view(cafeLogBuffer.lineBuffer.data(), cafeLogBuffer.lineLength));
|
||||
cafeLogBuffer.lineLength = 0;
|
||||
};
|
||||
|
||||
@@ -566,13 +572,13 @@ namespace coreinit
|
||||
if (c == '\n')
|
||||
{
|
||||
// flush line immediately
|
||||
flushLine(logBuffer, getLogBufferName(cafeLogType));
|
||||
flushLine(logBuffer, getLogBufferName(cafeLogType), s_forwardConsoleLogs);
|
||||
continue;
|
||||
}
|
||||
logBuffer.lineBuffer[logBuffer.lineLength] = c;
|
||||
logBuffer.lineLength++;
|
||||
if (logBuffer.lineLength >= logBuffer.lineBuffer.size())
|
||||
flushLine(logBuffer, getLogBufferName(cafeLogType));
|
||||
flushLine(logBuffer, getLogBufferName(cafeLogType), s_forwardConsoleLogs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -846,6 +852,7 @@ namespace coreinit
|
||||
{
|
||||
s_currentTitleId = CafeSystem::GetForegroundTitleId();
|
||||
s_sdkVersion = CafeSystem::GetForegroundTitleSDKVersion();
|
||||
s_forwardConsoleLogs = LaunchSettings::ForwardConsoleLogging();
|
||||
s_transitionToBackground = false;
|
||||
s_transitionToForeground = false;
|
||||
|
||||
|
||||
@@ -20,5 +20,6 @@ target_include_directories(CemuConfig PUBLIC "../")
|
||||
target_link_libraries(CemuConfig PRIVATE
|
||||
CemuCommon
|
||||
CemuGui
|
||||
Boost::nowide
|
||||
Boost::program_options
|
||||
)
|
||||
|
||||
@@ -63,7 +63,7 @@ bool LaunchSettings::HandleCommandline(const std::vector<std::wstring>& args)
|
||||
#endif
|
||||
|
||||
("game,g", po::wvalue<std::wstring>(), "Path of game to launch")
|
||||
("title-id,t", po::value<std::string>(), "Title ID of the title to be launched (overridden by --game)")
|
||||
("title-id,t", po::value<std::string>(), "Title ID of the title to be launched (overridden by --game)")
|
||||
("mlc,m", po::wvalue<std::wstring>(), "Custom mlc folder location")
|
||||
|
||||
("fullscreen,f", po::value<bool>()->implicit_value(true), "Launch games in fullscreen mode")
|
||||
@@ -71,6 +71,10 @@ bool LaunchSettings::HandleCommandline(const std::vector<std::wstring>& args)
|
||||
|
||||
("account,a", po::value<std::string>(), "Persistent id of account")
|
||||
|
||||
("extra-mounts", po::wvalue<std::vector<std::wstring>>()->composing(), "A series of mounts in the form of: (path on host:path within emulated system, e.g. `/tmp:/vol/temporary/`)")
|
||||
("forward-console-logging", "Forward OSReport, OSConsoleWrite, etc. to stderr.")
|
||||
("standalone-title-arguments", po::value<std::string>(), "Custom arguments to pass as arguments to a standalone RPX that is launched.")
|
||||
|
||||
("force-interpreter", po::value<bool>()->implicit_value(true), "Force interpreter CPU emulation, disables recompiler. Useful for debugging purposes where you want to get accurate memory accesses and stack traces.")
|
||||
("force-multicore-interpreter", po::value<bool>()->implicit_value(true), "Force multi-core interpreter CPU emulation, disables recompiler. Only useful for getting stack traces, but slightly faster than the single-core interpreter mode.")
|
||||
("enable-gdbstub", po::value<bool>()->implicit_value(true), "Enable GDB stub to debug executables inside Cemu using an external debugger");
|
||||
@@ -189,6 +193,30 @@ bool LaunchSettings::HandleCommandline(const std::vector<std::wstring>& args)
|
||||
if (vm.count("enable-gdbstub"))
|
||||
s_enable_gdbstub = vm["enable-gdbstub"].as<bool>();
|
||||
|
||||
if (vm.count("forward-console-logging"))
|
||||
{
|
||||
requireConsole();
|
||||
s_forward_console_logging = true;
|
||||
}
|
||||
|
||||
if (vm.count("standalone-title-arguments"))
|
||||
s_standalone_title_arguments = vm["standalone-title-arguments"].as<std::string>();
|
||||
|
||||
if (vm.count("extra-mounts"))
|
||||
{
|
||||
for (const auto& argument : vm["extra-mounts"].as<std::vector<std::wstring>>())
|
||||
{
|
||||
size_t colon_location = argument.find(L':');
|
||||
if (colon_location == std::wstring::npos)
|
||||
{
|
||||
std::cerr << "Argument for a mount expects to be in the format: `path on host:path in emulated system`, was not: `" << boost::nowide::narrow(argument) << "`\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
s_extra_mounts[argument.substr(0, colon_location)] = argument.substr(colon_location + 1);
|
||||
}
|
||||
}
|
||||
|
||||
std::wstring extract_path, log_path;
|
||||
std::string output_path;
|
||||
if (vm.count("extract"))
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
class LaunchSettings
|
||||
{
|
||||
@@ -16,7 +17,7 @@ public:
|
||||
static bool HandleCommandline(const std::vector<std::wstring>& args);
|
||||
|
||||
static std::optional<fs::path> GetLoadFile() { return s_load_game_file; }
|
||||
static std::optional<uint64> GetLoadTitleID() {return s_load_title_id;}
|
||||
static std::optional<uint64> GetLoadTitleID() {return s_load_title_id;}
|
||||
static std::optional<fs::path> GetMLCPath() { return s_mlc_path; }
|
||||
|
||||
static std::optional<bool> RenderUpsideDownEnabled() { return s_render_upside_down; }
|
||||
@@ -24,6 +25,10 @@ public:
|
||||
|
||||
static bool Verbose() { return s_verbose; }
|
||||
|
||||
static bool ForwardConsoleLogging() { return s_forward_console_logging; }
|
||||
static std::optional<std::string> StandaloneTitleArguments() { return s_standalone_title_arguments; }
|
||||
static std::unordered_map<fs::path, std::wstring>& ExtraMounts() { return s_extra_mounts; }
|
||||
|
||||
static bool GDBStubEnabled() { return s_enable_gdbstub; }
|
||||
static bool NSightModeEnabled() { return s_nsight_mode; }
|
||||
|
||||
@@ -37,14 +42,18 @@ public:
|
||||
|
||||
private:
|
||||
inline static std::optional<fs::path> s_load_game_file{};
|
||||
inline static std::optional<uint64> s_load_title_id{};
|
||||
inline static std::optional<uint64> s_load_title_id{};
|
||||
inline static std::optional<fs::path> s_mlc_path{};
|
||||
|
||||
inline static std::optional<bool> s_render_upside_down{};
|
||||
inline static std::optional<bool> s_fullscreen{};
|
||||
|
||||
inline static bool s_verbose = false;
|
||||
|
||||
|
||||
inline static bool s_forward_console_logging = false;
|
||||
inline static std::optional<std::string> s_standalone_title_arguments{};
|
||||
inline static std::unordered_map<fs::path, std::wstring> s_extra_mounts{};
|
||||
|
||||
inline static bool s_enable_gdbstub = false;
|
||||
inline static bool s_nsight_mode = false;
|
||||
|
||||
@@ -59,5 +68,3 @@ private:
|
||||
|
||||
static bool ExtractorTool(std::wstring_view wud_path, std::string_view output_path, std::wstring_view log_path);
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user