Added (incomplete) stubs to allow for booting the v18.0.0 firmware

This commit is contained in:
Jarrod Norwell 2024-04-12 17:45:07 +08:00
parent edd7896018
commit 0f2a1f3f04
25 changed files with 166 additions and 15 deletions

View file

@ -165,6 +165,7 @@ Result KPageTableBase::InitializeForKernel(bool is_64_bit, KVirtualAddress start
m_kernel_map_region_end = 0;
m_alias_code_region_start = 0;
m_alias_code_region_end = 0;
m_reserved_region_extra_size = 0;
m_code_region_start = 0;
m_code_region_end = 0;
m_max_heap_size = 0;
@ -253,6 +254,15 @@ Result KPageTableBase::InitializeForProcess(Svc::CreateProcessFlag as_type, bool
m_alias_code_region_end = m_code_region_end;
process_code_start = Common::AlignDown(GetInteger(code_address), RegionAlignment);
process_code_end = Common::AlignUp(GetInteger(code_address) + code_size, RegionAlignment);
// TODO: (jarrodnorwell)
// [switchbrew.org][0] Address space type must be 39-bit
// [switchbrew.org][1] System resource size must be > 0
// [switchbrew.org][2] KTargetSystem::IsDebugMode() must be true
if (as_type == Svc::CreateProcessFlag::EnableReservedRegionExtraSize) {
m_reserved_region_extra_size = GetAddressSpaceSize() / 8;
alias_region_size += alias_region_size;
}
} else {
stack_region_size = 0;
kernel_map_region_size = 0;

View file

@ -208,6 +208,7 @@ private:
size_t m_mapped_unsafe_physical_memory{};
size_t m_mapped_insecure_memory{};
size_t m_mapped_ipc_server_memory{};
size_t m_reserved_region_extra_size{};
mutable KLightLock m_general_lock;
mutable KLightLock m_map_physical_memory_lock;
KLightLock m_device_map_lock;
@ -694,6 +695,9 @@ public:
size_t GetAliasCodeRegionSize() const {
return m_alias_code_region_end - m_alias_code_region_start;
}
size_t GetReservedRegionExtraSize() const {
return m_reserved_region_extra_size;
}
size_t GetNormalMemorySize() const {
// Lock the table.

View file

@ -422,6 +422,9 @@ public:
size_t GetAliasCodeRegionSize() const {
return m_page_table.GetAliasCodeRegionSize();
}
size_t GetReservedRegionExtraSize() const {
return m_page_table.GetReservedRegionExtraSize();
}
size_t GetNormalMemorySize() const {
return m_page_table.GetNormalMemorySize();

View file

@ -37,7 +37,8 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
case InfoType::TotalNonSystemMemorySize:
case InfoType::UsedNonSystemMemorySize:
case InfoType::IsApplication:
case InfoType::FreeThreadCount: {
case InfoType::FreeThreadCount:
case InfoType::ReservedRegionExtraSize: {
R_UNLESS(info_sub_id == 0, ResultInvalidEnumValue);
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
@ -134,6 +135,10 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
}
R_SUCCEED();
case InfoType::ReservedRegionExtraSize:
*result = process->GetPageTable().GetReservedRegionExtraSize();
R_SUCCEED();
default:
break;
}

View file

@ -153,6 +153,7 @@ enum class InfoType : u32 {
ThreadTickCount = 25,
IsSvcPermitted = 26,
IoRegionHint = 27,
ReservedRegionExtraSize = 28,
MesosphereMeta = 65000,
MesosphereCurrentProcess = 65001,
@ -642,9 +643,13 @@ enum class CreateProcessFlag : u32 {
// 11.x+ DisableDeviceAddressSpaceMerge.
DisableDeviceAddressSpaceMerge = (1 << 12),
// 18.x+ EnableReservedRegionExtraSize.
EnableReservedRegionExtraSize = (1 << 13),
// Mask of all flags.
All = Is64Bit | AddressSpaceMask | EnableDebug | EnableAslr | IsApplication |
PoolPartitionMask | OptimizeMemoryAllocation | DisableDeviceAddressSpaceMerge,
PoolPartitionMask | OptimizeMemoryAllocation | DisableDeviceAddressSpaceMerge |
EnableReservedRegionExtraSize,
};
DECLARE_ENUM_FLAG_OPERATORS(CreateProcessFlag);

View file

@ -99,6 +99,7 @@ public:
{140, nullptr, "GetNetworkServiceLicenseCache"}, // 5.0.0+
{141, nullptr, "RefreshNetworkServiceLicenseCacheAsync"}, // 5.0.0+
{142, nullptr, "RefreshNetworkServiceLicenseCacheAsyncIfSecondsElapsed"}, // 5.0.0+
{143, nullptr, "GetNetworkServiceLicenseCacheEx"}, // 15.0.0+
{150, nullptr, "CreateAuthorizationRequest"},
{160, nullptr, "RequiresUpdateNetworkServiceAccountIdTokenCache"},
{161, nullptr, "RequireReauthenticationOfNetworkServiceAccount"},
@ -326,7 +327,7 @@ public:
{11, &IProfileCommon::LoadImage, "LoadImage"},
{20, nullptr, "GetLargeImageSize"}, // 18.0.0+
{21, nullptr, "LoadLargeImage"}, // 18.0.0+
{30, nullptr, "GetImageId"} // 18.0.0+
{30, &IProfileCommon::GetImageId, "GetImageId"} // 18.0.0+
};
// clang-format on
@ -405,6 +406,14 @@ protected:
rb.Push(static_cast<u32>(buffer.size()));
}
void GetImageId(HLERequestContext& ctx) {
LOG_DEBUG(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(0);
}
void GetImageSize(HLERequestContext& ctx) {
LOG_DEBUG(Service_ACC, "called");
IPC::ResponseBuilder rb{ctx, 3};

View file

@ -38,7 +38,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_, std::shared_ptr<Ap
{30, nullptr, "GetHomeButtonReaderLockAccessor"},
{31, &ICommonStateGetter::GetReaderLockAccessorEx, "GetReaderLockAccessorEx"},
{32, nullptr, "GetWriterLockAccessorEx"},
{40, nullptr, "GetCradleFwVersion"},
{40, &ICommonStateGetter::GetCradleFwVersion, "GetCradleFwVersion"},
{50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"},
{51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"},
{52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"},
@ -170,6 +170,13 @@ void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) {
rb.PushCopyObjects(applet->sleep_lock_event.GetHandle());
}
void ICommonStateGetter::GetCradleFwVersion(HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");

View file

@ -58,6 +58,7 @@ private:
void GetOperationMode(HLERequestContext& ctx);
void GetPerformanceMode(HLERequestContext& ctx);
void GetBootMode(HLERequestContext& ctx);
void GetCradleFwVersion(HLERequestContext& ctx);
void IsVrModeEnabled(HLERequestContext& ctx);
void SetVrModeEnabled(HLERequestContext& ctx);
void SetLcdBacklighOffEnabled(HLERequestContext& ctx);

View file

@ -38,7 +38,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_, std::shared_ptr<Ap
{30, nullptr, "GetHomeButtonReaderLockAccessor"},
{31, D<&ICommonStateGetter::GetReaderLockAccessorEx>, "GetReaderLockAccessorEx"},
{32, D<&ICommonStateGetter::GetWriterLockAccessorEx>, "GetWriterLockAccessorEx"},
{40, nullptr, "GetCradleFwVersion"},
{40, D<&ICommonStateGetter::GetCradleFwVersion>, "GetCradleFwVersion"},
{50, D<&ICommonStateGetter::IsVrModeEnabled>, "IsVrModeEnabled"},
{51, D<&ICommonStateGetter::SetVrModeEnabled>, "SetVrModeEnabled"},
{52, D<&ICommonStateGetter::SetLcdBacklighOffEnabled>, "SetLcdBacklighOffEnabled"},
@ -161,6 +161,11 @@ Result ICommonStateGetter::GetBootMode(Out<PM::SystemBootMode> out_boot_mode) {
R_SUCCEED();
}
Result ICommonStateGetter::GetCradleFwVersion() {
LOG_WARNING(Service_AM, "(STUBBED) called");
R_SUCCEED();
}
Result ICommonStateGetter::IsVrModeEnabled(Out<bool> out_is_vr_mode_enabled) {
LOG_DEBUG(Service_AM, "called");

View file

@ -38,6 +38,7 @@ private:
Result GetOperationMode(Out<OperationMode> out_operation_mode);
Result GetPerformanceMode(Out<APM::PerformanceMode> out_performance_mode);
Result GetBootMode(Out<PM::SystemBootMode> out_boot_mode);
Result GetCradleFwVersion();
Result IsVrModeEnabled(Out<bool> out_is_vr_mode_enabled);
Result SetVrModeEnabled(bool is_vr_mode_enabled);
Result SetLcdBacklighOffEnabled(bool is_lcd_backlight_off_enabled);

View file

@ -9,7 +9,7 @@ namespace Service::News {
INewsService::INewsService(Core::System& system_) : ServiceFramework{system_, "INewsService"} {
// clang-format off
static const FunctionInfo functions[] = {
{10100, nullptr, "PostLocalNews"},
{10100, D<&INewsService::PostLocalNews>, "PostLocalNews"},
{20100, nullptr, "SetPassphrase"},
{30100, D<&INewsService::GetSubscriptionStatus>, "GetSubscriptionStatus"},
{30101, nullptr, "GetTopicList"},
@ -36,6 +36,11 @@ INewsService::INewsService(Core::System& system_) : ServiceFramework{system_, "I
INewsService::~INewsService() = default;
Result INewsService::PostLocalNews() {
LOG_WARNING(Service_BCAT, "(STUBBED) called");
R_SUCCEED();
}
Result INewsService::GetSubscriptionStatus(Out<u32> out_status,
InBuffer<BufferAttr_HipcPointer> buffer_data) {
LOG_WARNING(Service_BCAT, "(STUBBED) called, buffer_size={}", buffer_data.size());

View file

@ -18,6 +18,8 @@ public:
~INewsService() override;
private:
Result PostLocalNews();
Result GetSubscriptionStatus(Out<u32> out_status, InBuffer<BufferAttr_HipcPointer> buffer_data);
Result IsSystemUpdateRequired(Out<bool> out_is_system_update_required);

View file

@ -67,7 +67,7 @@ FSP_SRV::FSP_SRV(Core::System& system_)
{24, nullptr, "RegisterSaveDataFileSystemAtomicDeletion"},
{25, nullptr, "DeleteSaveDataFileSystemBySaveDataSpaceId"},
{26, nullptr, "FormatSdCardDryRun"},
{27, nullptr, "IsExFatSupported"},
{27, D<&FSP_SRV::IsExFatSupported>, "IsExFatSupported"},
{28, nullptr, "DeleteSaveDataFileSystemBySaveDataAttribute"},
{30, nullptr, "OpenGameCardStorage"},
{31, nullptr, "OpenGameCardFileSystem"},
@ -247,6 +247,11 @@ Result FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId(
save_struct));
}
Result FSP_SRV::IsExFatSupported(bool is_exfat_supported) {
LOG_INFO(Service_FS, "(STUBBED) called.");
R_SUCCEED();
}
Result FSP_SRV::OpenSaveDataFileSystem(OutInterface<IFileSystem> out_interface,
FileSys::SaveDataSpaceId space_id,
FileSys::SaveDataAttribute attribute) {

View file

@ -55,6 +55,7 @@ private:
FileSys::SaveDataAttribute save_struct, u128 uid);
Result CreateSaveDataFileSystemBySystemSaveDataId(
FileSys::SaveDataAttribute save_struct, FileSys::SaveDataCreationInfo save_create_struct);
Result IsExFatSupported(bool is_exfat_supported);
Result OpenSaveDataFileSystem(OutInterface<IFileSystem> out_interface,
FileSys::SaveDataSpaceId space_id,
FileSys::SaveDataAttribute attribute);

View file

@ -756,7 +756,7 @@ FSP_SRV::FSP_SRV(Core::System& system_)
{24, nullptr, "RegisterSaveDataFileSystemAtomicDeletion"},
{25, nullptr, "DeleteSaveDataFileSystemBySaveDataSpaceId"},
{26, nullptr, "FormatSdCardDryRun"},
{27, nullptr, "IsExFatSupported"},
{27, &FSP_SRV::IsExFatSupported, "IsExFatSupported"},
{28, nullptr, "DeleteSaveDataFileSystemBySaveDataAttribute"},
{30, nullptr, "OpenGameCardStorage"},
{31, nullptr, "OpenGameCardFileSystem"},
@ -946,6 +946,14 @@ void FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId(HLERequestContext& ctx)
rb.Push(ResultSuccess);
}
void FSP_SRV::IsExFatSupported(HLERequestContext& ctx) {
LOG_INFO(Service_FS, "(STUBBED) called.");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(0);
}
void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};

View file

@ -43,6 +43,7 @@ private:
void OpenSdCardFileSystem(HLERequestContext& ctx);
void CreateSaveDataFileSystem(HLERequestContext& ctx);
void CreateSaveDataFileSystemBySystemSaveDataId(HLERequestContext& ctx);
void IsExFatSupported(HLERequestContext& ctx);
void OpenSaveDataFileSystem(HLERequestContext& ctx);
void OpenSaveDataFileSystemBySystemSaveDataId(HLERequestContext& ctx);
void OpenReadOnlySaveDataFileSystem(HLERequestContext& ctx);

View file

@ -419,6 +419,14 @@ void IGeneralService::GetCurrentNetworkProfile(HLERequestContext& ctx) {
rb.Push(ResultSuccess);
}
void IGeneralService::EnumerateNetworkInterfaces(HLERequestContext& ctx) {
for (const auto& interface : Network::GetAvailableNetworkInterfaces())
LOG_WARNING(Service_NIFM, "(STUBBED) called, interface={}", interface.name);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void IGeneralService::RemoveNetworkProfile(HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called");
@ -565,6 +573,15 @@ void IGeneralService::IsAnyForegroundRequestAccepted(HLERequestContext& ctx) {
rb.Push<u8>(is_accepted);
}
void IGeneralService::GetSsidListVersion(HLERequestContext& ctx) {
const u32 ssid = 1;
LOG_WARNING(Service_NIFM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u64>(ssid);
}
IGeneralService::IGeneralService(Core::System& system_)
: ServiceFramework{system_, "IGeneralService"}, network{system_.GetRoomNetwork()} {
// clang-format off
@ -573,7 +590,7 @@ IGeneralService::IGeneralService(Core::System& system_)
{2, &IGeneralService::CreateScanRequest, "CreateScanRequest"},
{4, &IGeneralService::CreateRequest, "CreateRequest"},
{5, &IGeneralService::GetCurrentNetworkProfile, "GetCurrentNetworkProfile"},
{6, nullptr, "EnumerateNetworkInterfaces"},
{6, &IGeneralService::EnumerateNetworkInterfaces, "EnumerateNetworkInterfaces"},
{7, nullptr, "EnumerateNetworkProfiles"},
{8, nullptr, "GetNetworkProfile"},
{9, nullptr, "SetNetworkProfile"},
@ -592,7 +609,7 @@ IGeneralService::IGeneralService(Core::System& system_)
{22, &IGeneralService::IsAnyForegroundRequestAccepted, "IsAnyForegroundRequestAccepted"},
{23, nullptr, "PutToSleep"},
{24, nullptr, "WakeUp"},
{25, nullptr, "GetSsidListVersion"},
{25, &IGeneralService::GetSsidListVersion, "GetSsidListVersion"},
{26, nullptr, "SetExclusiveClient"},
{27, nullptr, "GetDefaultIpSetting"},
{28, nullptr, "SetDefaultIpSetting"},

View file

@ -27,6 +27,7 @@ private:
void CreateScanRequest(HLERequestContext& ctx);
void CreateRequest(HLERequestContext& ctx);
void GetCurrentNetworkProfile(HLERequestContext& ctx);
void EnumerateNetworkInterfaces(HLERequestContext& ctx);
void RemoveNetworkProfile(HLERequestContext& ctx);
void GetCurrentIpAddress(HLERequestContext& ctx);
void CreateTemporaryNetworkProfile(HLERequestContext& ctx);
@ -36,6 +37,7 @@ private:
void IsEthernetCommunicationEnabled(HLERequestContext& ctx);
void IsAnyInternetRequestAccepted(HLERequestContext& ctx);
void IsAnyForegroundRequestAccepted(HLERequestContext& ctx);
void GetSsidListVersion(HLERequestContext& ctx);
Network::RoomNetwork& network;
};

View file

@ -25,7 +25,7 @@ public:
{5, C<&INpnsSystem::GetReceiveEvent>, "GetReceiveEvent"},
{6, nullptr, "ListenUndelivered"},
{7, nullptr, "GetStateChangeEvent"},
{8, nullptr, "ListenToByName"}, // 18.0.0+
{8, C<&INpnsSystem::ListenToByName>, "ListenToByName"}, // 18.0.0+
{11, nullptr, "SubscribeTopic"},
{12, nullptr, "UnsubscribeTopic"},
{13, nullptr, "QueryIsTopicExist"},
@ -57,10 +57,10 @@ public:
{51, nullptr, "DeleteDigitalTwinKeyValue"}, // 18.0.0+
{101, nullptr, "Suspend"},
{102, nullptr, "Resume"},
{103, nullptr, "GetState"},
{103, C<&INpnsSystem::GetState>, "GetState"},
{104, nullptr, "GetStatistics"},
{105, nullptr, "GetPlayReportRequestEvent"},
{106, nullptr, "GetLastNotifiedTime"}, // 18.0.0+
{106, C<&INpnsSystem::GetLastNotifiedTime>, "GetLastNotifiedTime"}, // 18.0.0+
{107, nullptr, "SetLastNotifiedTime"}, // 18.0.0+
{111, nullptr, "GetJid"},
{112, nullptr, "CreateJid"},
@ -109,6 +109,21 @@ private:
R_SUCCEED();
}
Result ListenToByName() {
LOG_WARNING(Service_AM, "(STUBBED) called");
R_SUCCEED();
}
Result GetState() {
LOG_WARNING(Service_AM, "(STUBBED) called");
R_SUCCEED();
}
Result GetLastNotifiedTime() {
LOG_WARNING(Service_AM, "(STUBBED) called");
R_SUCCEED();
}
KernelHelpers::ServiceContext service_context;
Kernel::KEvent* get_receive_event;
};

View file

@ -786,6 +786,13 @@ void SET_SYS::GetKeyboardLayout(HLERequestContext& ctx) {
rb.Push(static_cast<u32>(selected_keyboard_layout));
}
void SET_SYS::GetRebootlessSystemUpdateVersion(HLERequestContext& ctx) {
LOG_WARNING(Service_SET, "(STUBBED) called.");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void SET_SYS::GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx) {
LOG_WARNING(Service_SET, "called.");
@ -1021,7 +1028,7 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"},
{146, nullptr, "SetConsoleSixAxisSensorAngularVelocityTimeBias"},
{147, nullptr, "GetConsoleSixAxisSensorAngularAcceleration"},
{148, nullptr, "SetConsoleSixAxisSensorAngularAcceleration"},
{149, nullptr, "GetRebootlessSystemUpdateVersion"},
{149, &SET_SYS::GetRebootlessSystemUpdateVersion, "GetRebootlessSystemUpdateVersion"},
{150, &SET_SYS::GetDeviceTimeZoneLocationUpdatedTime, "GetDeviceTimeZoneLocationUpdatedTime"},
{151, &SET_SYS::SetDeviceTimeZoneLocationUpdatedTime, "SetDeviceTimeZoneLocationUpdatedTime"},
{152, &SET_SYS::GetUserSystemClockAutomaticCorrectionUpdatedTime, "GetUserSystemClockAutomaticCorrectionUpdatedTime"},

View file

@ -238,7 +238,7 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_)
{146, nullptr, "SetConsoleSixAxisSensorAngularVelocityTimeBias"},
{147, nullptr, "GetConsoleSixAxisSensorAngularAcceleration"},
{148, nullptr, "SetConsoleSixAxisSensorAngularAcceleration"},
{149, nullptr, "GetRebootlessSystemUpdateVersion"},
{149, C<&ISystemSettingsServer::GetRebootlessSystemUpdateVersion>, "GetRebootlessSystemUpdateVersion"},
{150, C<&ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime>, "GetDeviceTimeZoneLocationUpdatedTime"},
{151, C<&ISystemSettingsServer::SetDeviceTimeZoneLocationUpdatedTime>, "SetDeviceTimeZoneLocationUpdatedTime"},
{152, C<&ISystemSettingsServer::GetUserSystemClockAutomaticCorrectionUpdatedTime>, "GetUserSystemClockAutomaticCorrectionUpdatedTime"},
@ -1198,6 +1198,11 @@ Result ISystemSettingsServer::SetKeyboardLayout(KeyboardLayout keyboard_layout)
R_SUCCEED();
}
Result ISystemSettingsServer::GetRebootlessSystemUpdateVersion() {
LOG_WARNING(Service_SET, "(STUBBED) called.");
R_SUCCEED();
}
Result ISystemSettingsServer::GetDeviceTimeZoneLocationUpdatedTime(
Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point) {
LOG_INFO(Service_SET, "called");

View file

@ -136,6 +136,7 @@ public:
Result SetAppletLaunchFlags(u32 applet_launch_flag);
Result GetKeyboardLayout(Out<KeyboardLayout> out_keyboard_layout);
Result SetKeyboardLayout(KeyboardLayout keyboard_layout);
Result GetRebootlessSystemUpdateVersion();
Result GetDeviceTimeZoneLocationUpdatedTime(
Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point);
Result SetDeviceTimeZoneLocationUpdatedTime(

View file

@ -1593,6 +1593,7 @@ void GMainWindow::ConnectMenuEvents() {
[this]() { OnCabinet(Service::NFP::CabinetMode::StartFormatter); });
connect_menu(ui->action_Load_Mii_Edit, &GMainWindow::OnMiiEdit);
connect_menu(ui->action_Open_Controller_Menu, &GMainWindow::OnOpenControllerMenu);
connect_menu(ui->action_Load_Home_Menu, &GMainWindow::OnHomeMenu);
connect_menu(ui->action_Capture_Screenshot, &GMainWindow::OnCaptureScreenshot);
// TAS
@ -4487,6 +4488,29 @@ void GMainWindow::OnOpenControllerMenu() {
LibraryAppletParameters(ControllerAppletId, Service::AM::AppletId::Controller));
}
void GMainWindow::OnHomeMenu() {
constexpr u64 QLaunchId = static_cast<u64>(Service::AM::AppletProgramId::QLaunch);
auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
if (!bis_system) {
QMessageBox::warning(this, tr("No firmware available"),
tr("Please install the firmware to use the Home Menu."));
return;
}
auto qlaunch_applet_nca = bis_system->GetEntry(QLaunchId, FileSys::ContentRecordType::Program);
if (!qlaunch_applet_nca) {
QMessageBox::warning(this, tr("Home Menu Applet"),
tr("Home Menu is not available. Please reinstall firmware."));
return;
}
system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::QLaunch);
const auto filename = QString::fromStdString((qlaunch_applet_nca->GetFullPath()));
UISettings::values.roms_path = QFileInfo(filename).path().toStdString();
BootGame(filename, LibraryAppletParameters(QLaunchId, Service::AM::AppletId::QLaunch));
}
void GMainWindow::OnCaptureScreenshot() {
if (emu_thread == nullptr || !emu_thread->IsRunning()) {
return;

View file

@ -399,6 +399,7 @@ private slots:
void OnCabinet(Service::NFP::CabinetMode mode);
void OnMiiEdit();
void OnOpenControllerMenu();
void OnHomeMenu();
void OnCaptureScreenshot();
void OnCheckFirmwareDecryption();
void OnLanguageChanged(const QString& locale);

View file

@ -174,6 +174,8 @@
<addaction name="action_Load_Mii_Edit"/>
<addaction name="action_Open_Controller_Menu"/>
<addaction name="separator"/>
<addaction name="action_Load_Home_Menu"/>
<addaction name="separator"/>
<addaction name="action_Capture_Screenshot"/>
<addaction name="menuTAS"/>
</widget>
@ -475,6 +477,11 @@
<string>Install Decryption Keys</string>
</property>
</action>
<action name="action_Load_Home_Menu">
<property name="text">
<string>Open Home Menu</string>
</property>
</action>
</widget>
<resources>
<include location="sudachi.qrc"/>