Skip to content

Commit 4535deb

Browse files
authored
Add command line parameters to make Cemu more useful for running tests (cemu-project#1959)
1 parent 344c7a6 commit 4535deb

4 files changed

Lines changed: 91 additions & 22 deletions

File tree

src/Cafe/CafeSystem.cpp

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,22 @@ namespace CafeSystem
685685
fsc_unmount("/cemuBossStorage/", FSC_PRIORITY_BASE);
686686
}
687687

688+
void MountExtras()
689+
{
690+
for (const auto& [host_path, emulatedPath] : LaunchSettings::CosMounts())
691+
{
692+
FSCDeviceHostFS_Mount(boost::nowide::narrow(emulatedPath), _pathToUtf8(host_path), FSC_PRIORITY_BASE);
693+
}
694+
}
695+
696+
void UnmountExtras()
697+
{
698+
for (const auto& [_, emulatedPath] : LaunchSettings::CosMounts())
699+
{
700+
fsc_unmount(boost::nowide::narrow(emulatedPath), FSC_PRIORITY_BASE);
701+
}
702+
}
703+
688704
PREPARE_STATUS_CODE LoadAndMountForegroundTitle(TitleId titleId)
689705
{
690706
cemuLog_log(LogType::Force, "Mounting title {:016x}", (uint64)titleId);
@@ -838,6 +854,7 @@ namespace CafeSystem
838854
if (r != PREPARE_STATUS_CODE::SUCCESS)
839855
return r;
840856
InitVirtualMlcStorage();
857+
MountExtras();
841858
return PREPARE_STATUS_CODE::SUCCESS;
842859
}
843860

@@ -881,6 +898,7 @@ namespace CafeSystem
881898
// load executable
882899
PrepareExecutable();
883900
InitVirtualMlcStorage();
901+
MountExtras();
884902
return PREPARE_STATUS_CODE::SUCCESS;
885903
}
886904

@@ -960,6 +978,9 @@ namespace CafeSystem
960978

961979
std::string GetForegroundTitleArgStr()
962980
{
981+
auto optional_arguments = LaunchSettings::CosArgstr();
982+
if (optional_arguments.has_value())
983+
return *optional_arguments;
963984
if (sLaunchModeIsStandalone)
964985
return "";
965986
auto& update = sGameInfo_ForegroundTitle.GetUpdate();
@@ -1044,24 +1065,26 @@ namespace CafeSystem
10441065
{
10451066
if(!sSystemRunning)
10461067
return;
1047-
coreinit::OSSchedulerEnd();
1048-
Latte_Stop();
1049-
// reset Cafe OS userspace modules
1050-
snd_core::reset();
1051-
coreinit::OSAlarm_Shutdown();
1052-
GX2::_GX2DriverReset();
1053-
nn::save::ResetToDefaultState();
1054-
coreinit::__OSDeleteAllActivePPCThreads();
1055-
RPLLoader_UnloadAll();
1068+
coreinit::OSSchedulerEnd();
1069+
Latte_Stop();
1070+
// reset Cafe OS userspace modules
1071+
snd_core::reset();
1072+
coreinit::OSAlarm_Shutdown();
1073+
GX2::_GX2DriverReset();
1074+
nn::save::ResetToDefaultState();
1075+
coreinit::__OSDeleteAllActivePPCThreads();
1076+
RPLLoader_UnloadAll();
10561077
for(auto it = s_iosuModules.rbegin(); it != s_iosuModules.rend(); ++it)
10571078
(*it)->TitleStop();
1058-
// reset Cemu subsystems
1059-
PPCRecompiler_Shutdown();
1060-
GraphicPack2::Reset();
1061-
UnmountCurrentTitle();
1062-
MlcStorageUnmountAllTitles();
1063-
UnmountBaseDirectories();
1064-
DestroyMemorySpace();
1079+
// reset Cemu subsystems
1080+
PPCRecompiler_Shutdown();
1081+
GraphicPack2::Reset();
1082+
UnmountCurrentTitle();
1083+
UnmountExtras();
1084+
MlcStorageUnmountAllTitles();
1085+
UnmountBaseDirectories();
1086+
DestroyMemorySpace();
1087+
LaunchSettings::ClearCosArgstr();
10651088
sSystemRunning = false;
10661089
}
10671090

src/Cafe/OS/libs/coreinit/coreinit_Misc.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "Cafe/OS/libs/coreinit/coreinit_OSScreen.h"
55
#include "Cafe/CafeSystem.h"
66
#include "Cafe/Filesystem/fsc.h"
7+
#include "config/LaunchSettings.h"
78
#include <pugixml.hpp>
89

910
namespace coreinit
@@ -544,6 +545,7 @@ namespace coreinit
544545
}
545546

546547
std::mutex sCafeConsoleMutex;
548+
bool s_forwardConsoleLogs;
547549

548550
void WriteCafeConsole(CafeLogType cafeLogType, const char* msg, sint32 len)
549551
{
@@ -556,6 +558,13 @@ namespace coreinit
556558
cafeLogBuffer.lineLength = 0;
557559
};
558560

