mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-25 16:22:47 +01:00
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:
parent
42f3dd309e
commit
1ed34b1e47
3 changed files with 140 additions and 87 deletions
|
@ -47,6 +47,75 @@ bool ShouldCreateGuestApplet(AppletId applet_id) {
|
||||||
return true;
|
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) {
|
AppletProgramId AppletIdToProgramId(AppletId applet_id) {
|
||||||
switch (applet_id) {
|
switch (applet_id) {
|
||||||
case AppletId::OverlayDisplay:
|
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,
|
ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||||
WindowSystem& window_system)
|
WindowSystem& window_system)
|
||||||
: ServiceFramework{system_, "ILibraryAppletCreator"},
|
: ServiceFramework{system_, "ILibraryAppletCreator"}, m_window_system{window_system},
|
||||||
m_window_system{window_system}, m_applet{std::move(applet)} {
|
m_applet{std::move(applet)} {
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&ILibraryAppletCreator::CreateLibraryApplet>, "CreateLibraryApplet"},
|
{0, D<&ILibraryAppletCreator::CreateLibraryApplet>, "CreateLibraryApplet"},
|
||||||
{1, nullptr, "TerminateAllLibraryApplets"},
|
{1, nullptr, "TerminateAllLibraryApplets"},
|
||||||
|
|
|
@ -35,4 +35,6 @@ private:
|
||||||
const std::shared_ptr<Applet> m_applet;
|
const std::shared_ptr<Applet> m_applet;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
AppletProgramId AppletIdToProgramId(AppletId applet_id);
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
@ -23,9 +24,12 @@
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/cpu_manager.h"
|
#include "core/cpu_manager.h"
|
||||||
#include "core/crypto/key_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/registered_cache.h"
|
||||||
#include "core/file_sys/vfs/vfs_real.h"
|
#include "core/file_sys/vfs/vfs_real.h"
|
||||||
#include "core/hle/service/am/applet_manager.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/hle/service/filesystem/filesystem.h"
|
||||||
#include "core/loader/loader.h"
|
#include "core/loader/loader.h"
|
||||||
#include "frontend_common/config.h"
|
#include "frontend_common/config.h"
|
||||||
|
@ -67,17 +71,23 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void PrintHelp(const char* argv0) {
|
static void PrintHelp(const char* argv0) {
|
||||||
std::cout << "Usage: " << argv0
|
std::cout
|
||||||
<< " [options] <filename>\n"
|
<< "Usage: " << argv0
|
||||||
"-c, --config Load the specified configuration file\n"
|
<< " [options] <filename>\n"
|
||||||
"-f, --fullscreen Start in fullscreen mode\n"
|
"-c, --config Load the specified configuration file\n"
|
||||||
"-g, --game File path of the game to load\n"
|
"-f, --fullscreen Start in fullscreen mode\n"
|
||||||
"-h, --help Display this help and exit\n"
|
"-g, --game File path of the game to load\n"
|
||||||
"-m, --multiplayer=nick:password@address:port"
|
"-h, --help Display this help and exit\n"
|
||||||
" Nickname, password, address and port for multiplayer\n"
|
"-m, --multiplayer=nick:password@address:port"
|
||||||
"-p, --program Pass following string as arguments to executable\n"
|
" Nickname, password, address and port for multiplayer\n"
|
||||||
"-u, --user Select a specific user profile from 0 to 7\n"
|
"-p, --program Pass following string as arguments to executable\n"
|
||||||
"-v, --version Output version information and exit\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() {
|
static void PrintVersion() {
|
||||||
|
@ -212,6 +222,7 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
bool use_multiplayer = false;
|
bool use_multiplayer = false;
|
||||||
bool fullscreen = false;
|
bool fullscreen = false;
|
||||||
|
Service::AM::FrontendAppletParameters load_parameters{};
|
||||||
std::string nickname{};
|
std::string nickname{};
|
||||||
std::string password{};
|
std::string password{};
|
||||||
std::string address{};
|
std::string address{};
|
||||||
|
@ -223,6 +234,7 @@ int main(int argc, char** argv) {
|
||||||
{"fullscreen", no_argument, 0, 'f'},
|
{"fullscreen", no_argument, 0, 'f'},
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{"game", required_argument, 0, 'g'},
|
{"game", required_argument, 0, 'g'},
|
||||||
|
{"applet-params", required_argument, 0, 'l'},
|
||||||
{"multiplayer", required_argument, 0, 'm'},
|
{"multiplayer", required_argument, 0, 'm'},
|
||||||
{"program", optional_argument, 0, 'p'},
|
{"program", optional_argument, 0, 'p'},
|
||||||
{"user", required_argument, 0, 'u'},
|
{"user", required_argument, 0, 'u'},
|
||||||
|
@ -232,7 +244,7 @@ int main(int argc, char** argv) {
|
||||||
};
|
};
|
||||||
|
|
||||||
while (optind < argc) {
|
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) {
|
if (arg != -1) {
|
||||||
switch (static_cast<char>(arg)) {
|
switch (static_cast<char>(arg)) {
|
||||||
case 'c':
|
case 'c':
|
||||||
|
@ -250,6 +262,27 @@ int main(int argc, char** argv) {
|
||||||
filepath = str_arg;
|
filepath = str_arg;
|
||||||
break;
|
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': {
|
case 'm': {
|
||||||
use_multiplayer = true;
|
use_multiplayer = true;
|
||||||
const std::string str_arg(optarg);
|
const std::string str_arg(optarg);
|
||||||
|
@ -331,7 +364,7 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
Common::ConfigureNvidiaEnvironmentFlags();
|
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");
|
LOG_CRITICAL(Frontend, "Failed to load ROM: No ROM specified");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -367,9 +400,27 @@ int main(int argc, char** argv) {
|
||||||
system.GetFileSystemController().CreateFactories(*system.GetFilesystem());
|
system.GetFileSystemController().CreateFactories(*system.GetFilesystem());
|
||||||
system.GetUserChannel().clear();
|
system.GetUserChannel().clear();
|
||||||
|
|
||||||
Service::AM::FrontendAppletParameters load_parameters{
|
if (static_cast<u32>(load_parameters.applet_id)) {
|
||||||
.applet_id = Service::AM::AppletId::Application,
|
// 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)};
|
const Core::SystemResultStatus load_result{system.Load(*emu_window, filepath, load_parameters)};
|
||||||
|
|
||||||
switch (load_result) {
|
switch (load_result) {
|
||||||
|
|
Loading…
Reference in a new issue