suyu_cmd: allow launching of applets by supplying FrontendAppletParameters as an arg

Based off of a patch i saved before I nuked my local copy of the suyu repo from gitlab and replaced it with the one local-hosted
This commit is contained in:
RadsammyT 2024-03-21 23:52:32 -04:00 committed by RadsammyT
parent 42f3dd309e
commit 1ed34b1e47
3 changed files with 140 additions and 87 deletions

View file

@ -47,6 +47,75 @@ bool ShouldCreateGuestApplet(AppletId applet_id) {
return true;
}
std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
WindowSystem& window_system,
std::shared_ptr<Applet> caller_applet,
AppletId applet_id,
LibraryAppletMode mode) {
const auto program_id = static_cast<u64>(Service::AM::AppletIdToProgramId(applet_id));
if (program_id == 0) {
// Unknown applet
return {};
}
// TODO: enable other versions of applets
enum : u8 {
Firmware1400 = 14,
Firmware1500 = 15,
Firmware1600 = 16,
Firmware1700 = 17,
};
auto process = CreateProcess(system, program_id, Firmware1400, Firmware1700);
if (!process) {
// Couldn't initialize the guest process
return {};
}
const auto applet = std::make_shared<Applet>(system, std::move(process), false);
applet->program_id = program_id;
applet->applet_id = applet_id;
applet->type = AppletType::LibraryApplet;
applet->library_applet_mode = mode;
applet->window_visible = mode != LibraryAppletMode::AllForegroundInitiallyHidden;
auto broker = std::make_shared<AppletDataBroker>(system);
applet->caller_applet = caller_applet;
applet->caller_applet_broker = broker;
caller_applet->child_applets.push_back(applet);
window_system.TrackApplet(applet, false);
return std::make_shared<ILibraryAppletAccessor>(system, broker, applet);
}
std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& system,
WindowSystem& window_system,
std::shared_ptr<Applet> caller_applet,
AppletId applet_id,
LibraryAppletMode mode) {
const auto program_id = static_cast<u64>(Service::AM::AppletIdToProgramId(applet_id));
auto process = std::make_unique<Process>(system);
auto applet = std::make_shared<Applet>(system, std::move(process), false);
applet->program_id = program_id;
applet->applet_id = applet_id;
applet->type = AppletType::LibraryApplet;
applet->library_applet_mode = mode;
auto storage = std::make_shared<AppletDataBroker>(system);
applet->caller_applet = caller_applet;
applet->caller_applet_broker = storage;
applet->frontend = system.GetFrontendAppletHolder().GetApplet(applet, applet_id, mode);
caller_applet->child_applets.push_back(applet);
window_system.TrackApplet(applet, false);
return std::make_shared<ILibraryAppletAccessor>(system, storage, applet);
}
} // namespace
AppletProgramId AppletIdToProgramId(AppletId applet_id) {
switch (applet_id) {
case AppletId::OverlayDisplay:
@ -94,79 +163,10 @@ AppletProgramId AppletIdToProgramId(AppletId applet_id) {
}
}
std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
WindowSystem& window_system,
std::shared_ptr<Applet> caller_applet,
AppletId applet_id,
LibraryAppletMode mode) {
const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id));
if (program_id == 0) {
// Unknown applet
return {};
}
// TODO: enable other versions of applets
enum : u8 {
Firmware1400 = 14,
Firmware1500 = 15,
Firmware1600 = 16,
Firmware1700 = 17,
};
auto process = CreateProcess(system, program_id, Firmware1400, Firmware1700);
if (!process) {
// Couldn't initialize the guest process
return {};
}
const auto applet = std::make_shared<Applet>(system, std::move(process), false);
applet->program_id = program_id;
applet->applet_id = applet_id;
applet->type = AppletType::LibraryApplet;
applet->library_applet_mode = mode;
applet->window_visible = mode != LibraryAppletMode::AllForegroundInitiallyHidden;
auto broker = std::make_shared<AppletDataBroker>(system);
applet->caller_applet = caller_applet;
applet->caller_applet_broker = broker;
caller_applet->child_applets.push_back(applet);
window_system.TrackApplet(applet, false);
return std::make_shared<ILibraryAppletAccessor>(system, broker, applet);
}
std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& system,
WindowSystem& window_system,
std::shared_ptr<Applet> caller_applet,
AppletId applet_id,
LibraryAppletMode mode) {
const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id));
auto process = std::make_unique<Process>(system);
auto applet = std::make_shared<Applet>(system, std::move(process), false);
applet->program_id = program_id;
applet->applet_id = applet_id;
applet->type = AppletType::LibraryApplet;
applet->library_applet_mode = mode;
auto storage = std::make_shared<AppletDataBroker>(system);
applet->caller_applet = caller_applet;
applet->caller_applet_broker = storage;
applet->frontend = system.GetFrontendAppletHolder().GetApplet(applet, applet_id, mode);
caller_applet->child_applets.push_back(applet);
window_system.TrackApplet(applet, false);
return std::make_shared<ILibraryAppletAccessor>(system, storage, applet);
}
} // namespace
ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet,
WindowSystem& window_system)
: ServiceFramework{system_, "ILibraryAppletCreator"},
m_window_system{window_system}, m_applet{std::move(applet)} {
: ServiceFramework{system_, "ILibraryAppletCreator"}, m_window_system{window_system},
m_applet{std::move(applet)} {
static const FunctionInfo functions[] = {
{0, D<&ILibraryAppletCreator::CreateLibraryApplet>, "CreateLibraryApplet"},
{1, nullptr, "TerminateAllLibraryApplets"},

View file

@ -35,4 +35,6 @@ private:
const std::shared_ptr<Applet> m_applet;
};
AppletProgramId AppletIdToProgramId(AppletId applet_id);
} // namespace Service::AM

View file

@ -5,6 +5,7 @@
#include <iostream>
#include <memory>
#include <regex>
#include <sstream>
#include <string>
#include <thread>
@ -23,9 +24,12 @@
#include "core/core_timing.h"
#include "core/cpu_manager.h"
#include "core/crypto/key_manager.h"
#include "core/file_sys/content_archive.h"
#include "core/file_sys/nca_metadata.h"
#include "core/file_sys/registered_cache.h"
#include "core/file_sys/vfs/vfs_real.h"
#include "core/hle/service/am/applet_manager.h"
#include "core/hle/service/am/service/library_applet_creator.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/loader/loader.h"
#include "frontend_common/config.h"
@ -67,17 +71,23 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
#endif
static void PrintHelp(const char* argv0) {
std::cout << "Usage: " << argv0
<< " [options] <filename>\n"
"-c, --config Load the specified configuration file\n"
"-f, --fullscreen Start in fullscreen mode\n"
"-g, --game File path of the game to load\n"
"-h, --help Display this help and exit\n"
"-m, --multiplayer=nick:password@address:port"
" Nickname, password, address and port for multiplayer\n"
"-p, --program Pass following string as arguments to executable\n"
"-u, --user Select a specific user profile from 0 to 7\n"
"-v, --version Output version information and exit\n";
std::cout
<< "Usage: " << argv0
<< " [options] <filename>\n"
"-c, --config Load the specified configuration file\n"
"-f, --fullscreen Start in fullscreen mode\n"
"-g, --game File path of the game to load\n"
"-h, --help Display this help and exit\n"
"-m, --multiplayer=nick:password@address:port"
" Nickname, password, address and port for multiplayer\n"
"-p, --program Pass following string as arguments to executable\n"
"-u, --user Select a specific user profile from 0 to 7\n"
"-v, --version Output version information and exit\n"
"-l, "
"--applet-params="
"\"program_id,applet_id,applet_type,launch_type,prog_index,prev_prog_index\"\n"
" Numerical parameters for launching an applet. If applet_id\n"
" is 0, then the provided game will launch, if any.\n";
}
static void PrintVersion() {
@ -212,6 +222,7 @@ int main(int argc, char** argv) {
bool use_multiplayer = false;
bool fullscreen = false;
Service::AM::FrontendAppletParameters load_parameters{};
std::string nickname{};
std::string password{};
std::string address{};
@ -223,6 +234,7 @@ int main(int argc, char** argv) {
{"fullscreen", no_argument, 0, 'f'},
{"help", no_argument, 0, 'h'},
{"game", required_argument, 0, 'g'},
{"applet-params", required_argument, 0, 'l'},
{"multiplayer", required_argument, 0, 'm'},
{"program", optional_argument, 0, 'p'},
{"user", required_argument, 0, 'u'},
@ -232,7 +244,7 @@ int main(int argc, char** argv) {
};
while (optind < argc) {
int arg = getopt_long(argc, argv, "g:fhvp::c:u:", long_options, &option_index);
int arg = getopt_long(argc, argv, "g:fhvp::c:u:l:", long_options, &option_index);
if (arg != -1) {
switch (static_cast<char>(arg)) {
case 'c':
@ -250,6 +262,27 @@ int main(int argc, char** argv) {
filepath = str_arg;
break;
}
case 'l': {
std::string str_arg(optarg);
str_arg.append(",0"); // FALLBACK: if string is partially completed ("1234,3")
// this will set all those unset to 0. otherwise we get
// all 3s.
std::stringstream stream(str_arg);
std::string sub;
std::getline(stream, sub, ',');
load_parameters.program_id = std::stoull(sub);
std::getline(stream, sub, ',');
load_parameters.applet_id = static_cast<Service::AM::AppletId>(std::stoul(sub));
std::getline(stream, sub, ',');
load_parameters.applet_type = static_cast<Service::AM::AppletType>(std::stoi(sub));
std::getline(stream, sub, ',');
load_parameters.launch_type = static_cast<Service::AM::LaunchType>(std::stoi(sub));
std::getline(stream, sub, ',');
load_parameters.program_index = std::stoi(sub);
std::getline(stream, sub, ',');
load_parameters.previous_program_index = std::stoi(sub);
break;
}
case 'm': {
use_multiplayer = true;
const std::string str_arg(optarg);
@ -331,7 +364,7 @@ int main(int argc, char** argv) {
Common::ConfigureNvidiaEnvironmentFlags();
if (filepath.empty()) {
if (filepath.empty() && !static_cast<u32>(load_parameters.applet_id)) {
LOG_CRITICAL(Frontend, "Failed to load ROM: No ROM specified");
return -1;
}
@ -367,9 +400,27 @@ int main(int argc, char** argv) {
system.GetFileSystemController().CreateFactories(*system.GetFilesystem());
system.GetUserChannel().clear();
Service::AM::FrontendAppletParameters load_parameters{
.applet_id = Service::AM::AppletId::Application,
};
if (static_cast<u32>(load_parameters.applet_id)) {
// code below based off of suyu/main.cpp : GMainWindow::OnHomeMenu()
Service::AM::AppletProgramId applet_prog_id =
Service::AM::AppletIdToProgramId(load_parameters.applet_id);
auto sysnand = system.GetFileSystemController().GetSystemNANDContents();
if (!sysnand) {
LOG_CRITICAL(Frontend, "Failed to load applet: Firmware not installed.");
return -1;
}
auto user_applet_nca = sysnand->GetEntry(static_cast<u64>(applet_prog_id),
FileSys::ContentRecordType::Program);
if (!user_applet_nca) {
LOG_CRITICAL(Frontend, "Failed to load applet: applet cannot be found.");
return -1;
}
if (filepath.empty())
filepath = user_applet_nca->GetFullPath();
} else {
load_parameters.applet_id = Service::AM::AppletId::Application;
}
const Core::SystemResultStatus load_result{system.Load(*emu_window, filepath, load_parameters)};
switch (load_result) {