561+
if (s_forwardConsoleLogs) {
562+
if (cafeLogType == CafeLogType::OSCONSOLE) {
563+
fwrite(msg, 1, len, stdout);
564+
} else {
565+
fwrite(msg, 1, len, stderr);
566+
}
567+
}
559568
while (len)
560569
{
561570
char c = *msg;
@@ -846,6 +855,7 @@ namespace coreinit
846855
{
847856
s_currentTitleId = CafeSystem::GetForegroundTitleId();
848857
s_sdkVersion = CafeSystem::GetForegroundTitleSDKVersion();
858+
s_forwardConsoleLogs = LaunchSettings::ForwardConsoleLogging();
849859
s_transitionToBackground = false;
850860
s_transitionToForeground = false;
851861

src/config/LaunchSettings.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,18 @@ bool LaunchSettings::HandleCommandline(const std::vector<std::wstring>& args)
6363
#endif
6464

6565
("game,g", po::wvalue<std::wstring>(), "Path of game to launch")
66-
("title-id,t", po::value<std::string>(), "Title ID of the title to be launched (overridden by --game)")
66+
("title-id,t", po::value<std::string>(), "Title ID of the title to be launched (overridden by --game)")
6767
("mlc,m", po::wvalue<std::wstring>(), "Custom mlc folder location")
6868

6969
("fullscreen,f", po::value<bool>()->implicit_value(true), "Launch games in fullscreen mode")
7070
("ud,u", po::value<bool>()->implicit_value(true), "Render output upside-down")
7171

7272
("account,a", po::value<std::string>(), "Persistent id of account")
7373

74+
("cos-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/`)")
75+
("forward-console-logging", "Forward OSReport, OSConsoleWrite, etc. to stdout/stderr.")
76+
("cos-argstr", po::value<std::string>(), "A custom argstr used to override to the arguments to the first RPX that is launched, will be unset after the first launch.")
77+
7478
("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.")
7579
("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.")
7680
("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)
189193
if (vm.count("enable-gdbstub"))
190194
s_enable_gdbstub = vm["enable-gdbstub"].as<bool>();
191195

196+
if (vm.count("forward-console-logging"))
197+
{
198+
requireConsole();
199+
s_forward_console_logging = true;
200+
}
201+
202+
if (vm.count("cos-argstr"))
203+
s_cos_argstr = vm["cos-argstr"].as<std::string>();
204+
205+
if (vm.count("cos-mounts"))
206+
{
207+
for (const auto& argument : vm["cos-mounts"].as<std::vector<std::wstring>>())
208+
{
209+
size_t colon_location = argument.find(L':');
210+
if (colon_location == std::wstring::npos)
211+
{
212+
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";
213+
continue;
214+
}
215+
216+
s_cos_mounts[argument.substr(0, colon_location)] = argument.substr(colon_location + 1);
217+
}
218+
}
219+
192220
std::wstring extract_path, log_path;
193221
std::string output_path;
194222
if (vm.count("extract"))

src/config/LaunchSettings.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <optional>
44
#include <string>
5+
#include <unordered_map>
56

67
class LaunchSettings
78
{
@@ -16,14 +17,19 @@ class LaunchSettings
1617
static bool HandleCommandline(const std::vector<std::wstring>& args);
1718

1819
static std::optional<fs::path> GetLoadFile() { return s_load_game_file; }
19-
static std::optional<uint64> GetLoadTitleID() {return s_load_title_id;}
20+
static std::optional<uint64> GetLoadTitleID() {return s_load_title_id;}
2021
static std::optional<fs::path> GetMLCPath() { return s_mlc_path; }
2122

2223
static std::optional<bool> RenderUpsideDownEnabled() { return s_render_upside_down; }
2324
static std::optional<bool> FullscreenEnabled() { return s_fullscreen; }
2425

2526
static bool Verbose() { return s_verbose; }
2627

28+
static bool ForwardConsoleLogging() { return s_forward_console_logging; }
29+
static std::optional<std::string> CosArgstr() { return s_cos_argstr; }
30+
static void ClearCosArgstr() { s_cos_argstr.reset(); }
31+
static std::unordered_map<fs::path, std::wstring>& CosMounts() { return s_cos_mounts; }
32+
2733
static bool GDBStubEnabled() { return s_enable_gdbstub; }
2834
static bool NSightModeEnabled() { return s_nsight_mode; }
2935

@@ -37,14 +43,18 @@ class LaunchSettings
3743

3844
private:
3945
inline static std::optional<fs::path> s_load_game_file{};
40-
inline static std::optional<uint64> s_load_title_id{};
46+
inline static std::optional<uint64> s_load_title_id{};
4147
inline static std::optional<fs::path> s_mlc_path{};
4248

4349
inline static std::optional<bool> s_render_upside_down{};
4450
inline static std::optional<bool> s_fullscreen{};
4551

4652
inline static bool s_verbose = false;
47-
53+
54+
inline static bool s_forward_console_logging = false;
55+
inline static std::optional<std::string> s_cos_argstr{};
56+
inline static std::unordered_map<fs::path, std::wstring> s_cos_mounts{};
57+
4858
inline static bool s_enable_gdbstub = false;
4959
inline static bool s_nsight_mode = false;
5060

@@ -59,5 +69,3 @@ class LaunchSettings
5969

6070
static bool ExtractorTool(std::wstring_view wud_path, std::string_view output_path, std::wstring_view log_path);
6171
};
62-
63-

0 commit comments

Comments
 (0)