diff --git a/src/core/hle/service/am/service/library_applet_creator.cpp b/src/core/hle/service/am/service/library_applet_creator.cpp index 3ffb03bc978189eea4190b905a8fcba0cbcbd105..4048cb870493429dac0b410937134526dde027a7 100644 --- a/src/core/hle/service/am/service/library_applet_creator.cpp +++ b/src/core/hle/service/am/service/library_applet_creator.cpp @@ -47,59 +47,12 @@ bool ShouldCreateGuestApplet(AppletId applet_id) { return true; } -AppletProgramId AppletIdToProgramId(AppletId applet_id) { - switch (applet_id) { - case AppletId::OverlayDisplay: - return AppletProgramId::OverlayDisplay; - case AppletId::QLaunch: - return AppletProgramId::QLaunch; - case AppletId::Starter: - return AppletProgramId::Starter; - case AppletId::Auth: - return AppletProgramId::Auth; - case AppletId::Cabinet: - return AppletProgramId::Cabinet; - case AppletId::Controller: - return AppletProgramId::Controller; - case AppletId::DataErase: - return AppletProgramId::DataErase; - case AppletId::Error: - return AppletProgramId::Error; - case AppletId::NetConnect: - return AppletProgramId::NetConnect; - case AppletId::ProfileSelect: - return AppletProgramId::ProfileSelect; - case AppletId::SoftwareKeyboard: - return AppletProgramId::SoftwareKeyboard; - case AppletId::MiiEdit: - return AppletProgramId::MiiEdit; - case AppletId::Web: - return AppletProgramId::Web; - case AppletId::Shop: - return AppletProgramId::Shop; - case AppletId::PhotoViewer: - return AppletProgramId::PhotoViewer; - case AppletId::Settings: - return AppletProgramId::Settings; - case AppletId::OfflineWeb: - return AppletProgramId::OfflineWeb; - case AppletId::LoginShare: - return AppletProgramId::LoginShare; - case AppletId::WebAuth: - return AppletProgramId::WebAuth; - case AppletId::MyPage: - return AppletProgramId::MyPage; - default: - return static_cast<AppletProgramId>(0); - } -} - 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)); + const auto program_id = static_cast<u64>(Service::AM::AppletIdToProgramId(applet_id)); if (program_id == 0) { // Unknown applet return {}; @@ -141,7 +94,7 @@ std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& syste std::shared_ptr<Applet> caller_applet, AppletId applet_id, LibraryAppletMode mode) { - const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id)); + 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); @@ -163,10 +116,57 @@ std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& syste } // namespace +AppletProgramId AppletIdToProgramId(AppletId applet_id) { + switch (applet_id) { + case AppletId::OverlayDisplay: + return AppletProgramId::OverlayDisplay; + case AppletId::QLaunch: + return AppletProgramId::QLaunch; + case AppletId::Starter: + return AppletProgramId::Starter; + case AppletId::Auth: + return AppletProgramId::Auth; + case AppletId::Cabinet: + return AppletProgramId::Cabinet; + case AppletId::Controller: + return AppletProgramId::Controller; + case AppletId::DataErase: + return AppletProgramId::DataErase; + case AppletId::Error: + return AppletProgramId::Error; + case AppletId::NetConnect: + return AppletProgramId::NetConnect; + case AppletId::ProfileSelect: + return AppletProgramId::ProfileSelect; + case AppletId::SoftwareKeyboard: + return AppletProgramId::SoftwareKeyboard; + case AppletId::MiiEdit: + return AppletProgramId::MiiEdit; + case AppletId::Web: + return AppletProgramId::Web; + case AppletId::Shop: + return AppletProgramId::Shop; + case AppletId::PhotoViewer: + return AppletProgramId::PhotoViewer; + case AppletId::Settings: + return AppletProgramId::Settings; + case AppletId::OfflineWeb: + return AppletProgramId::OfflineWeb; + case AppletId::LoginShare: + return AppletProgramId::LoginShare; + case AppletId::WebAuth: + return AppletProgramId::WebAuth; + case AppletId::MyPage: + return AppletProgramId::MyPage; + default: + return static_cast<AppletProgramId>(0); + } +} + 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"}, diff --git a/src/core/hle/service/am/service/library_applet_creator.h b/src/core/hle/service/am/service/library_applet_creator.h index a10a7698280deefd65bffb30edbddcee89a21dc1..80ea6bd1af3a417cc2894c6b66ab2bc48124bad6 100644 --- a/src/core/hle/service/am/service/library_applet_creator.h +++ b/src/core/hle/service/am/service/library_applet_creator.h @@ -35,4 +35,6 @@ private: const std::shared_ptr<Applet> m_applet; }; +AppletProgramId AppletIdToProgramId(AppletId applet_id); + } // namespace Service::AM diff --git a/src/suyu_cmd/suyu.cpp b/src/suyu_cmd/suyu.cpp index f559c74f5b2c2f018a59f361347547b03e06cc8c..5458b0793bc0c60fe75bade71ccb388ce85b9d6c 100644 --- a/src/suyu_cmd/suyu.cpp +++ b/src/suyu_cmd/suyu.cpp @@ -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) {