mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-05-27 04:17:02 +02:00
Compare commits
18 commits
726f4621ea
...
6b94984041
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b94984041 | ||
|
|
a8d6b4fe60 | ||
|
|
ea4d36ad06 | ||
|
|
ea9f43d987 | ||
|
|
20f1a2ef02 | ||
|
|
272a71d27d | ||
|
|
84db20b9f0 | ||
|
|
12af978b3e | ||
|
|
aa2875e1e9 | ||
|
|
daee174a87 | ||
|
|
41283a8fac | ||
|
|
2f90bd6de8 | ||
|
|
610c757592 | ||
|
|
fb4385f7ea | ||
|
|
5d60dc79bb | ||
|
|
5ab562a9c0 | ||
|
|
cd38b261a4 | ||
|
|
e2ebc37cd0 |
21 changed files with 570 additions and 47 deletions
|
|
@ -1089,6 +1089,8 @@ add_library(core STATIC
|
|||
hle/service/ssl/ssl.h
|
||||
hle/service/ssl/ssl_backend.h
|
||||
hle/service/ssl/ssl_types.h
|
||||
hle/service/ulsf/ulsf.cpp
|
||||
hle/service/ulsf/ulsf.h
|
||||
hle/service/usb/usb.cpp
|
||||
hle/service/usb/usb.h
|
||||
hle/service/vi/application_display_service.cpp
|
||||
|
|
|
|||
|
|
@ -83,7 +83,8 @@ constexpr size_t SlabCountKDeviceAddressSpace = 300;
|
|||
constexpr size_t SlabCountKSession = 1133;
|
||||
constexpr size_t SlabCountKLightSession = 100;
|
||||
constexpr size_t SlabCountKObjectName = 7;
|
||||
constexpr size_t SlabCountKResourceLimit = 5;
|
||||
// TODO(lizzie): divergence that allows ulauncher to work
|
||||
constexpr size_t SlabCountKResourceLimit = 5 + 1;
|
||||
constexpr size_t SlabCountKDebug = Core::Hardware::NUM_CPU_CORES;
|
||||
constexpr size_t SlabCountKIoPool = 1;
|
||||
constexpr size_t SlabCountKIoRegion = 6;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
|
|
@ -94,7 +94,9 @@ enum class AppletId : u32 {
|
|||
LoginShare = 0x18,
|
||||
WebAuth = 0x19,
|
||||
MyPage = 0x1A,
|
||||
Lhub = 0x35
|
||||
Lhub = 0x35,
|
||||
// Homebrew -- uses same ProgramId as qlaunch
|
||||
UlauncherUmenu = 0xF000'0000,
|
||||
};
|
||||
|
||||
enum class AppletProgramId : u64 {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,20 @@ namespace Service::AM {
|
|||
|
||||
namespace {
|
||||
|
||||
constexpr size_t NroPathSize = 512;
|
||||
constexpr size_t NroArgvSize = 2048;
|
||||
constexpr size_t MenuCaptionSize = 1024;
|
||||
struct UloaderTargetInput {
|
||||
u32 magic;
|
||||
bool target_once;
|
||||
bool is_auto_game_recording;
|
||||
std::array<u8, 2> unused;
|
||||
std::array<char, NroPathSize> nro_path;
|
||||
std::array<char, NroArgvSize> nro_argv;
|
||||
std::array<char, MenuCaptionSize> menu_caption;
|
||||
};
|
||||
static_assert(sizeof(UloaderTargetInput) == 3592);
|
||||
|
||||
constexpr u32 LaunchParameterAccountPreselectedUserMagic = 0xC79497CA;
|
||||
|
||||
struct LaunchParameterAccountPreselectedUser {
|
||||
|
|
@ -121,6 +135,44 @@ void PushInShowController(Core::System& system, AppletStorageChannel& channel) {
|
|||
channel.Push(std::make_shared<IStorage>(system, std::move(user_args_data)));
|
||||
}
|
||||
|
||||
void PushInShowUlauncherUmenu(Core::System& system, AppletStorageChannel& channel) {
|
||||
typedef std::array<u64, 2> AccountUid;
|
||||
const CommonArguments common_args = {
|
||||
.arguments_version = CommonArgumentVersion::Version3,
|
||||
.size = CommonArgumentSize::Version3,
|
||||
.library_version = 2,
|
||||
.theme_color = ThemeColor::BasicBlack,
|
||||
.play_startup_sound = true,
|
||||
.system_tick = system.CoreTiming().GetClockTicks(),
|
||||
};
|
||||
struct UmenuInput {
|
||||
AccountUid selected_user;
|
||||
UloaderTargetInput suspended_hb_target_ipt; // Set if homebrew (launched as an application) is currently suspended
|
||||
u64 suspended_app_id; // Set if any normal application is suspended
|
||||
std::array<char, 0x301> last_menu_fs_path; //FS_MAX_PATH
|
||||
std::array<char, 0x301> last_menu_path;
|
||||
u32 last_menu_index;
|
||||
bool reload_theme_cache;
|
||||
bool warned_about_outdated_theme;
|
||||
u32 last_added_app_count;
|
||||
u32 last_deleted_app_count;
|
||||
u32 in_verify_app_count;
|
||||
} user_args = {};
|
||||
static_assert(sizeof(UmenuInput) == 5176);
|
||||
|
||||
auto const user = system.GetProfileManager().GetUser(0);
|
||||
user_args.selected_user[0] = user->uuid[0];
|
||||
user_args.selected_user[1] = user->uuid[1];
|
||||
user_args.warned_about_outdated_theme = true;
|
||||
|
||||
std::vector<u8> common_args_data(sizeof(common_args));
|
||||
std::vector<u8> user_args_data(sizeof(user_args));
|
||||
std::memcpy(common_args_data.data(), std::addressof(common_args), sizeof(common_args));
|
||||
std::memcpy(user_args_data.data(), std::addressof(user_args), sizeof(user_args));
|
||||
channel.Push(std::make_shared<IStorage>(system, std::move(common_args_data)));
|
||||
channel.Push(std::make_shared<IStorage>(system, std::move(user_args_data)));
|
||||
}
|
||||
|
||||
void PushInShowCabinetData(Core::System& system, AppletStorageChannel& channel) {
|
||||
const CommonArguments arguments{
|
||||
.arguments_version = CommonArgumentVersion::Version3,
|
||||
|
|
@ -292,8 +344,18 @@ void AppletManager::SetWindowSystem(WindowSystem* window_system) {
|
|||
applet->previous_program_index = params.previous_program_index;
|
||||
|
||||
// Push UserChannel data from previous application
|
||||
// Or ulaunch initialization where we push parameters willingly!
|
||||
if (params.launch_type == LaunchType::ApplicationInitiated) {
|
||||
applet->user_channel_launch_parameter.swap(m_system.GetUserChannel());
|
||||
} else if (params.launch_type == LaunchType::FrontendUlaunchInitiated) {
|
||||
UloaderTargetInput target_ipt = {};
|
||||
target_ipt.magic = 0x49444C55; // "ULDI"
|
||||
target_ipt.nro_path = {"sdmc:/hbmenu.nro"};
|
||||
target_ipt.menu_caption = {"Loaded by uLoader v1.2.4 - uLaunch's custom hbloader replacement ;)"};
|
||||
std::vector<u8> v(sizeof(target_ipt));
|
||||
std::memcpy(v.data(), std::addressof(target_ipt), sizeof(target_ipt));
|
||||
applet->user_channel_launch_parameter.clear();
|
||||
applet->user_channel_launch_parameter.push_back(std::move(v));
|
||||
}
|
||||
|
||||
// TODO: Read whether we need a preselected user from NACP?
|
||||
|
|
@ -335,6 +397,9 @@ void AppletManager::SetWindowSystem(WindowSystem* window_system) {
|
|||
case AppletId::Controller:
|
||||
PushInShowController(m_system, InitializeFakeCallerApplet(m_system, applet));
|
||||
break;
|
||||
case AppletId::UlauncherUmenu:
|
||||
PushInShowUlauncherUmenu(m_system, InitializeFakeCallerApplet(m_system, applet));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -342,7 +407,7 @@ void AppletManager::SetWindowSystem(WindowSystem* window_system) {
|
|||
// Applet was started by frontend, so it is foreground.
|
||||
applet->lifecycle_manager.SetFocusState(FocusState::InFocus);
|
||||
|
||||
if (applet->applet_id == AppletId::QLaunch) {
|
||||
if (applet->applet_id == AppletId::QLaunch || applet->applet_id == AppletId::UlauncherUmenu) {
|
||||
applet->lifecycle_manager.SetFocusHandlingMode(false);
|
||||
applet->lifecycle_manager.SetOutOfFocusSuspendingEnabled(false);
|
||||
m_window_system->TrackApplet(applet, false);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
|
|
@ -26,6 +26,9 @@ class WindowSystem;
|
|||
enum class LaunchType {
|
||||
FrontendInitiated,
|
||||
ApplicationInitiated,
|
||||
// Special masquerade for AMS + uLaunch CFW
|
||||
FrontendUlaunchInitiated = 0x800,
|
||||
FrontendUmenuInitiated,
|
||||
};
|
||||
|
||||
struct FrontendAppletParameters {
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ AppletProgramId AppletIdToProgramId(AppletId applet_id) {
|
|||
case AppletId::OverlayDisplay:
|
||||
return AppletProgramId::OverlayDisplay;
|
||||
case AppletId::QLaunch:
|
||||
case AppletId::UlauncherUmenu: //reuses same id as Qlaunch
|
||||
return AppletProgramId::QLaunch;
|
||||
case AppletId::Starter:
|
||||
return AppletProgramId::Starter;
|
||||
|
|
|
|||
|
|
@ -8,18 +8,23 @@
|
|||
#include "core/file_sys/control_metadata.h"
|
||||
#include "core/file_sys/patch_manager.h"
|
||||
#include "core/file_sys/registered_cache.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/acc/profile_manager.h"
|
||||
#include "core/hle/service/am/applet_data_broker.h"
|
||||
#include "core/hle/service/am/applet_manager.h"
|
||||
#include "core/hle/service/am/frontend/applets.h"
|
||||
#include "core/hle/service/am/process_creation.h"
|
||||
#include "core/hle/service/am/service/library_applet_self_accessor.h"
|
||||
#include "core/hle/service/am/service/storage.h"
|
||||
#include "core/hle/service/am/window_system.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/hle/service/glue/glue_manager.h"
|
||||
#include "core/hle/service/ns/application_manager_interface.h"
|
||||
#include "core/hle/service/ns/service_getter_interface.h"
|
||||
#include "core/hle/service/server_manager.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
|
|
@ -44,8 +49,9 @@ AppletIdentityInfo GetCallerIdentity(Applet& applet) {
|
|||
|
||||
ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_,
|
||||
std::shared_ptr<Applet> applet)
|
||||
: ServiceFramework{system_, "ILibraryAppletSelfAccessor"}, m_applet{std::move(applet)},
|
||||
m_broker{m_applet->caller_applet_broker} {
|
||||
: ServiceFramework{system_, "ILibraryAppletSelfAccessor"}, m_applet{std::move(applet)}
|
||||
, m_broker{m_applet->caller_applet_broker}
|
||||
{
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&ILibraryAppletSelfAccessor::PopInData>, "PopInData"},
|
||||
|
|
@ -96,9 +102,130 @@ Result ILibraryAppletSelfAccessor::PopInData(Out<SharedPointer<IStorage>> out_st
|
|||
R_RETURN(m_broker->GetInData().Pop(out_storage));
|
||||
}
|
||||
|
||||
// uLauncher emulation
|
||||
static Result UloaderCreateApplication(Core::System& system, u64 program_id, std::shared_ptr<Applet> caller_applet) {
|
||||
// Get the program NCA from storage.
|
||||
auto& storage = system.GetContentProviderUnion();
|
||||
FileSys::VirtualFile nca_raw = storage.GetEntryRaw(program_id, FileSys::ContentRecordType::Program);
|
||||
// Ensure we retrieved a program NCA.
|
||||
R_UNLESS(nca_raw != nullptr, ResultUnknown);
|
||||
std::vector<u8> control;
|
||||
std::unique_ptr<Loader::AppLoader> loader;
|
||||
Loader::ResultStatus result;
|
||||
auto process = CreateApplicationProcess(control, loader, result, system, nca_raw, program_id, 0);
|
||||
R_UNLESS(process != nullptr, ResultUnknown);
|
||||
const auto applet = std::make_shared<Applet>(system, std::move(process), true);
|
||||
applet->program_id = program_id;
|
||||
applet->applet_id = AppletId::Application;
|
||||
applet->type = AppletType::Application;
|
||||
applet->library_applet_mode = LibraryAppletMode::AllForeground;
|
||||
|
||||
applet->caller_applet = caller_applet;
|
||||
applet->caller_applet_broker = std::make_shared<AppletDataBroker>(system);
|
||||
applet->frontend = caller_applet->frontend;
|
||||
caller_applet->child_applets.push_back(applet);
|
||||
|
||||
system.GetAppletManager().GetWindowSystem()->TrackApplet(applet, true);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ILibraryAppletSelfAccessor::PushOutData(SharedPointer<IStorage> storage) {
|
||||
LOG_INFO(Service_AM, "called");
|
||||
m_broker->GetOutData().Push(storage);
|
||||
|
||||
if (m_applet->applet_id == AppletId::UlauncherUmenu) {
|
||||
enum class SystemMessage : u32 {
|
||||
Invalid,
|
||||
SetSelectedUser,
|
||||
LaunchApplication,
|
||||
ResumeApplication,
|
||||
TerminateApplication,
|
||||
LaunchHomebrewLibraryApplet,
|
||||
LaunchHomebrewApplication,
|
||||
ChooseHomebrew,
|
||||
OpenWebPage,
|
||||
OpenAlbum,
|
||||
RestartMenu,
|
||||
ReloadConfig,
|
||||
UpdateMenuPaths,
|
||||
UpdateMenuIndex,
|
||||
OpenUserPage,
|
||||
OpenMiiEdit,
|
||||
OpenAddUser,
|
||||
OpenNetConnect,
|
||||
ListAddedApplications,
|
||||
ListDeletedApplications,
|
||||
OpenCabinet,
|
||||
StartVerifyApplication,
|
||||
ListInVerifyApplications,
|
||||
NotifyWarnedAboutOutdatedTheme,
|
||||
TerminateMenu,
|
||||
OpenControllerKeyRemapping
|
||||
};
|
||||
struct CommandCommonHeader {
|
||||
u32 magic;
|
||||
u32 val;
|
||||
};
|
||||
std::shared_ptr<IStorage> req_storage;
|
||||
m_broker->GetOutData().Pop(&req_storage);
|
||||
auto req_data = req_storage->GetData();
|
||||
CommandCommonHeader req_cmd{};
|
||||
std::memcpy(&req_cmd, req_data.data(), sizeof(req_cmd));
|
||||
|
||||
LOG_WARNING(Service_AM, "uLauncher:IPC {}, {}", req_cmd.magic, req_cmd.val);
|
||||
switch (SystemMessage(req_cmd.val)) {
|
||||
case SystemMessage::SetSelectedUser:
|
||||
break;
|
||||
case SystemMessage::LaunchApplication: {
|
||||
// all applet proxies OpenSystemAppletProxy
|
||||
// applet proxy GetApplicationCreator
|
||||
// application creator CreateApplication
|
||||
u64 args_value{};
|
||||
std::memcpy(std::addressof(args_value), req_data.data() + sizeof(req_cmd), sizeof(args_value));
|
||||
LOG_WARNING(Service_AM, "program_id={:016x}", args_value);
|
||||
UloaderCreateApplication(system, args_value, m_applet);
|
||||
break;
|
||||
}
|
||||
case SystemMessage::ResumeApplication:
|
||||
case SystemMessage::TerminateApplication:
|
||||
case SystemMessage::LaunchHomebrewLibraryApplet:
|
||||
case SystemMessage::LaunchHomebrewApplication:
|
||||
case SystemMessage::ChooseHomebrew:
|
||||
case SystemMessage::OpenWebPage:
|
||||
case SystemMessage::OpenAlbum:
|
||||
case SystemMessage::RestartMenu:
|
||||
case SystemMessage::ReloadConfig:
|
||||
case SystemMessage::UpdateMenuPaths:
|
||||
case SystemMessage::UpdateMenuIndex:
|
||||
case SystemMessage::OpenUserPage:
|
||||
case SystemMessage::OpenMiiEdit:
|
||||
case SystemMessage::OpenAddUser:
|
||||
case SystemMessage::OpenNetConnect:
|
||||
case SystemMessage::ListAddedApplications:
|
||||
case SystemMessage::ListDeletedApplications:
|
||||
case SystemMessage::OpenCabinet:
|
||||
case SystemMessage::StartVerifyApplication:
|
||||
case SystemMessage::ListInVerifyApplications:
|
||||
case SystemMessage::NotifyWarnedAboutOutdatedTheme:
|
||||
break;
|
||||
case SystemMessage::TerminateMenu:
|
||||
system.GetUserChannel() = m_applet->user_channel_launch_parameter;
|
||||
system.ExecuteProgram(0);
|
||||
break;
|
||||
case SystemMessage::OpenControllerKeyRemapping:
|
||||
break;
|
||||
case SystemMessage::Invalid:
|
||||
break;
|
||||
}
|
||||
|
||||
CommandCommonHeader res_cmd{};
|
||||
std::vector<u8> res_data(0x8000);
|
||||
res_cmd.magic = 0x21494D53;
|
||||
res_cmd.val = u32(ResultSuccess.raw);
|
||||
std::memcpy(res_data.data(), &res_cmd, sizeof(res_cmd));
|
||||
m_broker->GetInData().Push(std::make_shared<IStorage>(system, std::move(res_data)));
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ void WindowSystem::Update() {
|
|||
void WindowSystem::TrackApplet(std::shared_ptr<Applet> applet, bool is_application) {
|
||||
std::scoped_lock lk{m_lock};
|
||||
|
||||
if (applet->applet_id == AppletId::QLaunch) {
|
||||
if (applet->applet_id == AppletId::QLaunch || applet->applet_id == AppletId::UlauncherUmenu) {
|
||||
ASSERT(m_home_menu == nullptr);
|
||||
m_home_menu = applet.get();
|
||||
} else if (applet->applet_id == AppletId::OverlayDisplay) {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ IBtmSystemCore::IBtmSystemCore(Core::System& system_)
|
|||
{10, nullptr, "StartAudioDeviceDiscovery"},
|
||||
{11, nullptr, "StopAudioDeviceDiscovery"},
|
||||
{12, nullptr, "IsDiscoveryingAudioDevice"},
|
||||
{13, nullptr, "GetDiscoveredAudioDevice"},
|
||||
{13, C<&IBtmSystemCore::GetDiscoveredAudioDevice>, "GetDiscoveredAudioDevice"},
|
||||
{14, C<&IBtmSystemCore::AcquireAudioDeviceConnectionEvent>, "AcquireAudioDeviceConnectionEvent"},
|
||||
{15, nullptr, "ConnectAudioDevice"},
|
||||
{16, nullptr, "IsConnectingAudioDevice"},
|
||||
|
|
@ -93,6 +93,11 @@ Result IBtmSystemCore::AcquireRadioEvent(Out<bool> out_is_valid,
|
|||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IBtmSystemCore::GetDiscoveredAudioDevice(OutArray<std::array<u8, 0xFF>, BufferAttr_HipcPointer> out_audio_devices, s32 count, Out<s32> out_total) {
|
||||
LOG_WARNING(Service_BTM, "(STUBBED) called");
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IBtmSystemCore::AcquireAudioDeviceConnectionEvent(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_WARNING(Service_BTM, "(STUBBED) called");
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
|
|
@ -34,9 +37,8 @@ private:
|
|||
Result DisableRadio();
|
||||
Result IsRadioEnabled(Out<bool> out_is_enabled);
|
||||
|
||||
Result AcquireRadioEvent(Out<bool> out_is_valid,
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
|
||||
Result AcquireRadioEvent(Out<bool> out_is_valid, OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result GetDiscoveredAudioDevice(OutArray<std::array<u8, 0xFF>, BufferAttr_HipcPointer> out_audio_devices, s32 count, Out<s32> out_total);
|
||||
Result AcquireAudioDeviceConnectionEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
|
||||
Result GetConnectedAudioDevices(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
|
|
@ -62,6 +62,7 @@
|
|||
#include "core/hle/service/sockets/sockets.h"
|
||||
#include "core/hle/service/spl/spl_module.h"
|
||||
#include "core/hle/service/ssl/ssl.h"
|
||||
#include "core/hle/service/ulsf/ulsf.h"
|
||||
#include "core/hle/service/usb/usb.h"
|
||||
#include "core/hle/service/vi/vi.h"
|
||||
|
||||
|
|
@ -144,7 +145,8 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system
|
|||
{"ro", &RO::LoopProcess},
|
||||
{"spl", &SPL::LoopProcess},
|
||||
{"ssl", &SSL::LoopProcess},
|
||||
{"usb", &USB::LoopProcess}
|
||||
{"usb", &USB::LoopProcess},
|
||||
{"ulsf", &ULSF::LoopProcess},
|
||||
})
|
||||
kernel.RunOnGuestCoreProcess(std::string(e.first), [&system, f = e.second] { f(system); });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,10 +142,10 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
|
|||
{22, C<&ISystemSettingsServer::SetEulaVersions>, "SetEulaVersions"},
|
||||
{23, C<&ISystemSettingsServer::GetColorSetId>, "GetColorSetId"},
|
||||
{24, C<&ISystemSettingsServer::SetColorSetId>, "SetColorSetId"},
|
||||
{25, nullptr, "GetConsoleInformationUploadFlag"},
|
||||
{26, nullptr, "SetConsoleInformationUploadFlag"},
|
||||
{27, nullptr, "GetAutomaticApplicationDownloadFlag"},
|
||||
{28, nullptr, "SetAutomaticApplicationDownloadFlag"},
|
||||
{25, C<&ISystemSettingsServer::GetConsoleInformationUploadFlag>, "GetConsoleInformationUploadFlag"},
|
||||
{26, C<&ISystemSettingsServer::SetConsoleInformationUploadFlag>, "SetConsoleInformationUploadFlag"},
|
||||
{27, C<&ISystemSettingsServer::GetAutomaticApplicationDownloadFlag>, "GetAutomaticApplicationDownloadFlag"},
|
||||
{28, C<&ISystemSettingsServer::SetAutomaticApplicationDownloadFlag>, "SetAutomaticApplicationDownloadFlag"},
|
||||
{29, C<&ISystemSettingsServer::GetNotificationSettings>, "GetNotificationSettings"},
|
||||
{30, C<&ISystemSettingsServer::SetNotificationSettings>, "SetNotificationSettings"},
|
||||
{31, C<&ISystemSettingsServer::GetAccountNotificationSettings>, "GetAccountNotificationSettings"},
|
||||
|
|
@ -160,8 +160,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
|
|||
{42, nullptr, "SetEdid"},
|
||||
{43, C<&ISystemSettingsServer::GetAudioOutputMode>, "GetAudioOutputMode"},
|
||||
{44, C<&ISystemSettingsServer::SetAudioOutputMode>, "SetAudioOutputMode"},
|
||||
{45, C<&ISystemSettingsServer::GetSpeakerAutoMuteFlag> , "GetSpeakerAutoMuteFlag"},
|
||||
{46, C<&ISystemSettingsServer::SetSpeakerAutoMuteFlag> , "SetSpeakerAutoMuteFlag"},
|
||||
{45, C<&ISystemSettingsServer::GetSpeakerAutoMuteFlag>, "GetSpeakerAutoMuteFlag"},
|
||||
{46, C<&ISystemSettingsServer::SetSpeakerAutoMuteFlag>, "SetSpeakerAutoMuteFlag"},
|
||||
{47, C<&ISystemSettingsServer::GetQuestFlag>, "GetQuestFlag"},
|
||||
{48, C<&ISystemSettingsServer::SetQuestFlag>, "SetQuestFlag"},
|
||||
{49, nullptr, "GetDataDeletionSettings"},
|
||||
|
|
@ -180,8 +180,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
|
|||
{62, C<&ISystemSettingsServer::GetDebugModeFlag>, "GetDebugModeFlag"},
|
||||
{63, C<&ISystemSettingsServer::GetPrimaryAlbumStorage>, "GetPrimaryAlbumStorage"},
|
||||
{64, C<&ISystemSettingsServer::SetPrimaryAlbumStorage>, "SetPrimaryAlbumStorage"},
|
||||
{65, nullptr, "GetUsb30EnableFlag"},
|
||||
{66, nullptr, "SetUsb30EnableFlag"},
|
||||
{65, C<&ISystemSettingsServer::GetUsb30EnableFlag>, "GetUsb30EnableFlag"},
|
||||
{66, C<&ISystemSettingsServer::SetUsb30EnableFlag>, "SetUsb30EnableFlag"},
|
||||
{67, C<&ISystemSettingsServer::GetBatteryLot>, "GetBatteryLot"},
|
||||
{68, C<&ISystemSettingsServer::GetSerialNumber>, "GetSerialNumber"},
|
||||
{69, C<&ISystemSettingsServer::GetNfcEnableFlag>, "GetNfcEnableFlag"},
|
||||
|
|
@ -1074,6 +1074,45 @@ Result ISystemSettingsServer::SetNfcEnableFlag(bool nfc_enable_flag) {
|
|||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISystemSettingsServer::GetConsoleInformationUploadFlag(Out<bool> out_flag) {
|
||||
LOG_INFO(Service_SET, "called {}", m_system_settings.console_information_upload_flag);
|
||||
*out_flag = m_system_settings.console_information_upload_flag;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISystemSettingsServer::SetConsoleInformationUploadFlag(bool flag) {
|
||||
LOG_INFO(Service_SET, "called {}", flag);
|
||||
m_system_settings.usb_30_enable_flag = flag;
|
||||
SetSaveNeeded();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISystemSettingsServer::GetAutomaticApplicationDownloadFlag(Out<bool> out_flag) {
|
||||
LOG_INFO(Service_SET, "called {}", m_system_settings.usb_30_enable_flag);
|
||||
*out_flag = m_system_settings.automatic_application_download_flag;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISystemSettingsServer::SetAutomaticApplicationDownloadFlag(bool flag) {
|
||||
LOG_INFO(Service_SET, "called {}", flag);
|
||||
m_system_settings.automatic_application_download_flag = flag;
|
||||
SetSaveNeeded();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISystemSettingsServer::GetUsb30EnableFlag(Out<bool> out_usb30_enable_flag) {
|
||||
LOG_INFO(Service_SET, "called, usb30_enable_flag={}", m_system_settings.usb_30_enable_flag);
|
||||
*out_usb30_enable_flag = m_system_settings.usb_30_enable_flag;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISystemSettingsServer::SetUsb30EnableFlag(bool usb30_enable_flag) {
|
||||
LOG_INFO(Service_SET, "called, usb30_enable_flag={}", usb30_enable_flag);
|
||||
m_system_settings.usb_30_enable_flag = usb30_enable_flag;
|
||||
SetSaveNeeded();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISystemSettingsServer::GetSleepSettings(Out<SleepSettings> out_sleep_settings) {
|
||||
LOG_INFO(Service_SET, "called, flags={}, handheld_sleep_plan={}, console_sleep_plan={}",
|
||||
m_system_settings.sleep_settings.flags.raw,
|
||||
|
|
|
|||
|
|
@ -109,6 +109,12 @@ public:
|
|||
Result SetPrimaryAlbumStorage(PrimaryAlbumStorage primary_album_storage);
|
||||
Result GetBatteryLot(Out<BatteryLot> out_battery_lot);
|
||||
Result GetSerialNumber(Out<SerialNumber> out_console_serial);
|
||||
Result GetConsoleInformationUploadFlag(Out<bool> out_flag);
|
||||
Result SetConsoleInformationUploadFlag(bool flag);
|
||||
Result GetAutomaticApplicationDownloadFlag(Out<bool> out_flag);
|
||||
Result SetAutomaticApplicationDownloadFlag(bool flag);
|
||||
Result GetUsb30EnableFlag(Out<bool> out_usb30_enable_flag);
|
||||
Result SetUsb30EnableFlag(bool usb30_enable_flag);
|
||||
Result GetNfcEnableFlag(Out<bool> out_nfc_enable_flag);
|
||||
Result SetNfcEnableFlag(bool nfc_enable_flag);
|
||||
Result GetSleepSettings(Out<SleepSettings> out_sleep_settings);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -11,6 +14,7 @@
|
|||
#include "core/hle/kernel/k_scoped_resource_reservation.h"
|
||||
#include "core/hle/kernel/k_server_port.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/server_manager.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
|
@ -250,15 +254,37 @@ void SM::UnregisterService(HLERequestContext& ctx) {
|
|||
rb.Push(service_manager.UnregisterService(name));
|
||||
}
|
||||
|
||||
void SM::AtmosphereHasService(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
std::string name(PopServiceName(rp));
|
||||
LOG_WARNING(Service_SM, "(stubbed) called with name={}", name);
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
Kernel::KClientPort* out_client_port = nullptr;
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<bool>(service_manager.GetServicePort(&out_client_port, name) == ResultSuccess);
|
||||
}
|
||||
|
||||
SM::SM(ServiceManager& service_manager_, Core::System& system_)
|
||||
: ServiceFramework{system_, "sm:", 4},
|
||||
service_manager{service_manager_}, kernel{system_.Kernel()} {
|
||||
: ServiceFramework{system_, "sm:", 4}
|
||||
, service_manager{service_manager_}
|
||||
, kernel{system_.Kernel()}
|
||||
{
|
||||
RegisterHandlers({
|
||||
{0, &SM::Initialize, "Initialize"},
|
||||
{1, &SM::GetServiceCmif, "GetService"},
|
||||
{2, &SM::RegisterServiceCmif, "RegisterService"},
|
||||
{3, &SM::UnregisterService, "UnregisterService"},
|
||||
{4, nullptr, "DetachClient"},
|
||||
// TODO: are these non-TIPC as well?
|
||||
{65000, nullptr, "AtmosphereInstallMitm"},
|
||||
{65001, nullptr, "AtmosphereUninstallMitm"},
|
||||
{65002, nullptr, "Deprecated_AtmosphereAssociatePidTidForMitm"},
|
||||
{65003, nullptr, "AtmosphereAcknowledgeMitmSession"},
|
||||
{65004, nullptr, "AtmosphereHasMitm"},
|
||||
{65005, nullptr, "AtmosphereWaitMitm"},
|
||||
{65006, nullptr, "AtmosphereDeclareFutureMitm"},
|
||||
{65100, &SM::AtmosphereHasService, "AtmosphereHasService"},
|
||||
{65101, nullptr, "AtmosphereWaitService"},
|
||||
});
|
||||
RegisterHandlersTipc({
|
||||
{0, &SM::Initialize, "Initialize"},
|
||||
|
|
@ -266,6 +292,15 @@ SM::SM(ServiceManager& service_manager_, Core::System& system_)
|
|||
{2, &SM::RegisterServiceTipc, "RegisterService"},
|
||||
{3, &SM::UnregisterService, "UnregisterService"},
|
||||
{4, nullptr, "DetachClient"},
|
||||
{65000, nullptr, "AtmosphereInstallMitm"},
|
||||
{65001, nullptr, "AtmosphereUninstallMitm"},
|
||||
{65002, nullptr, "Deprecated_AtmosphereAssociatePidTidForMitm"},
|
||||
{65003, nullptr, "AtmosphereAcknowledgeMitmSession"},
|
||||
{65004, nullptr, "AtmosphereHasMitm"},
|
||||
{65005, nullptr, "AtmosphereWaitMitm"},
|
||||
{65006, nullptr, "AtmosphereDeclareFutureMitm"},
|
||||
{65100, &SM::AtmosphereHasService, "AtmosphereHasService"},
|
||||
{65101, nullptr, "AtmosphereWaitService"},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ private:
|
|||
void RegisterServiceCmif(HLERequestContext& ctx);
|
||||
void RegisterServiceTipc(HLERequestContext& ctx);
|
||||
void UnregisterService(HLERequestContext& ctx);
|
||||
void AtmosphereHasService(HLERequestContext& ctx);
|
||||
|
||||
Result GetServiceImpl(Kernel::KClientSession** out_client_session, HLERequestContext& ctx);
|
||||
void RegisterServiceImpl(HLERequestContext& ctx, std::string name, u32 max_session_count,
|
||||
|
|
|
|||
137
src/core/hle/service/ulsf/ulsf.cpp
Normal file
137
src/core/hle/service/ulsf/ulsf.cpp
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <memory>
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/ulsf/ulsf.h"
|
||||
#include "core/hle/service/server_manager.h"
|
||||
|
||||
namespace Service::ULSF {
|
||||
|
||||
ULSF_U::ULSF_U(Core::System& system_) : ServiceFramework{system_, "ulsf:u"} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &ULSF_U::GetVersion, "GetVersion"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
ULSF_U::~ULSF_U() = default;
|
||||
|
||||
// Result ULSF_U::GetVersion(Out<ULauncherVersion> out_version) {
|
||||
// LOG_WARNING(Service_SM, "(stubbed)");
|
||||
// *out_version = {};
|
||||
// R_SUCCEED();
|
||||
// }
|
||||
|
||||
void ULSF_U::GetVersion(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_SM, "(stubbed)");
|
||||
ULauncherVersion version{1, 6, 7};
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(version);
|
||||
}
|
||||
|
||||
enum class MenuMessage : u32 {
|
||||
Invalid,
|
||||
HomeRequest,
|
||||
SdCardEjected,
|
||||
GameCardMountFailure,
|
||||
PreviousLaunchFailure,
|
||||
ChosenHomebrew,
|
||||
FinishedSleep,
|
||||
ApplicationRecordsChanged,
|
||||
ApplicationVerifyProgress,
|
||||
ApplicationVerifyResult
|
||||
};
|
||||
struct MenuMessageContext {
|
||||
MenuMessage msg;
|
||||
union {
|
||||
struct {
|
||||
Result mount_rc;
|
||||
} gc_mount_failure;
|
||||
struct {
|
||||
char nro_path[0x301];
|
||||
} chosen_hb;
|
||||
struct {
|
||||
bool records_added_or_deleted;
|
||||
} app_records_changed;
|
||||
struct {
|
||||
u64 app_id;
|
||||
u64 done;
|
||||
u64 total;
|
||||
} app_verify_progress;
|
||||
struct {
|
||||
u64 app_id;
|
||||
Result rc;
|
||||
Result detail_rc;
|
||||
} app_verify_rc;
|
||||
};
|
||||
};
|
||||
|
||||
class ULSF_P final : public ServiceFramework<ULSF_P> {
|
||||
public:
|
||||
explicit ULSF_P(Core::System& system_) : ServiceFramework{system_, "ulsf:p"} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, C<&ULSF_P::Initialize>, "Initialize"},
|
||||
{1, C<&ULSF_P::TryPopMessageContext>, "TryPopMessageContext"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
~ULSF_P() = default;
|
||||
|
||||
Result Initialize(u64 pid) {
|
||||
LOG_WARNING(Service_SM, "(stubbed) pid={}", pid);
|
||||
R_SUCCEED();
|
||||
}
|
||||
Result TryPopMessageContext(OutLargeData<MenuMessageContext, BufferAttr_HipcMapAlias> out_menu_message) {
|
||||
//LOG_WARNING(Service_SM, "(stubbed)");
|
||||
// *out_menu_message = {};
|
||||
// R_SUCCEED();
|
||||
R_THROW(Kernel::ResultInvalidAddress);
|
||||
}
|
||||
};
|
||||
|
||||
class AVM final : public ServiceFramework<AVM> {
|
||||
public:
|
||||
explicit AVM(Core::System& system_): ServiceFramework{system_, "avm"} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &AVM::Cmd0, "Cmd0"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
~AVM() = default;
|
||||
void Cmd0(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_SM, "(stubbed)");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
};
|
||||
class WLAN final : public ServiceFramework<WLAN> {
|
||||
public:
|
||||
explicit WLAN(Core::System& system_): ServiceFramework{system_, "wlan"} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &WLAN::Cmd0, "Cmd0"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
~WLAN() = default;
|
||||
void Cmd0(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_SM, "(stubbed)");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
};
|
||||
|
||||
void LoopProcess(Core::System& system) {
|
||||
auto server_manager = std::make_unique<ServerManager>(system);
|
||||
server_manager->RegisterNamedService("ulsf:u", std::make_shared<ULSF_U>(system));
|
||||
server_manager->RegisterNamedService("ulsf:p", std::make_shared<ULSF_P>(system));
|
||||
|
||||
server_manager->RegisterNamedService("avm", std::make_shared<AVM>(system));
|
||||
server_manager->RegisterNamedService("wlan", std::make_shared<WLAN>(system));
|
||||
ServerManager::RunServer(std::move(server_manager));
|
||||
}
|
||||
|
||||
}
|
||||
28
src/core/hle/service/ulsf/ulsf.h
Normal file
28
src/core/hle/service/ulsf/ulsf.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::ULSF {
|
||||
|
||||
struct ULauncherVersion {
|
||||
u8 major;
|
||||
u8 minor;
|
||||
u8 micro;
|
||||
};
|
||||
|
||||
class ULSF_U final : public ServiceFramework<ULSF_U> {
|
||||
public:
|
||||
explicit ULSF_U(Core::System& system_);
|
||||
~ULSF_U();
|
||||
//Result GetVersion(Out<ULauncherVersion> out_version);
|
||||
void GetVersion(HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
void LoopProcess(Core::System& system);
|
||||
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
#include "core/file_sys/content_archive.h"
|
||||
#include "core/file_sys/control_metadata.h"
|
||||
#include "core/file_sys/patch_manager.h"
|
||||
#include "core/file_sys/program_metadata.h"
|
||||
#include "core/file_sys/romfs_factory.h"
|
||||
#include "core/hle/kernel/k_page_table.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
|
|
@ -204,7 +205,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
|
|||
|
||||
const bool should_pass_arguments = std::strcmp(module, "rtld") == 0;
|
||||
const auto tentative_next_load_addr = AppLoader_NSO::LoadModule(
|
||||
process, system, *module_file, code_size, should_pass_arguments, false, {},
|
||||
process, system, *module_file, code_size, should_pass_arguments, false, nullptr, metadata, {},
|
||||
patch_ctx.GetPatchers(), patch_ctx.GetLastIndex());
|
||||
if (!tentative_next_load_addr) {
|
||||
return {ResultStatus::ErrorLoadingNSO, {}};
|
||||
|
|
@ -251,8 +252,9 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
|
|||
|
||||
const VAddr load_addr{next_load_addr};
|
||||
const bool should_pass_arguments = std::strcmp(module, "rtld") == 0;
|
||||
FileSys::ProgramMetadata tmp_metadata{};
|
||||
const auto tentative_next_load_addr = AppLoader_NSO::LoadModule(
|
||||
process, system, *module_file, load_addr, should_pass_arguments, true, pm,
|
||||
process, system, *module_file, load_addr, should_pass_arguments, true, nullptr, metadata, pm,
|
||||
patch_ctx.GetPatchers(), patch_ctx.GetIndex(i));
|
||||
if (!tentative_next_load_addr) {
|
||||
return {ResultStatus::ErrorLoadingNSO, {}};
|
||||
|
|
|
|||
|
|
@ -17,10 +17,14 @@
|
|||
#include "common/swap.h"
|
||||
#include "core/core.h"
|
||||
#include "core/file_sys/patch_manager.h"
|
||||
#include "core/file_sys/romfs_factory.h"
|
||||
#include "core/file_sys/vfs/vfs_types.h"
|
||||
#include "core/hle/kernel/code_set.h"
|
||||
#include "core/hle/kernel/k_page_table.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_thread.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/loader/loader.h"
|
||||
#include "core/loader/nso.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
|
|
@ -66,7 +70,7 @@ FileType AppLoader_NSO::IdentifyType(const FileSys::VirtualFile& in_file) {
|
|||
return FileType::NSO;
|
||||
}
|
||||
|
||||
std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core::System& system, const FileSys::VfsFile& nso_file, VAddr load_base, bool should_pass_arguments, bool load_into_process, std::optional<FileSys::PatchManager> pm, std::vector<Core::NCE::Patcher>* patches, s32 patch_index) {
|
||||
std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core::System& system, const FileSys::VfsFile& nso_file, const VAddr load_base, const bool should_pass_arguments, const bool load_into_process, VAddr* out_load_base, FileSys::ProgramMetadata metadata, std::optional<FileSys::PatchManager> pm, std::vector<Core::NCE::Patcher>* patches, s32 patch_index) {
|
||||
if (nso_file.GetSize() < sizeof(NSOHeader))
|
||||
return std::nullopt;
|
||||
NSOHeader nso_header{};
|
||||
|
|
@ -216,9 +220,19 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core::
|
|||
}
|
||||
}
|
||||
|
||||
const bool is_hbl = true;
|
||||
if (process
|
||||
.LoadFromMetadata(metadata, image_size, 0, 0, is_hbl)
|
||||
.IsError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto const new_load_base = process.GetEntryPoint().GetValue();
|
||||
if (out_load_base)
|
||||
*out_load_base = new_load_base; // no change
|
||||
// Load codeset for current process
|
||||
process.LoadModule(std::move(codeset), load_base);
|
||||
return load_base + image_size;
|
||||
process.LoadModule(std::move(codeset), new_load_base);
|
||||
return new_load_base + image_size;
|
||||
}
|
||||
|
||||
AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::KProcess& process, Core::System& system) {
|
||||
|
|
@ -226,20 +240,34 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::KProcess& process, Core::S
|
|||
return {ResultStatus::ErrorAlreadyLoaded, {}};
|
||||
}
|
||||
|
||||
modules.clear();
|
||||
FileSys::VirtualFile npdm_file{};
|
||||
metadata = FileSys::ProgramMetadata::GetDefault();
|
||||
if (auto const dir = file->GetContainingDirectory()) {
|
||||
npdm_file = dir->GetFile("main.npdm");
|
||||
if (npdm_file) {
|
||||
metadata.Load(npdm_file);
|
||||
}
|
||||
}
|
||||
|
||||
modules.clear();
|
||||
// Load module
|
||||
const VAddr base_address = GetInteger(process.GetEntryPoint());
|
||||
if (!LoadModule(process, system, *file, base_address, true, true)) {
|
||||
VAddr base_address = GetInteger(process.GetEntryPoint());
|
||||
if (!LoadModule(process, system, *file, base_address, true, true, &base_address, metadata)) {
|
||||
return {ResultStatus::ErrorLoadingNSO, {}};
|
||||
}
|
||||
|
||||
modules.insert_or_assign(base_address, file->GetName());
|
||||
LOG_DEBUG(Loader, "loaded module {} @ {:#X}", file->GetName(), base_address);
|
||||
|
||||
if (npdm_file) {
|
||||
LOG_WARNING(Loader, "creating associated rom-fs factories for likely standalone NSO");
|
||||
u64 program_id{};
|
||||
ReadProgramId(program_id);
|
||||
system.GetFileSystemController().RegisterProcess(process.GetProcessId(), program_id, std::make_unique<FileSys::RomFSFactory>(*this, system.GetContentProvider(), system.GetFileSystemController()));
|
||||
}
|
||||
|
||||
is_loaded = true;
|
||||
return {ResultStatus::Success, LoadParameters{Kernel::KThread::DefaultThreadPriority,
|
||||
Core::Memory::DEFAULT_STACK_SIZE}};
|
||||
return {ResultStatus::Success, LoadParameters{Kernel::KThread::DefaultThreadPriority, Core::Memory::DEFAULT_STACK_SIZE}};
|
||||
}
|
||||
|
||||
ResultStatus AppLoader_NSO::ReadNSOModules(Modules& out_modules) {
|
||||
|
|
@ -247,4 +275,18 @@ ResultStatus AppLoader_NSO::ReadNSOModules(Modules& out_modules) {
|
|||
return ResultStatus::Success;
|
||||
}
|
||||
|
||||
ResultStatus AppLoader_NSO::ReadProgramId(u64& out_program_id) {
|
||||
if (metadata.GetTitleID() == 0)
|
||||
return ResultStatus::ErrorNoControl;
|
||||
out_program_id = metadata.GetTitleID();
|
||||
return ResultStatus::Success;
|
||||
}
|
||||
|
||||
ResultStatus AppLoader_NSO::ReadTitle(std::string& out_title) {
|
||||
auto const raw_name = metadata.GetName();
|
||||
out_title.resize(raw_name.size());
|
||||
std::memcpy(out_title.data(), raw_name.data(), raw_name.size());
|
||||
return ResultStatus::Success;
|
||||
}
|
||||
|
||||
} // namespace Loader
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -9,6 +12,7 @@
|
|||
#include "common/common_types.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/file_sys/patch_manager.h"
|
||||
#include "core/file_sys/program_metadata.h"
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
namespace Core {
|
||||
|
|
@ -90,18 +94,20 @@ public:
|
|||
}
|
||||
|
||||
static std::optional<VAddr> LoadModule(Kernel::KProcess& process, Core::System& system,
|
||||
const FileSys::VfsFile& nso_file, VAddr load_base,
|
||||
bool should_pass_arguments, bool load_into_process,
|
||||
std::optional<FileSys::PatchManager> pm = {},
|
||||
std::vector<Core::NCE::Patcher>* patches = nullptr,
|
||||
s32 patch_index = -1);
|
||||
const FileSys::VfsFile& nso_file, const VAddr load_base,
|
||||
const bool should_pass_arguments, const bool load_into_process, VAddr* out_load_base,
|
||||
FileSys::ProgramMetadata metadata,
|
||||
std::optional<FileSys::PatchManager> pm = {}, std::vector<Core::NCE::Patcher>* patches = nullptr, s32 patch_index = -1);
|
||||
|
||||
LoadResult Load(Kernel::KProcess& process, Core::System& system) override;
|
||||
|
||||
ResultStatus ReadNSOModules(Modules& out_modules) override;
|
||||
ResultStatus ReadProgramId(u64& out_program_id) override;
|
||||
ResultStatus ReadTitle(std::string& title) override;
|
||||
|
||||
private:
|
||||
Modules modules;
|
||||
FileSys::ProgramMetadata metadata;
|
||||
};
|
||||
|
||||
} // namespace Loader
|
||||
|
|
|
|||
|
|
@ -512,11 +512,12 @@ MainWindow::MainWindow(bool has_broken_vulkan)
|
|||
return;
|
||||
}
|
||||
|
||||
QString game_path;
|
||||
QString game_path{};
|
||||
bool should_launch_qlaunch = false;
|
||||
bool should_launch_hlaunch = false;
|
||||
bool should_launch_hlaunch_uloader = false;
|
||||
bool should_launch_ulaunch = false;
|
||||
bool should_launch_setup = false;
|
||||
bool has_gamepath = false;
|
||||
bool is_fullscreen = false;
|
||||
|
||||
// Preserves drag/drop functionality
|
||||
|
|
@ -550,7 +551,6 @@ MainWindow::MainWindow(bool has_broken_vulkan)
|
|||
} else if (args[i] == QStringLiteral("-g") && i < args.size() - 1) {
|
||||
// Launch game at path
|
||||
game_path = args[++i];
|
||||
has_gamepath = true;
|
||||
} else if (args[i] == QStringLiteral("-input-profile") && i < args.size() - 1) {
|
||||
auto& players = Settings::values.players.GetValue();
|
||||
players[0].profile_name = args[++i].toStdString();
|
||||
|
|
@ -558,16 +558,19 @@ MainWindow::MainWindow(bool has_broken_vulkan)
|
|||
should_launch_qlaunch = true;
|
||||
} else if (args[i] == QStringLiteral("-hlaunch")) {
|
||||
should_launch_hlaunch = true;
|
||||
} else if (args[i] == QStringLiteral("-hlaunch-uloader")) {
|
||||
should_launch_hlaunch_uloader = true;
|
||||
} else if (args[i] == QStringLiteral("-ulaunch")) {
|
||||
should_launch_ulaunch = true;
|
||||
} else if (args[i] == QStringLiteral("-setup")) {
|
||||
should_launch_setup = true;
|
||||
} else {
|
||||
game_path = args[i];
|
||||
has_gamepath = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Override fullscreen setting if gamepath or argument is provided
|
||||
if (has_gamepath || is_fullscreen) {
|
||||
if (!game_path.isEmpty() || is_fullscreen) {
|
||||
ui->action_Fullscreen->setChecked(is_fullscreen);
|
||||
}
|
||||
|
||||
|
|
@ -580,8 +583,22 @@ MainWindow::MainWindow(bool has_broken_vulkan)
|
|||
LaunchFirmwareApplet(u64(Service::AM::AppletProgramId::QLaunch), std::nullopt);
|
||||
} else if (should_launch_hlaunch) {
|
||||
std::filesystem::path const sd_dir = Common::FS::GetEdenPathString(Common::FS::EdenPath::SDMCDir);
|
||||
auto const hbl_path = (sd_dir / "atmosphere" / "hbl.nsp").string();
|
||||
BootGame(QString::fromStdString(hbl_path), ApplicationAppletParameters());
|
||||
auto const path = (sd_dir / "atmosphere" / "hbl.nsp").string();
|
||||
BootGame(QString::fromStdString(path), ApplicationAppletParameters());
|
||||
} else if (should_launch_hlaunch_uloader) {
|
||||
std::filesystem::path const sd_dir = Common::FS::GetEdenPathString(Common::FS::EdenPath::SDMCDir);
|
||||
auto const path = (sd_dir / "ulaunch" / "bin" / "uLoader" / "application" / "main").string();
|
||||
auto params = ApplicationAppletParameters();
|
||||
params.launch_type = Service::AM::LaunchType::FrontendUlaunchInitiated;
|
||||
BootGame(QString::fromStdString(path), params);
|
||||
} else if (should_launch_ulaunch) {
|
||||
std::filesystem::path const sd_dir = Common::FS::GetEdenPathString(Common::FS::EdenPath::SDMCDir);
|
||||
auto const path = (sd_dir / "ulaunch" / "bin" / "uMenu" / "main").string();
|
||||
auto const program_id = 0x010000000000FFFF;
|
||||
auto const applet_id = Service::AM::AppletId::UlauncherUmenu;
|
||||
auto params = LibraryAppletParameters(program_id, applet_id);
|
||||
QtCommon::system->GetFrontendAppletHolder().SetCurrentAppletId(applet_id);
|
||||
BootGame(QString::fromStdString(path), params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2779,7 +2796,7 @@ void MainWindow::OnMenuLoadFolder() {
|
|||
|
||||
const QDir dir{dir_path};
|
||||
const QStringList matching_main = dir.entryList({QStringLiteral("main")}, QDir::Files);
|
||||
if (matching_main.size() == 1) {
|
||||
if (matching_main.size() > 0) {
|
||||
BootGame(dir.path() + QDir::separator() + matching_main[0], ApplicationAppletParameters());
|
||||
} else {
|
||||
QMessageBox::warning(this, tr("Invalid Directory Selected"),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue