early-access version 4173
This commit is contained in:
		| @@ -1,7 +1,7 @@ | |||||||
| yuzu emulator early access | yuzu emulator early access | ||||||
| ============= | ============= | ||||||
|  |  | ||||||
| This is the source code for early-access 4172. | This is the source code for early-access 4173. | ||||||
|  |  | ||||||
| ## Legal Notice | ## Legal Notice | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								externals/sse2neon/sse2neon.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								externals/sse2neon/sse2neon.h
									
									
									
									
										vendored
									
									
								
							| @@ -1,3 +1,6 @@ | |||||||
|  | // SPDX-FileCopyrightText: Copyright 2015-2024 SSE2NEON Contributors | ||||||
|  | // SPDX-License-Identifier: MIT | ||||||
|  |  | ||||||
| #ifndef SSE2NEON_H | #ifndef SSE2NEON_H | ||||||
| #define SSE2NEON_H | #define SSE2NEON_H | ||||||
|  |  | ||||||
|   | |||||||
| @@ -401,14 +401,16 @@ add_library(core STATIC | |||||||
|     hle/service/am/am_types.h |     hle/service/am/am_types.h | ||||||
|     hle/service/am/applet.cpp |     hle/service/am/applet.cpp | ||||||
|     hle/service/am/applet.h |     hle/service/am/applet.h | ||||||
|  |     hle/service/am/applet_manager.cpp | ||||||
|     hle/service/am/applet_data_broker.cpp |     hle/service/am/applet_data_broker.cpp | ||||||
|     hle/service/am/applet_data_broker.h |     hle/service/am/applet_data_broker.h | ||||||
|     hle/service/am/applet_manager.cpp |  | ||||||
|     hle/service/am/applet_manager.h |     hle/service/am/applet_manager.h | ||||||
|     hle/service/am/applet_message_queue.cpp |     hle/service/am/button_poller.cpp | ||||||
|     hle/service/am/applet_message_queue.h |     hle/service/am/button_poller.h | ||||||
|     hle/service/am/display_layer_manager.cpp |     hle/service/am/display_layer_manager.cpp | ||||||
|     hle/service/am/display_layer_manager.h |     hle/service/am/display_layer_manager.h | ||||||
|  |     hle/service/am/event_observer.cpp | ||||||
|  |     hle/service/am/event_observer.h | ||||||
|     hle/service/am/frontend/applet_cabinet.cpp |     hle/service/am/frontend/applet_cabinet.cpp | ||||||
|     hle/service/am/frontend/applet_cabinet.h |     hle/service/am/frontend/applet_cabinet.h | ||||||
|     hle/service/am/frontend/applet_controller.cpp |     hle/service/am/frontend/applet_controller.cpp | ||||||
| @@ -434,8 +436,12 @@ add_library(core STATIC | |||||||
|     hle/service/am/hid_registration.h |     hle/service/am/hid_registration.h | ||||||
|     hle/service/am/library_applet_storage.cpp |     hle/service/am/library_applet_storage.cpp | ||||||
|     hle/service/am/library_applet_storage.h |     hle/service/am/library_applet_storage.h | ||||||
|     hle/service/am/process.cpp |     hle/service/am/lifecycle_manager.cpp | ||||||
|     hle/service/am/process.h |     hle/service/am/lifecycle_manager.h | ||||||
|  |     hle/service/am/process_creation.cpp | ||||||
|  |     hle/service/am/process_creation.h | ||||||
|  |     hle/service/am/process_holder.cpp | ||||||
|  |     hle/service/am/process_holder.h | ||||||
|     hle/service/am/service/all_system_applet_proxies_service.cpp |     hle/service/am/service/all_system_applet_proxies_service.cpp | ||||||
|     hle/service/am/service/all_system_applet_proxies_service.h |     hle/service/am/service/all_system_applet_proxies_service.h | ||||||
|     hle/service/am/service/applet_common_functions.cpp |     hle/service/am/service/applet_common_functions.cpp | ||||||
| @@ -486,6 +492,8 @@ add_library(core STATIC | |||||||
|     hle/service/am/service/system_applet_proxy.h |     hle/service/am/service/system_applet_proxy.h | ||||||
|     hle/service/am/service/window_controller.cpp |     hle/service/am/service/window_controller.cpp | ||||||
|     hle/service/am/service/window_controller.h |     hle/service/am/service/window_controller.h | ||||||
|  |     hle/service/am/window_system.cpp | ||||||
|  |     hle/service/am/window_system.h | ||||||
|     hle/service/aoc/addon_content_manager.cpp |     hle/service/aoc/addon_content_manager.cpp | ||||||
|     hle/service/aoc/addon_content_manager.h |     hle/service/aoc/addon_content_manager.h | ||||||
|     hle/service/aoc/purchase_event_manager.cpp |     hle/service/aoc/purchase_event_manager.cpp | ||||||
| @@ -918,6 +926,8 @@ add_library(core STATIC | |||||||
|     hle/service/os/multi_wait_utils.h |     hle/service/os/multi_wait_utils.h | ||||||
|     hle/service/os/mutex.cpp |     hle/service/os/mutex.cpp | ||||||
|     hle/service/os/mutex.h |     hle/service/os/mutex.h | ||||||
|  |     hle/service/os/process.cpp | ||||||
|  |     hle/service/os/process.h | ||||||
|     hle/service/pcie/pcie.cpp |     hle/service/pcie/pcie.cpp | ||||||
|     hle/service/pcie/pcie.h |     hle/service/pcie/pcie.h | ||||||
|     hle/service/pctl/parental_control_service_factory.cpp |     hle/service/pctl/parental_control_service_factory.cpp | ||||||
|   | |||||||
| @@ -3,7 +3,6 @@ | |||||||
|  |  | ||||||
| #include <array> | #include <array> | ||||||
| #include <atomic> | #include <atomic> | ||||||
| #include <exception> |  | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <utility> | #include <utility> | ||||||
|  |  | ||||||
| @@ -20,7 +19,6 @@ | |||||||
| #include "core/cpu_manager.h" | #include "core/cpu_manager.h" | ||||||
| #include "core/debugger/debugger.h" | #include "core/debugger/debugger.h" | ||||||
| #include "core/device_memory.h" | #include "core/device_memory.h" | ||||||
| #include "core/file_sys/bis_factory.h" |  | ||||||
| #include "core/file_sys/fs_filesystem.h" | #include "core/file_sys/fs_filesystem.h" | ||||||
| #include "core/file_sys/patch_manager.h" | #include "core/file_sys/patch_manager.h" | ||||||
| #include "core/file_sys/registered_cache.h" | #include "core/file_sys/registered_cache.h" | ||||||
| @@ -38,6 +36,7 @@ | |||||||
| #include "core/hle/service/acc/profile_manager.h" | #include "core/hle/service/acc/profile_manager.h" | ||||||
| #include "core/hle/service/am/applet_manager.h" | #include "core/hle/service/am/applet_manager.h" | ||||||
| #include "core/hle/service/am/frontend/applets.h" | #include "core/hle/service/am/frontend/applets.h" | ||||||
|  | #include "core/hle/service/am/process_creation.h" | ||||||
| #include "core/hle/service/apm/apm_controller.h" | #include "core/hle/service/apm/apm_controller.h" | ||||||
| #include "core/hle/service/filesystem/filesystem.h" | #include "core/hle/service/filesystem/filesystem.h" | ||||||
| #include "core/hle/service/glue/glue_manager.h" | #include "core/hle/service/glue/glue_manager.h" | ||||||
| @@ -72,30 +71,6 @@ MICROPROFILE_DEFINE(ARM_CPU3, "ARM", "CPU 3", MP_RGB(255, 64, 64)); | |||||||
|  |  | ||||||
| namespace Core { | namespace Core { | ||||||
|  |  | ||||||
| namespace { |  | ||||||
|  |  | ||||||
| FileSys::StorageId GetStorageIdForFrontendSlot( |  | ||||||
|     std::optional<FileSys::ContentProviderUnionSlot> slot) { |  | ||||||
|     if (!slot.has_value()) { |  | ||||||
|         return FileSys::StorageId::None; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     switch (*slot) { |  | ||||||
|     case FileSys::ContentProviderUnionSlot::UserNAND: |  | ||||||
|         return FileSys::StorageId::NandUser; |  | ||||||
|     case FileSys::ContentProviderUnionSlot::SysNAND: |  | ||||||
|         return FileSys::StorageId::NandSystem; |  | ||||||
|     case FileSys::ContentProviderUnionSlot::SDMC: |  | ||||||
|         return FileSys::StorageId::SdCard; |  | ||||||
|     case FileSys::ContentProviderUnionSlot::FrontendManual: |  | ||||||
|         return FileSys::StorageId::Host; |  | ||||||
|     default: |  | ||||||
|         return FileSys::StorageId::None; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| } // Anonymous namespace |  | ||||||
|  |  | ||||||
| FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, | FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, | ||||||
|                                          const std::string& path) { |                                          const std::string& path) { | ||||||
|     // To account for split 00+01+etc files. |     // To account for split 00+01+etc files. | ||||||
| @@ -297,9 +272,6 @@ struct System::Impl { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) { |     SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) { | ||||||
|         /// Reset all glue registrations |  | ||||||
|         arp_manager.ResetAll(); |  | ||||||
|  |  | ||||||
|         telemetry_session = std::make_unique<Core::TelemetrySession>(); |         telemetry_session = std::make_unique<Core::TelemetrySession>(); | ||||||
|  |  | ||||||
|         host1x_core = std::make_unique<Tegra::Host1x::Host1x>(system); |         host1x_core = std::make_unique<Tegra::Host1x::Host1x>(system); | ||||||
| @@ -335,33 +307,17 @@ struct System::Impl { | |||||||
|     SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window, |     SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window, | ||||||
|                             const std::string& filepath, |                             const std::string& filepath, | ||||||
|                             Service::AM::FrontendAppletParameters& params) { |                             Service::AM::FrontendAppletParameters& params) { | ||||||
|         app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath), |  | ||||||
|                                        params.program_id, params.program_index); |  | ||||||
|  |  | ||||||
|         if (!app_loader) { |  | ||||||
|             LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); |  | ||||||
|             return SystemResultStatus::ErrorGetLoader; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (app_loader->ReadProgramId(params.program_id) != Loader::ResultStatus::Success) { |  | ||||||
|             LOG_ERROR(Core, "Failed to find title id for ROM!"); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         std::string name = "Unknown program"; |  | ||||||
|         if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) { |  | ||||||
|             LOG_ERROR(Core, "Failed to read title for ROM!"); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         LOG_INFO(Core, "Loading {} ({})", name, params.program_id); |  | ||||||
|  |  | ||||||
|         InitializeKernel(system); |         InitializeKernel(system); | ||||||
|  |  | ||||||
|         // Create the application process. |         const auto file = GetGameFileFromPath(virtual_filesystem, filepath); | ||||||
|         auto main_process = Kernel::KProcess::Create(system.Kernel()); |  | ||||||
|         Kernel::KProcess::Register(system.Kernel(), main_process); |         // Create the application process | ||||||
|         kernel.AppendNewProcess(main_process); |         Loader::ResultStatus load_result{}; | ||||||
|         kernel.MakeApplicationProcess(main_process); |         std::vector<u8> control; | ||||||
|         const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); |         auto process = | ||||||
|  |             Service::AM::CreateApplicationProcess(control, app_loader, load_result, system, file, | ||||||
|  |                                                   params.program_id, params.program_index); | ||||||
|  |  | ||||||
|         if (load_result != Loader::ResultStatus::Success) { |         if (load_result != Loader::ResultStatus::Success) { | ||||||
|             LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result); |             LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result); | ||||||
|             ShutdownMainProcess(); |             ShutdownMainProcess(); | ||||||
| @@ -370,6 +326,25 @@ struct System::Impl { | |||||||
|                 static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result)); |                 static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result)); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if (!app_loader) { | ||||||
|  |             LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath); | ||||||
|  |             return SystemResultStatus::ErrorGetLoader; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (app_loader->ReadProgramId(params.program_id) != Loader::ResultStatus::Success) { | ||||||
|  |             LOG_ERROR(Core, "Failed to find program id for ROM!"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         std::string name = "Unknown program"; | ||||||
|  |         if (app_loader->ReadTitle(name) != Loader::ResultStatus::Success) { | ||||||
|  |             LOG_ERROR(Core, "Failed to read title for ROM!"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         LOG_INFO(Core, "Loading {} ({:016X}) ...", name, params.program_id); | ||||||
|  |  | ||||||
|  |         // Make the process created be the application | ||||||
|  |         kernel.MakeApplicationProcess(process->GetHandle()); | ||||||
|  |  | ||||||
|         // Set up the rest of the system. |         // Set up the rest of the system. | ||||||
|         SystemResultStatus init_result{SetupForApplicationProcess(system, emu_window)}; |         SystemResultStatus init_result{SetupForApplicationProcess(system, emu_window)}; | ||||||
|         if (init_result != SystemResultStatus::Success) { |         if (init_result != SystemResultStatus::Success) { | ||||||
| @@ -379,7 +354,6 @@ struct System::Impl { | |||||||
|             return init_result; |             return init_result; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         AddGlueRegistrationForProcess(*app_loader, *main_process); |  | ||||||
|         telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); |         telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); | ||||||
|  |  | ||||||
|         // Initialize cheat engine |         // Initialize cheat engine | ||||||
| @@ -387,14 +361,9 @@ struct System::Impl { | |||||||
|             cheat_engine->Initialize(); |             cheat_engine->Initialize(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Register with applet manager. |         // Register with applet manager | ||||||
|         applet_manager.CreateAndInsertByFrontendAppletParameters(main_process->GetProcessId(), |         // All threads are started, begin main process execution, now that we're in the clear | ||||||
|                                                                  params); |         applet_manager.CreateAndInsertByFrontendAppletParameters(std::move(process), params); | ||||||
|  |  | ||||||
|         // All threads are started, begin main process execution, now that we're in the clear. |  | ||||||
|         main_process->Run(load_parameters->main_thread_priority, |  | ||||||
|                           load_parameters->main_thread_stack_size); |  | ||||||
|         main_process->Close(); |  | ||||||
|  |  | ||||||
|         if (Settings::values.gamecard_inserted) { |         if (Settings::values.gamecard_inserted) { | ||||||
|             if (Settings::values.gamecard_current_game) { |             if (Settings::values.gamecard_current_game) { | ||||||
| @@ -466,7 +435,6 @@ struct System::Impl { | |||||||
|         kernel.SuspendEmulation(true); |         kernel.SuspendEmulation(true); | ||||||
|         kernel.CloseServices(); |         kernel.CloseServices(); | ||||||
|         kernel.ShutdownCores(); |         kernel.ShutdownCores(); | ||||||
|         applet_manager.Reset(); |  | ||||||
|         services.reset(); |         services.reset(); | ||||||
|         service_manager.reset(); |         service_manager.reset(); | ||||||
|         fs_controller.Reset(); |         fs_controller.Reset(); | ||||||
| @@ -492,6 +460,9 @@ struct System::Impl { | |||||||
|         // Workarounds |         // Workarounds | ||||||
|         Settings::values.renderer_amdvlk_depth_bias_workaround = false; |         Settings::values.renderer_amdvlk_depth_bias_workaround = false; | ||||||
|  |  | ||||||
|  |         // Reset all glue registrations | ||||||
|  |         arp_manager.ResetAll(); | ||||||
|  |  | ||||||
|         LOG_DEBUG(Core, "Shutdown OK"); |         LOG_DEBUG(Core, "Shutdown OK"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -509,31 +480,6 @@ struct System::Impl { | |||||||
|         return app_loader->ReadTitle(out); |         return app_loader->ReadTitle(out); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void AddGlueRegistrationForProcess(Loader::AppLoader& loader, Kernel::KProcess& process) { |  | ||||||
|         std::vector<u8> nacp_data; |  | ||||||
|         FileSys::NACP nacp; |  | ||||||
|         if (loader.ReadControlData(nacp) == Loader::ResultStatus::Success) { |  | ||||||
|             nacp_data = nacp.GetRawBytes(); |  | ||||||
|         } else { |  | ||||||
|             nacp_data.resize(sizeof(FileSys::RawNACP)); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         Service::Glue::ApplicationLaunchProperty launch{}; |  | ||||||
|         launch.title_id = process.GetProgramId(); |  | ||||||
|  |  | ||||||
|         FileSys::PatchManager pm{launch.title_id, fs_controller, *content_provider}; |  | ||||||
|         launch.version = pm.GetGameVersion().value_or(0); |  | ||||||
|  |  | ||||||
|         // TODO(DarkLordZach): When FSController/Game Card Support is added, if |  | ||||||
|         // current_process_game_card use correct StorageId |  | ||||||
|         launch.base_game_storage_id = GetStorageIdForFrontendSlot(content_provider->GetSlotForEntry( |  | ||||||
|             launch.title_id, FileSys::ContentRecordType::Program)); |  | ||||||
|         launch.update_storage_id = GetStorageIdForFrontendSlot(content_provider->GetSlotForEntry( |  | ||||||
|             FileSys::GetUpdateTitleID(launch.title_id), FileSys::ContentRecordType::Program)); |  | ||||||
|  |  | ||||||
|         arp_manager.Register(launch.title_id, launch, std::move(nacp_data)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void SetStatus(SystemResultStatus new_status, const char* details = nullptr) { |     void SetStatus(SystemResultStatus new_status, const char* details = nullptr) { | ||||||
|         status = new_status; |         status = new_status; | ||||||
|         if (details) { |         if (details) { | ||||||
|   | |||||||
| @@ -1170,6 +1170,7 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: | |||||||
|     // Determine if we are an application. |     // Determine if we are an application. | ||||||
|     if (pool == KMemoryManager::Pool::Application) { |     if (pool == KMemoryManager::Pool::Application) { | ||||||
|         flag |= Svc::CreateProcessFlag::IsApplication; |         flag |= Svc::CreateProcessFlag::IsApplication; | ||||||
|  |         m_is_application = true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // If we are 64-bit, create as such. |     // If we are 64-bit, create as such. | ||||||
|   | |||||||
| @@ -2,19 +2,26 @@ | |||||||
| // SPDX-License-Identifier: GPL-2.0-or-later | // SPDX-License-Identifier: GPL-2.0-or-later | ||||||
|  |  | ||||||
| #include "core/hle/service/am/am.h" | #include "core/hle/service/am/am.h" | ||||||
|  | #include "core/hle/service/am/button_poller.h" | ||||||
|  | #include "core/hle/service/am/event_observer.h" | ||||||
| #include "core/hle/service/am/service/all_system_applet_proxies_service.h" | #include "core/hle/service/am/service/all_system_applet_proxies_service.h" | ||||||
| #include "core/hle/service/am/service/application_proxy_service.h" | #include "core/hle/service/am/service/application_proxy_service.h" | ||||||
|  | #include "core/hle/service/am/window_system.h" | ||||||
| #include "core/hle/service/server_manager.h" | #include "core/hle/service/server_manager.h" | ||||||
|  |  | ||||||
| namespace Service::AM { | namespace Service::AM { | ||||||
|  |  | ||||||
| void LoopProcess(Core::System& system) { | void LoopProcess(Core::System& system) { | ||||||
|  |     WindowSystem window_system(system); | ||||||
|  |     ButtonPoller button_poller(system, window_system); | ||||||
|  |     EventObserver event_observer(system, window_system); | ||||||
|  |  | ||||||
|     auto server_manager = std::make_unique<ServerManager>(system); |     auto server_manager = std::make_unique<ServerManager>(system); | ||||||
|  |  | ||||||
|     server_manager->RegisterNamedService("appletAE", |     server_manager->RegisterNamedService( | ||||||
|                                          std::make_shared<IAllSystemAppletProxiesService>(system)); |         "appletAE", std::make_shared<IAllSystemAppletProxiesService>(system, window_system)); | ||||||
|     server_manager->RegisterNamedService("appletOE", |     server_manager->RegisterNamedService( | ||||||
|                                          std::make_shared<IApplicationProxyService>(system)); |         "appletOE", std::make_shared<IApplicationProxyService>(system, window_system)); | ||||||
|     ServerManager::RunServer(std::move(server_manager)); |     ServerManager::RunServer(std::move(server_manager)); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ namespace Service::AM { | |||||||
|  |  | ||||||
| constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2}; | constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2}; | ||||||
| constexpr Result ResultNoMessages{ErrorModule::AM, 3}; | constexpr Result ResultNoMessages{ErrorModule::AM, 3}; | ||||||
|  | constexpr Result ResultLibraryAppletTerminated{ErrorModule::AM, 22}; | ||||||
| constexpr Result ResultInvalidOffset{ErrorModule::AM, 503}; | constexpr Result ResultInvalidOffset{ErrorModule::AM, 503}; | ||||||
| constexpr Result ResultInvalidStorageType{ErrorModule::AM, 511}; | constexpr Result ResultInvalidStorageType{ErrorModule::AM, 511}; | ||||||
| constexpr Result ResultFatalSectionCountImbalance{ErrorModule::AM, 512}; | constexpr Result ResultFatalSectionCountImbalance{ErrorModule::AM, 512}; | ||||||
|   | |||||||
| @@ -61,12 +61,6 @@ enum class ScreenshotPermission : u32 { | |||||||
|     Disable = 2, |     Disable = 2, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct FocusHandlingMode { |  | ||||||
|     bool notify; |  | ||||||
|     bool background; |  | ||||||
|     bool suspend; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| enum class IdleTimeDetectionExtension : u32 { | enum class IdleTimeDetectionExtension : u32 { | ||||||
|     Disabled = 0, |     Disabled = 0, | ||||||
|     Extended = 1, |     Extended = 1, | ||||||
| @@ -239,7 +233,6 @@ struct ApplicationPlayStatistics { | |||||||
| static_assert(sizeof(ApplicationPlayStatistics) == 0x18, | static_assert(sizeof(ApplicationPlayStatistics) == 0x18, | ||||||
|               "ApplicationPlayStatistics has incorrect size."); |               "ApplicationPlayStatistics has incorrect size."); | ||||||
|  |  | ||||||
| using AppletResourceUserId = u64; |  | ||||||
| using ProgramId = u64; | using ProgramId = u64; | ||||||
|  |  | ||||||
| struct Applet; | struct Applet; | ||||||
|   | |||||||
| @@ -1,27 +1,71 @@ | |||||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||||||
| // SPDX-License-Identifier: GPL-2.0-or-later | // SPDX-License-Identifier: GPL-2.0-or-later | ||||||
|  |  | ||||||
| #include "common/scope_exit.h" |  | ||||||
|  |  | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/hle/service/am/am_results.h" |  | ||||||
| #include "core/hle/service/am/applet.h" | #include "core/hle/service/am/applet.h" | ||||||
| #include "core/hle/service/am/applet_manager.h" | #include "core/hle/service/am/applet_manager.h" | ||||||
|  |  | ||||||
| namespace Service::AM { | namespace Service::AM { | ||||||
|  |  | ||||||
| Applet::Applet(Core::System& system, std::unique_ptr<Process> process_) | Applet::Applet(Core::System& system, std::unique_ptr<Process> process_, bool is_application) | ||||||
|     : context(system, "Applet"), message_queue(system), process(std::move(process_)), |     : context(system, "Applet"), lifecycle_manager(system, context, is_application), | ||||||
|       hid_registration(system, *process), gpu_error_detected_event(context), |       process(std::move(process_)), hid_registration(system, *process), | ||||||
|       friend_invitation_storage_channel_event(context), notification_storage_channel_event(context), |       gpu_error_detected_event(context), friend_invitation_storage_channel_event(context), | ||||||
|       health_warning_disappeared_system_event(context), acquired_sleep_lock_event(context), |       notification_storage_channel_event(context), health_warning_disappeared_system_event(context), | ||||||
|       pop_from_general_channel_event(context), library_applet_launchable_event(context), |       acquired_sleep_lock_event(context), pop_from_general_channel_event(context), | ||||||
|       accumulated_suspended_tick_changed_event(context), sleep_lock_event(context) { |       library_applet_launchable_event(context), accumulated_suspended_tick_changed_event(context), | ||||||
|  |       sleep_lock_event(context), state_changed_event(context) { | ||||||
|  |  | ||||||
|     aruid = process->GetProcessId(); |     aruid.pid = process->GetProcessId(); | ||||||
|     program_id = process->GetProgramId(); |     program_id = process->GetProgramId(); | ||||||
| } | } | ||||||
|  |  | ||||||
| Applet::~Applet() = default; | Applet::~Applet() = default; | ||||||
|  |  | ||||||
|  | void Applet::UpdateSuspensionStateLocked(bool force_message) { | ||||||
|  |     // Remove any forced resumption. | ||||||
|  |     lifecycle_manager.RemoveForceResumeIfPossible(); | ||||||
|  |  | ||||||
|  |     // Check if we're runnable. | ||||||
|  |     const bool curr_activity_runnable = lifecycle_manager.IsRunnable(); | ||||||
|  |     const bool prev_activity_runnable = is_activity_runnable; | ||||||
|  |     const bool was_changed = curr_activity_runnable != prev_activity_runnable; | ||||||
|  |  | ||||||
|  |     if (was_changed) { | ||||||
|  |         if (curr_activity_runnable) { | ||||||
|  |             process->Suspend(false); | ||||||
|  |         } else { | ||||||
|  |             process->Suspend(true); | ||||||
|  |             lifecycle_manager.RequestResumeNotification(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         is_activity_runnable = curr_activity_runnable; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (lifecycle_manager.GetForcedSuspend()) { | ||||||
|  |         // TODO: why is this allowed? | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Signal if the focus state was changed or the process state was changed. | ||||||
|  |     if (lifecycle_manager.UpdateRequestedFocusState() || was_changed || force_message) { | ||||||
|  |         lifecycle_manager.SignalSystemEventIfNeeded(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void Applet::SetInteractibleLocked(bool interactible) { | ||||||
|  |     if (is_interactible == interactible) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     is_interactible = interactible; | ||||||
|  |  | ||||||
|  |     hid_registration.EnableAppletToGetInput(interactible && !lifecycle_manager.GetExitRequested()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void Applet::OnProcessTerminatedLocked() { | ||||||
|  |     is_completed = true; | ||||||
|  |     state_changed_event.Signal(); | ||||||
|  | } | ||||||
|  |  | ||||||
| } // namespace Service::AM | } // namespace Service::AM | ||||||
|   | |||||||
| @@ -3,25 +3,28 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include <deque> | ||||||
| #include <mutex> | #include <mutex> | ||||||
|  |  | ||||||
| #include "common/math_util.h" | #include "common/math_util.h" | ||||||
| #include "core/hle/service/apm/apm_controller.h" | #include "core/hle/service/apm/apm_controller.h" | ||||||
| #include "core/hle/service/caps/caps_types.h" | #include "core/hle/service/caps/caps_types.h" | ||||||
|  | #include "core/hle/service/cmif_types.h" | ||||||
| #include "core/hle/service/kernel_helpers.h" | #include "core/hle/service/kernel_helpers.h" | ||||||
| #include "core/hle/service/os/event.h" | #include "core/hle/service/os/event.h" | ||||||
|  | #include "core/hle/service/os/process.h" | ||||||
| #include "core/hle/service/service.h" | #include "core/hle/service/service.h" | ||||||
|  |  | ||||||
| #include "core/hle/service/am/am_types.h" | #include "core/hle/service/am/am_types.h" | ||||||
| #include "core/hle/service/am/applet_message_queue.h" |  | ||||||
| #include "core/hle/service/am/display_layer_manager.h" | #include "core/hle/service/am/display_layer_manager.h" | ||||||
| #include "core/hle/service/am/hid_registration.h" | #include "core/hle/service/am/hid_registration.h" | ||||||
| #include "core/hle/service/am/process.h" | #include "core/hle/service/am/lifecycle_manager.h" | ||||||
|  | #include "core/hle/service/am/process_holder.h" | ||||||
|  |  | ||||||
| namespace Service::AM { | namespace Service::AM { | ||||||
|  |  | ||||||
| struct Applet { | struct Applet { | ||||||
|     explicit Applet(Core::System& system, std::unique_ptr<Process> process_); |     explicit Applet(Core::System& system, std::unique_ptr<Process> process_, bool is_application); | ||||||
|     ~Applet(); |     ~Applet(); | ||||||
|  |  | ||||||
|     // Lock |     // Lock | ||||||
| @@ -30,11 +33,13 @@ struct Applet { | |||||||
|     // Event creation helper |     // Event creation helper | ||||||
|     KernelHelpers::ServiceContext context; |     KernelHelpers::ServiceContext context; | ||||||
|  |  | ||||||
|     // Applet message queue |     // Lifecycle manager | ||||||
|     AppletMessageQueue message_queue; |     LifecycleManager lifecycle_manager; | ||||||
|  |  | ||||||
|     // Process |     // Process | ||||||
|     std::unique_ptr<Process> process; |     std::unique_ptr<Process> process; | ||||||
|  |     std::optional<ProcessHolder> process_holder; | ||||||
|  |     bool is_process_running{}; | ||||||
|  |  | ||||||
|     // Creation state |     // Creation state | ||||||
|     AppletId applet_id{}; |     AppletId applet_id{}; | ||||||
| @@ -75,11 +80,9 @@ struct Applet { | |||||||
|     bool game_play_recording_supported{}; |     bool game_play_recording_supported{}; | ||||||
|     GamePlayRecordingState game_play_recording_state{GamePlayRecordingState::Disabled}; |     GamePlayRecordingState game_play_recording_state{GamePlayRecordingState::Disabled}; | ||||||
|     bool jit_service_launched{}; |     bool jit_service_launched{}; | ||||||
|     bool is_running{}; |  | ||||||
|     bool application_crash_report_enabled{}; |     bool application_crash_report_enabled{}; | ||||||
|  |  | ||||||
|     // Common state |     // Common state | ||||||
|     FocusState focus_state{}; |  | ||||||
|     bool sleep_lock_enabled{}; |     bool sleep_lock_enabled{}; | ||||||
|     bool vr_mode_enabled{}; |     bool vr_mode_enabled{}; | ||||||
|     bool lcd_backlight_off_enabled{}; |     bool lcd_backlight_off_enabled{}; | ||||||
| @@ -93,15 +96,12 @@ struct Applet { | |||||||
|     // Caller applet |     // Caller applet | ||||||
|     std::weak_ptr<Applet> caller_applet{}; |     std::weak_ptr<Applet> caller_applet{}; | ||||||
|     std::shared_ptr<AppletDataBroker> caller_applet_broker{}; |     std::shared_ptr<AppletDataBroker> caller_applet_broker{}; | ||||||
|  |     std::list<std::shared_ptr<Applet>> child_applets{}; | ||||||
|  |     bool is_completed{}; | ||||||
|  |  | ||||||
|     // Self state |     // Self state | ||||||
|     bool exit_locked{}; |     bool exit_locked{}; | ||||||
|     s32 fatal_section_count{}; |     s32 fatal_section_count{}; | ||||||
|     bool operation_mode_changed_notification_enabled{true}; |  | ||||||
|     bool performance_mode_changed_notification_enabled{true}; |  | ||||||
|     FocusHandlingMode focus_handling_mode{}; |  | ||||||
|     bool restart_message_enabled{}; |  | ||||||
|     bool out_of_focus_suspension_enabled{true}; |  | ||||||
|     Capture::AlbumImageOrientation album_image_orientation{}; |     Capture::AlbumImageOrientation album_image_orientation{}; | ||||||
|     bool handles_request_to_display{}; |     bool handles_request_to_display{}; | ||||||
|     ScreenshotPermission screenshot_permission{}; |     ScreenshotPermission screenshot_permission{}; | ||||||
| @@ -110,6 +110,9 @@ struct Applet { | |||||||
|     u64 suspended_ticks{}; |     u64 suspended_ticks{}; | ||||||
|     bool album_image_taken_notification_enabled{}; |     bool album_image_taken_notification_enabled{}; | ||||||
|     bool record_volume_muted{}; |     bool record_volume_muted{}; | ||||||
|  |     bool is_activity_runnable{}; | ||||||
|  |     bool is_interactible{true}; | ||||||
|  |     bool window_visible{true}; | ||||||
|  |  | ||||||
|     // Events |     // Events | ||||||
|     Event gpu_error_detected_event; |     Event gpu_error_detected_event; | ||||||
| @@ -121,9 +124,15 @@ struct Applet { | |||||||
|     Event library_applet_launchable_event; |     Event library_applet_launchable_event; | ||||||
|     Event accumulated_suspended_tick_changed_event; |     Event accumulated_suspended_tick_changed_event; | ||||||
|     Event sleep_lock_event; |     Event sleep_lock_event; | ||||||
|  |     Event state_changed_event; | ||||||
|  |  | ||||||
|     // Frontend state |     // Frontend state | ||||||
|     std::shared_ptr<Frontend::FrontendApplet> frontend{}; |     std::shared_ptr<Frontend::FrontendApplet> frontend{}; | ||||||
|  |  | ||||||
|  |     // Process state management | ||||||
|  |     void UpdateSuspensionStateLocked(bool force_message); | ||||||
|  |     void SetInteractibleLocked(bool interactible); | ||||||
|  |     void OnProcessTerminatedLocked(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| } // namespace Service::AM | } // namespace Service::AM | ||||||
|   | |||||||
| @@ -44,24 +44,8 @@ Kernel::KReadableEvent* AppletStorageChannel::GetEvent() { | |||||||
|  |  | ||||||
| AppletDataBroker::AppletDataBroker(Core::System& system_) | AppletDataBroker::AppletDataBroker(Core::System& system_) | ||||||
|     : system(system_), context(system_, "AppletDataBroker"), in_data(context), |     : system(system_), context(system_, "AppletDataBroker"), in_data(context), | ||||||
|       interactive_in_data(context), out_data(context), interactive_out_data(context), |       interactive_in_data(context), out_data(context), interactive_out_data(context) {} | ||||||
|       state_changed_event(context), is_completed(false) {} |  | ||||||
|  |  | ||||||
| AppletDataBroker::~AppletDataBroker() = default; | AppletDataBroker::~AppletDataBroker() = default; | ||||||
|  |  | ||||||
| void AppletDataBroker::SignalCompletion() { |  | ||||||
|     { |  | ||||||
|         std::scoped_lock lk{lock}; |  | ||||||
|  |  | ||||||
|         if (is_completed) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         is_completed = true; |  | ||||||
|         state_changed_event.Signal(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     system.GetAppletManager().FocusStateChanged(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| } // namespace Service::AM | } // namespace Service::AM | ||||||
|   | |||||||
| @@ -53,16 +53,6 @@ public: | |||||||
|         return interactive_out_data; |         return interactive_out_data; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Event& GetStateChangedEvent() { |  | ||||||
|         return state_changed_event; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool IsCompleted() const { |  | ||||||
|         return is_completed; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void SignalCompletion(); |  | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     Core::System& system; |     Core::System& system; | ||||||
|     KernelHelpers::ServiceContext context; |     KernelHelpers::ServiceContext context; | ||||||
| @@ -71,10 +61,6 @@ private: | |||||||
|     AppletStorageChannel interactive_in_data; |     AppletStorageChannel interactive_in_data; | ||||||
|     AppletStorageChannel out_data; |     AppletStorageChannel out_data; | ||||||
|     AppletStorageChannel interactive_out_data; |     AppletStorageChannel interactive_out_data; | ||||||
|     Event state_changed_event; |  | ||||||
|  |  | ||||||
|     std::mutex lock; |  | ||||||
|     bool is_completed; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| } // namespace Service::AM | } // namespace Service::AM | ||||||
|   | |||||||
| @@ -13,6 +13,7 @@ | |||||||
| #include "core/hle/service/am/frontend/applet_mii_edit_types.h" | #include "core/hle/service/am/frontend/applet_mii_edit_types.h" | ||||||
| #include "core/hle/service/am/frontend/applet_software_keyboard_types.h" | #include "core/hle/service/am/frontend/applet_software_keyboard_types.h" | ||||||
| #include "core/hle/service/am/service/storage.h" | #include "core/hle/service/am/service/storage.h" | ||||||
|  | #include "core/hle/service/am/window_system.h" | ||||||
| #include "hid_core/hid_types.h" | #include "hid_core/hid_types.h" | ||||||
|  |  | ||||||
| namespace Service::AM { | namespace Service::AM { | ||||||
| @@ -225,49 +226,46 @@ void PushInShowSoftwareKeyboard(Core::System& system, AppletStorageChannel& chan | |||||||
| } // namespace | } // namespace | ||||||
|  |  | ||||||
| AppletManager::AppletManager(Core::System& system) : m_system(system) {} | AppletManager::AppletManager(Core::System& system) : m_system(system) {} | ||||||
| AppletManager::~AppletManager() { | AppletManager::~AppletManager() = default; | ||||||
|     this->Reset(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void AppletManager::InsertApplet(std::shared_ptr<Applet> applet) { |  | ||||||
|     std::scoped_lock lk{m_lock}; |  | ||||||
|  |  | ||||||
|     m_applets.emplace(applet->aruid, std::move(applet)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void AppletManager::TerminateAndRemoveApplet(AppletResourceUserId aruid) { |  | ||||||
|     std::shared_ptr<Applet> applet; |  | ||||||
|     bool should_stop = false; |  | ||||||
|     { |  | ||||||
|         std::scoped_lock lk{m_lock}; |  | ||||||
|  |  | ||||||
|         const auto it = m_applets.find(aruid); |  | ||||||
|         if (it == m_applets.end()) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         applet = it->second; |  | ||||||
|         m_applets.erase(it); |  | ||||||
|  |  | ||||||
|         should_stop = m_applets.empty(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Terminate process. |  | ||||||
|     applet->process->Terminate(); |  | ||||||
|  |  | ||||||
|     // If there were no applets left, stop emulation. |  | ||||||
|     if (should_stop) { |  | ||||||
|         m_system.Exit(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void AppletManager::CreateAndInsertByFrontendAppletParameters( | void AppletManager::CreateAndInsertByFrontendAppletParameters( | ||||||
|     AppletResourceUserId aruid, const FrontendAppletParameters& params) { |     std::unique_ptr<Process> process, const FrontendAppletParameters& params) { | ||||||
|     // TODO: this should be run inside AM so that the events will have a parent process |     { | ||||||
|     // TODO: have am create the guest process |         std::scoped_lock lk{m_lock}; | ||||||
|     auto applet = std::make_shared<Applet>(m_system, std::make_unique<Process>(m_system)); |         m_pending_process = std::move(process); | ||||||
|  |         m_pending_parameters = params; | ||||||
|  |     } | ||||||
|  |     m_cv.notify_all(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void AppletManager::RequestExit() { | ||||||
|  |     std::scoped_lock lk{m_lock}; | ||||||
|  |     if (m_window_system) { | ||||||
|  |         m_window_system->OnExitRequested(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void AppletManager::OperationModeChanged() { | ||||||
|  |     std::scoped_lock lk{m_lock}; | ||||||
|  |     if (m_window_system) { | ||||||
|  |         m_window_system->OnOperationModeChanged(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void AppletManager::SetWindowSystem(WindowSystem* window_system) { | ||||||
|  |     std::unique_lock lk{m_lock}; | ||||||
|  |  | ||||||
|  |     m_window_system = window_system; | ||||||
|  |     if (!m_window_system) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     m_cv.wait(lk, [&] { return m_pending_process != nullptr; }); | ||||||
|  |  | ||||||
|  |     const auto& params = m_pending_parameters; | ||||||
|  |     auto applet = std::make_shared<Applet>(m_system, std::move(m_pending_process), | ||||||
|  |                                            params.applet_id == AppletId::Application); | ||||||
|  |  | ||||||
|     applet->aruid = aruid; |  | ||||||
|     applet->program_id = params.program_id; |     applet->program_id = params.program_id; | ||||||
|     applet->applet_id = params.applet_id; |     applet->applet_id = params.applet_id; | ||||||
|     applet->type = params.applet_type; |     applet->type = params.applet_type; | ||||||
| @@ -322,59 +320,19 @@ void AppletManager::CreateAndInsertByFrontendAppletParameters( | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Applet was started by frontend, so it is foreground. |     // Applet was started by frontend, so it is foreground. | ||||||
|     applet->message_queue.PushMessage(AppletMessage::ChangeIntoForeground); |     applet->lifecycle_manager.SetFocusState(FocusState::InFocus); | ||||||
|     applet->message_queue.PushMessage(AppletMessage::FocusStateChanged); |  | ||||||
|     applet->focus_state = FocusState::InFocus; |  | ||||||
|  |  | ||||||
|     this->InsertApplet(std::move(applet)); |     if (applet->applet_id == AppletId::QLaunch) { | ||||||
| } |         applet->lifecycle_manager.SetFocusHandlingMode(false); | ||||||
|  |         applet->lifecycle_manager.SetOutOfFocusSuspendingEnabled(false); | ||||||
| std::shared_ptr<Applet> AppletManager::GetByAppletResourceUserId(AppletResourceUserId aruid) const { |         m_window_system->TrackApplet(applet, false); | ||||||
|     std::scoped_lock lk{m_lock}; |         m_window_system->RequestHomeMenuToGetForeground(); | ||||||
|  |     } else { | ||||||
|     if (const auto it = m_applets.find(aruid); it != m_applets.end()) { |         m_window_system->TrackApplet(applet, true); | ||||||
|         return it->second; |         m_window_system->RequestApplicationToGetForeground(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return {}; |     applet->process->Run(); | ||||||
| } |  | ||||||
|  |  | ||||||
| void AppletManager::Reset() { |  | ||||||
|     std::scoped_lock lk{m_lock}; |  | ||||||
|  |  | ||||||
|     m_applets.clear(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void AppletManager::RequestExit() { |  | ||||||
|     std::scoped_lock lk{m_lock}; |  | ||||||
|  |  | ||||||
|     for (const auto& [aruid, applet] : m_applets) { |  | ||||||
|         applet->message_queue.RequestExit(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void AppletManager::RequestResume() { |  | ||||||
|     std::scoped_lock lk{m_lock}; |  | ||||||
|  |  | ||||||
|     for (const auto& [aruid, applet] : m_applets) { |  | ||||||
|         applet->message_queue.RequestResume(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void AppletManager::OperationModeChanged() { |  | ||||||
|     std::scoped_lock lk{m_lock}; |  | ||||||
|  |  | ||||||
|     for (const auto& [aruid, applet] : m_applets) { |  | ||||||
|         applet->message_queue.OperationModeChanged(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void AppletManager::FocusStateChanged() { |  | ||||||
|     std::scoped_lock lk{m_lock}; |  | ||||||
|  |  | ||||||
|     for (const auto& [aruid, applet] : m_applets) { |  | ||||||
|         applet->message_queue.FocusStateChanged(); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| } // namespace Service::AM | } // namespace Service::AM | ||||||
|   | |||||||
| @@ -3,17 +3,23 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <map> | #include <condition_variable> | ||||||
| #include <mutex> | #include <mutex> | ||||||
|  |  | ||||||
| #include "core/hle/service/am/applet.h" | #include "core/hle/service/am/am_types.h" | ||||||
|  |  | ||||||
| namespace Core { | namespace Core { | ||||||
| class System; | class System; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | namespace Service { | ||||||
|  | class Process; | ||||||
|  | } | ||||||
|  |  | ||||||
| namespace Service::AM { | namespace Service::AM { | ||||||
|  |  | ||||||
|  | class WindowSystem; | ||||||
|  |  | ||||||
| enum class LaunchType { | enum class LaunchType { | ||||||
|     FrontendInitiated, |     FrontendInitiated, | ||||||
|     ApplicationInitiated, |     ApplicationInitiated, | ||||||
| @@ -33,27 +39,24 @@ public: | |||||||
|     explicit AppletManager(Core::System& system); |     explicit AppletManager(Core::System& system); | ||||||
|     ~AppletManager(); |     ~AppletManager(); | ||||||
|  |  | ||||||
|     void InsertApplet(std::shared_ptr<Applet> applet); |     void CreateAndInsertByFrontendAppletParameters(std::unique_ptr<Process> process, | ||||||
|     void TerminateAndRemoveApplet(AppletResourceUserId aruid); |  | ||||||
|  |  | ||||||
|     void CreateAndInsertByFrontendAppletParameters(AppletResourceUserId aruid, |  | ||||||
|                                                    const FrontendAppletParameters& params); |                                                    const FrontendAppletParameters& params); | ||||||
|     std::shared_ptr<Applet> GetByAppletResourceUserId(AppletResourceUserId aruid) const; |  | ||||||
|  |  | ||||||
|     void Reset(); |  | ||||||
|  |  | ||||||
|     void RequestExit(); |     void RequestExit(); | ||||||
|     void RequestResume(); |  | ||||||
|     void OperationModeChanged(); |     void OperationModeChanged(); | ||||||
|     void FocusStateChanged(); |  | ||||||
|  | public: | ||||||
|  |     void SetWindowSystem(WindowSystem* window_system); | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     Core::System& m_system; |     Core::System& m_system; | ||||||
|  |  | ||||||
|     mutable std::mutex m_lock{}; |     std::mutex m_lock; | ||||||
|     std::map<AppletResourceUserId, std::shared_ptr<Applet>> m_applets{}; |     std::condition_variable m_cv; | ||||||
|  |  | ||||||
|     // AudioController state goes here |     WindowSystem* m_window_system{}; | ||||||
|  |  | ||||||
|  |     FrontendAppletParameters m_pending_parameters{}; | ||||||
|  |     std::unique_ptr<Process> m_pending_process{}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| } // namespace Service::AM | } // namespace Service::AM | ||||||
|   | |||||||
| @@ -69,7 +69,11 @@ void FrontendApplet::PushInteractiveOutData(std::shared_ptr<IStorage> storage) { | |||||||
| } | } | ||||||
|  |  | ||||||
| void FrontendApplet::Exit() { | void FrontendApplet::Exit() { | ||||||
|     applet.lock()->caller_applet_broker->SignalCompletion(); |     auto applet_ = applet.lock(); | ||||||
|  |  | ||||||
|  |     std::scoped_lock lk{applet_->lock}; | ||||||
|  |     applet_->is_completed = true; | ||||||
|  |     applet_->state_changed_event.Signal(); | ||||||
| } | } | ||||||
|  |  | ||||||
| FrontendAppletSet::FrontendAppletSet() = default; | FrontendAppletSet::FrontendAppletSet() = default; | ||||||
|   | |||||||
| @@ -3,24 +3,28 @@ | |||||||
|  |  | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
| #include "core/hle/service/am/hid_registration.h" | #include "core/hle/service/am/hid_registration.h" | ||||||
| #include "core/hle/service/am/process.h" |  | ||||||
| #include "core/hle/service/hid/hid_server.h" | #include "core/hle/service/hid/hid_server.h" | ||||||
|  | #include "core/hle/service/os/process.h" | ||||||
| #include "core/hle/service/sm/sm.h" | #include "core/hle/service/sm/sm.h" | ||||||
| #include "hid_core/resource_manager.h" | #include "hid_core/resource_manager.h" | ||||||
|  |  | ||||||
| namespace Service::AM { | namespace Service::AM { | ||||||
|  |  | ||||||
| HidRegistration::HidRegistration(Core::System& system, Process& process) : m_process(process) { | HidRegistration::HidRegistration(Core::System& system, Process& process) : m_process(process) { | ||||||
|     m_hid_server = system.ServiceManager().GetService<HID::IHidServer>("hid"); |     m_hid_server = system.ServiceManager().GetService<HID::IHidServer>("hid", true); | ||||||
|  |  | ||||||
|     if (m_process.IsInitialized()) { |     if (m_process.IsInitialized()) { | ||||||
|         m_hid_server->GetResourceManager()->RegisterAppletResourceUserId(m_process.GetProcessId(), |         m_hid_server->GetResourceManager()->RegisterAppletResourceUserId(m_process.GetProcessId(), | ||||||
|                                                                          true); |                                                                          true); | ||||||
|  |         m_hid_server->GetResourceManager()->SetAruidValidForVibration(m_process.GetProcessId(), | ||||||
|  |                                                                       true); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| HidRegistration::~HidRegistration() { | HidRegistration::~HidRegistration() { | ||||||
|     if (m_process.IsInitialized()) { |     if (m_process.IsInitialized()) { | ||||||
|  |         m_hid_server->GetResourceManager()->SetAruidValidForVibration(m_process.GetProcessId(), | ||||||
|  |                                                                       false); | ||||||
|         m_hid_server->GetResourceManager()->UnregisterAppletResourceUserId( |         m_hid_server->GetResourceManager()->UnregisterAppletResourceUserId( | ||||||
|             m_process.GetProcessId()); |             m_process.GetProcessId()); | ||||||
|     } |     } | ||||||
| @@ -28,6 +32,8 @@ HidRegistration::~HidRegistration() { | |||||||
|  |  | ||||||
| void HidRegistration::EnableAppletToGetInput(bool enable) { | void HidRegistration::EnableAppletToGetInput(bool enable) { | ||||||
|     if (m_process.IsInitialized()) { |     if (m_process.IsInitialized()) { | ||||||
|  |         m_hid_server->GetResourceManager()->SetAruidValidForVibration(m_process.GetProcessId(), | ||||||
|  |                                                                       enable); | ||||||
|         m_hid_server->GetResourceManager()->EnableInput(m_process.GetProcessId(), enable); |         m_hid_server->GetResourceManager()->EnableInput(m_process.GetProcessId(), enable); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -13,9 +13,11 @@ namespace Service::HID { | |||||||
| class IHidServer; | class IHidServer; | ||||||
| } | } | ||||||
|  |  | ||||||
| namespace Service::AM { | namespace Service { | ||||||
|  |  | ||||||
| class Process; | class Process; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | namespace Service::AM { | ||||||
|  |  | ||||||
| class HidRegistration { | class HidRegistration { | ||||||
| public: | public: | ||||||
|   | |||||||
| @@ -6,12 +6,14 @@ | |||||||
| #include "core/hle/service/am/service/all_system_applet_proxies_service.h" | #include "core/hle/service/am/service/all_system_applet_proxies_service.h" | ||||||
| #include "core/hle/service/am/service/library_applet_proxy.h" | #include "core/hle/service/am/service/library_applet_proxy.h" | ||||||
| #include "core/hle/service/am/service/system_applet_proxy.h" | #include "core/hle/service/am/service/system_applet_proxy.h" | ||||||
|  | #include "core/hle/service/am/window_system.h" | ||||||
| #include "core/hle/service/cmif_serialization.h" | #include "core/hle/service/cmif_serialization.h" | ||||||
|  |  | ||||||
| namespace Service::AM { | namespace Service::AM { | ||||||
|  |  | ||||||
| IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_) | IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_, | ||||||
|     : ServiceFramework{system_, "appletAE"} { |                                                                WindowSystem& window_system) | ||||||
|  |     : ServiceFramework{system_, "appletAE"}, m_window_system{window_system} { | ||||||
|     // clang-format off |     // clang-format off | ||||||
|     static const FunctionInfo functions[] = { |     static const FunctionInfo functions[] = { | ||||||
|         {100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"}, |         {100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"}, | ||||||
| @@ -36,8 +38,8 @@ Result IAllSystemAppletProxiesService::OpenSystemAppletProxy( | |||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|  |  | ||||||
|     if (const auto applet = this->GetAppletFromProcessId(pid); applet) { |     if (const auto applet = this->GetAppletFromProcessId(pid); applet) { | ||||||
|         *out_system_applet_proxy = |         *out_system_applet_proxy = std::make_shared<ISystemAppletProxy>( | ||||||
|             std::make_shared<ISystemAppletProxy>(system, applet, process_handle.Get()); |             system, applet, process_handle.Get(), m_window_system); | ||||||
|         R_SUCCEED(); |         R_SUCCEED(); | ||||||
|     } else { |     } else { | ||||||
|         UNIMPLEMENTED(); |         UNIMPLEMENTED(); | ||||||
| @@ -52,8 +54,8 @@ Result IAllSystemAppletProxiesService::OpenLibraryAppletProxy( | |||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|  |  | ||||||
|     if (const auto applet = this->GetAppletFromProcessId(pid); applet) { |     if (const auto applet = this->GetAppletFromProcessId(pid); applet) { | ||||||
|         *out_library_applet_proxy = |         *out_library_applet_proxy = std::make_shared<ILibraryAppletProxy>( | ||||||
|             std::make_shared<ILibraryAppletProxy>(system, applet, process_handle.Get()); |             system, applet, process_handle.Get(), m_window_system); | ||||||
|         R_SUCCEED(); |         R_SUCCEED(); | ||||||
|     } else { |     } else { | ||||||
|         UNIMPLEMENTED(); |         UNIMPLEMENTED(); | ||||||
| @@ -73,7 +75,7 @@ Result IAllSystemAppletProxiesService::OpenLibraryAppletProxyOld( | |||||||
|  |  | ||||||
| std::shared_ptr<Applet> IAllSystemAppletProxiesService::GetAppletFromProcessId( | std::shared_ptr<Applet> IAllSystemAppletProxiesService::GetAppletFromProcessId( | ||||||
|     ProcessId process_id) { |     ProcessId process_id) { | ||||||
|     return system.GetAppletManager().GetByAppletResourceUserId(process_id.pid); |     return m_window_system.GetByAppletResourceUserId(process_id.pid); | ||||||
| } | } | ||||||
|  |  | ||||||
| } // namespace Service::AM | } // namespace Service::AM | ||||||
|   | |||||||
| @@ -14,11 +14,12 @@ struct Applet; | |||||||
| struct AppletAttribute; | struct AppletAttribute; | ||||||
| class ILibraryAppletProxy; | class ILibraryAppletProxy; | ||||||
| class ISystemAppletProxy; | class ISystemAppletProxy; | ||||||
|  | class WindowSystem; | ||||||
|  |  | ||||||
| class IAllSystemAppletProxiesService final | class IAllSystemAppletProxiesService final | ||||||
|     : public ServiceFramework<IAllSystemAppletProxiesService> { |     : public ServiceFramework<IAllSystemAppletProxiesService> { | ||||||
| public: | public: | ||||||
|     explicit IAllSystemAppletProxiesService(Core::System& system_); |     explicit IAllSystemAppletProxiesService(Core::System& system_, WindowSystem& window_system); | ||||||
|     ~IAllSystemAppletProxiesService() override; |     ~IAllSystemAppletProxiesService() override; | ||||||
|  |  | ||||||
| private: | private: | ||||||
| @@ -35,6 +36,8 @@ private: | |||||||
|  |  | ||||||
| private: | private: | ||||||
|     std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid); |     std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid); | ||||||
|  |  | ||||||
|  |     WindowSystem& m_window_system; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| } // namespace AM | } // namespace AM | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_, | |||||||
|         {21, nullptr, "TryPopFromAppletBoundChannel"}, |         {21, nullptr, "TryPopFromAppletBoundChannel"}, | ||||||
|         {40, nullptr, "GetDisplayLogicalResolution"}, |         {40, nullptr, "GetDisplayLogicalResolution"}, | ||||||
|         {42, nullptr, "SetDisplayMagnification"}, |         {42, nullptr, "SetDisplayMagnification"}, | ||||||
|         {50, nullptr, "SetHomeButtonDoubleClickEnabled"}, |         {50, D<&IAppletCommonFunctions::SetHomeButtonDoubleClickEnabled>, "SetHomeButtonDoubleClickEnabled"}, | ||||||
|         {51, D<&IAppletCommonFunctions::GetHomeButtonDoubleClickEnabled>, "GetHomeButtonDoubleClickEnabled"}, |         {51, D<&IAppletCommonFunctions::GetHomeButtonDoubleClickEnabled>, "GetHomeButtonDoubleClickEnabled"}, | ||||||
|         {52, nullptr, "IsHomeButtonShortPressedBlocked"}, |         {52, nullptr, "IsHomeButtonShortPressedBlocked"}, | ||||||
|         {60, nullptr, "IsVrModeCurtainRequired"}, |         {60, nullptr, "IsVrModeCurtainRequired"}, | ||||||
| @@ -40,6 +40,13 @@ IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_, | |||||||
|  |  | ||||||
| IAppletCommonFunctions::~IAppletCommonFunctions() = default; | IAppletCommonFunctions::~IAppletCommonFunctions() = default; | ||||||
|  |  | ||||||
|  | Result IAppletCommonFunctions::SetHomeButtonDoubleClickEnabled( | ||||||
|  |     bool home_button_double_click_enabled) { | ||||||
|  |     LOG_WARNING(Service_AM, "(STUBBED) called, home_button_double_click_enabled={}", | ||||||
|  |                 home_button_double_click_enabled); | ||||||
|  |     R_SUCCEED(); | ||||||
|  | } | ||||||
|  |  | ||||||
| Result IAppletCommonFunctions::GetHomeButtonDoubleClickEnabled( | Result IAppletCommonFunctions::GetHomeButtonDoubleClickEnabled( | ||||||
|     Out<bool> out_home_button_double_click_enabled) { |     Out<bool> out_home_button_double_click_enabled) { | ||||||
|     LOG_WARNING(Service_AM, "(STUBBED) called"); |     LOG_WARNING(Service_AM, "(STUBBED) called"); | ||||||
|   | |||||||
| @@ -16,6 +16,7 @@ public: | |||||||
|     ~IAppletCommonFunctions() override; |     ~IAppletCommonFunctions() override; | ||||||
|  |  | ||||||
| private: | private: | ||||||
|  |     Result SetHomeButtonDoubleClickEnabled(bool home_button_double_click_enabled); | ||||||
|     Result GetHomeButtonDoubleClickEnabled(Out<bool> out_home_button_double_click_enabled); |     Result GetHomeButtonDoubleClickEnabled(Out<bool> out_home_button_double_click_enabled); | ||||||
|     Result SetCpuBoostRequestPriority(s32 priority); |     Result SetCpuBoostRequestPriority(s32 priority); | ||||||
|     Result GetCurrentApplicationId(Out<u64> out_application_id); |     Result GetCurrentApplicationId(Out<u64> out_application_id); | ||||||
|   | |||||||
| @@ -9,12 +9,16 @@ | |||||||
| #include "core/hle/service/am/service/application_accessor.h" | #include "core/hle/service/am/service/application_accessor.h" | ||||||
| #include "core/hle/service/am/service/library_applet_accessor.h" | #include "core/hle/service/am/service/library_applet_accessor.h" | ||||||
| #include "core/hle/service/am/service/storage.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/cmif_serialization.h" | ||||||
|  | #include "core/hle/service/glue/glue_manager.h" | ||||||
|  |  | ||||||
| namespace Service::AM { | namespace Service::AM { | ||||||
|  |  | ||||||
| IApplicationAccessor::IApplicationAccessor(Core::System& system_, std::shared_ptr<Applet> applet) | IApplicationAccessor::IApplicationAccessor(Core::System& system_, std::shared_ptr<Applet> applet, | ||||||
|     : ServiceFramework{system_, "IApplicationAccessor"}, m_applet(std::move(applet)) { |                                            WindowSystem& window_system) | ||||||
|  |     : ServiceFramework{system_, "IApplicationAccessor"}, m_window_system(window_system), | ||||||
|  |       m_applet(std::move(applet)) { | ||||||
|     // clang-format off |     // clang-format off | ||||||
|     static const FunctionInfo functions[] = { |     static const FunctionInfo functions[] = { | ||||||
|         {0, D<&IApplicationAccessor::GetAppletStateChangedEvent>, "GetAppletStateChangedEvent"}, |         {0, D<&IApplicationAccessor::GetAppletStateChangedEvent>, "GetAppletStateChangedEvent"}, | ||||||
| @@ -59,7 +63,15 @@ Result IApplicationAccessor::Start() { | |||||||
|  |  | ||||||
| Result IApplicationAccessor::RequestExit() { | Result IApplicationAccessor::RequestExit() { | ||||||
|     LOG_INFO(Service_AM, "called"); |     LOG_INFO(Service_AM, "called"); | ||||||
|     m_applet->message_queue.RequestExit(); |  | ||||||
|  |     std::scoped_lock lk{m_applet->lock}; | ||||||
|  |     if (m_applet->exit_locked) { | ||||||
|  |         m_applet->lifecycle_manager.RequestExit(); | ||||||
|  |         m_applet->UpdateSuspensionStateLocked(true); | ||||||
|  |     } else { | ||||||
|  |         m_applet->process->Terminate(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -71,13 +83,14 @@ Result IApplicationAccessor::Terminate() { | |||||||
|  |  | ||||||
| Result IApplicationAccessor::GetResult() { | Result IApplicationAccessor::GetResult() { | ||||||
|     LOG_INFO(Service_AM, "called"); |     LOG_INFO(Service_AM, "called"); | ||||||
|     R_SUCCEED(); |     std::scoped_lock lk{m_applet->lock}; | ||||||
|  |     R_RETURN(m_applet->terminate_result); | ||||||
| } | } | ||||||
|  |  | ||||||
| Result IApplicationAccessor::GetAppletStateChangedEvent( | Result IApplicationAccessor::GetAppletStateChangedEvent( | ||||||
|     OutCopyHandle<Kernel::KReadableEvent> out_event) { |     OutCopyHandle<Kernel::KReadableEvent> out_event) { | ||||||
|     LOG_INFO(Service_AM, "called"); |     LOG_INFO(Service_AM, "called"); | ||||||
|     *out_event = m_applet->caller_applet_broker->GetStateChangedEvent().GetHandle(); |     *out_event = m_applet->state_changed_event.GetHandle(); | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -96,8 +109,15 @@ Result IApplicationAccessor::PushLaunchParameter(LaunchParameterKind kind, | |||||||
|  |  | ||||||
| Result IApplicationAccessor::GetApplicationControlProperty( | Result IApplicationAccessor::GetApplicationControlProperty( | ||||||
|     OutBuffer<BufferAttr_HipcMapAlias> out_control_property) { |     OutBuffer<BufferAttr_HipcMapAlias> out_control_property) { | ||||||
|     LOG_WARNING(Service_AM, "(STUBBED) called"); |     LOG_INFO(Service_AM, "called"); | ||||||
|     R_THROW(ResultUnknown); |  | ||||||
|  |     std::vector<u8> nacp; | ||||||
|  |     R_TRY(system.GetARPManager().GetControlProperty(&nacp, m_applet->program_id)); | ||||||
|  |  | ||||||
|  |     std::memcpy(out_control_property.data(), nacp.data(), | ||||||
|  |                 std::min(out_control_property.size(), nacp.size())); | ||||||
|  |  | ||||||
|  |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
| Result IApplicationAccessor::SetUsers(bool enable, | Result IApplicationAccessor::SetUsers(bool enable, | ||||||
| @@ -114,8 +134,9 @@ Result IApplicationAccessor::GetCurrentLibraryApplet( | |||||||
| } | } | ||||||
|  |  | ||||||
| Result IApplicationAccessor::RequestForApplicationToGetForeground() { | Result IApplicationAccessor::RequestForApplicationToGetForeground() { | ||||||
|     LOG_WARNING(Service_AM, "(STUBBED) called"); |     LOG_INFO(Service_AM, "called"); | ||||||
|     R_THROW(ResultUnknown); |     m_window_system.RequestApplicationToGetForeground(); | ||||||
|  |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
| Result IApplicationAccessor::CheckRightsEnvironmentAvailable(Out<bool> out_is_available) { | Result IApplicationAccessor::CheckRightsEnvironmentAvailable(Out<bool> out_is_available) { | ||||||
|   | |||||||
| @@ -13,10 +13,12 @@ namespace Service::AM { | |||||||
| struct Applet; | struct Applet; | ||||||
| class ILibraryAppletAccessor; | class ILibraryAppletAccessor; | ||||||
| class IStorage; | class IStorage; | ||||||
|  | class WindowSystem; | ||||||
|  |  | ||||||
| class IApplicationAccessor final : public ServiceFramework<IApplicationAccessor> { | class IApplicationAccessor final : public ServiceFramework<IApplicationAccessor> { | ||||||
| public: | public: | ||||||
|     explicit IApplicationAccessor(Core::System& system_, std::shared_ptr<Applet> applet); |     explicit IApplicationAccessor(Core::System& system_, std::shared_ptr<Applet> applet, | ||||||
|  |                                   WindowSystem& window_system); | ||||||
|     ~IApplicationAccessor() override; |     ~IApplicationAccessor() override; | ||||||
|  |  | ||||||
| private: | private: | ||||||
| @@ -34,6 +36,7 @@ private: | |||||||
|     Result GetNsRightsEnvironmentHandle(Out<u64> out_handle); |     Result GetNsRightsEnvironmentHandle(Out<u64> out_handle); | ||||||
|     Result ReportApplicationExitTimeout(); |     Result ReportApplicationExitTimeout(); | ||||||
|  |  | ||||||
|  |     WindowSystem& m_window_system; | ||||||
|     const std::shared_ptr<Applet> m_applet; |     const std::shared_ptr<Applet> m_applet; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,17 +1,57 @@ | |||||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||||||
| // SPDX-License-Identifier: GPL-2.0-or-later | // SPDX-License-Identifier: GPL-2.0-or-later | ||||||
|  |  | ||||||
|  | #include "core/file_sys/nca_metadata.h" | ||||||
|  | #include "core/file_sys/registered_cache.h" | ||||||
| #include "core/hle/service/am/am_types.h" | #include "core/hle/service/am/am_types.h" | ||||||
| #include "core/hle/service/am/applet.h" | #include "core/hle/service/am/applet.h" | ||||||
| #include "core/hle/service/am/applet_manager.h" | #include "core/hle/service/am/applet_manager.h" | ||||||
|  | #include "core/hle/service/am/process_creation.h" | ||||||
| #include "core/hle/service/am/service/application_accessor.h" | #include "core/hle/service/am/service/application_accessor.h" | ||||||
| #include "core/hle/service/am/service/application_creator.h" | #include "core/hle/service/am/service/application_creator.h" | ||||||
|  | #include "core/hle/service/am/window_system.h" | ||||||
| #include "core/hle/service/cmif_serialization.h" | #include "core/hle/service/cmif_serialization.h" | ||||||
|  | #include "core/loader/loader.h" | ||||||
|  |  | ||||||
| namespace Service::AM { | namespace Service::AM { | ||||||
|  |  | ||||||
| IApplicationCreator::IApplicationCreator(Core::System& system_) | namespace { | ||||||
|     : ServiceFramework{system_, "IApplicationCreator"} { |  | ||||||
|  | Result CreateGuestApplication(SharedPointer<IApplicationAccessor>* out_application_accessor, | ||||||
|  |                               Core::System& system, WindowSystem& window_system, u64 program_id) { | ||||||
|  |     FileSys::VirtualFile nca_raw{}; | ||||||
|  |  | ||||||
|  |     // Get the program NCA from storage. | ||||||
|  |     auto& storage = system.GetContentProviderUnion(); | ||||||
|  |     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; | ||||||
|  |  | ||||||
|  |     window_system.TrackApplet(applet, true); | ||||||
|  |  | ||||||
|  |     *out_application_accessor = | ||||||
|  |         std::make_shared<IApplicationAccessor>(system, applet, window_system); | ||||||
|  |     R_SUCCEED(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | } // namespace | ||||||
|  |  | ||||||
|  | IApplicationCreator::IApplicationCreator(Core::System& system_, WindowSystem& window_system) | ||||||
|  |     : ServiceFramework{system_, "IApplicationCreator"}, m_window_system{window_system} { | ||||||
|     // clang-format off |     // clang-format off | ||||||
|     static const FunctionInfo functions[] = { |     static const FunctionInfo functions[] = { | ||||||
|         {0, D<&IApplicationCreator::CreateApplication>, "CreateApplication"}, |         {0, D<&IApplicationCreator::CreateApplication>, "CreateApplication"}, | ||||||
| @@ -28,8 +68,9 @@ IApplicationCreator::~IApplicationCreator() = default; | |||||||
|  |  | ||||||
| Result IApplicationCreator::CreateApplication( | Result IApplicationCreator::CreateApplication( | ||||||
|     Out<SharedPointer<IApplicationAccessor>> out_application_accessor, u64 application_id) { |     Out<SharedPointer<IApplicationAccessor>> out_application_accessor, u64 application_id) { | ||||||
|     LOG_ERROR(Service_NS, "called, application_id={:x}", application_id); |     LOG_INFO(Service_NS, "called, application_id={:016X}", application_id); | ||||||
|     R_THROW(ResultUnknown); |     R_RETURN( | ||||||
|  |         CreateGuestApplication(out_application_accessor, system, m_window_system, application_id)); | ||||||
| } | } | ||||||
|  |  | ||||||
| } // namespace Service::AM | } // namespace Service::AM | ||||||
|   | |||||||
| @@ -10,14 +10,17 @@ namespace Service::AM { | |||||||
|  |  | ||||||
| class IApplicationAccessor; | class IApplicationAccessor; | ||||||
| struct Applet; | struct Applet; | ||||||
|  | class WindowSystem; | ||||||
|  |  | ||||||
| class IApplicationCreator final : public ServiceFramework<IApplicationCreator> { | class IApplicationCreator final : public ServiceFramework<IApplicationCreator> { | ||||||
| public: | public: | ||||||
|     explicit IApplicationCreator(Core::System& system_); |     explicit IApplicationCreator(Core::System& system_, WindowSystem& window_system); | ||||||
|     ~IApplicationCreator() override; |     ~IApplicationCreator() override; | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     Result CreateApplication(Out<SharedPointer<IApplicationAccessor>>, u64 application_id); |     Result CreateApplication(Out<SharedPointer<IApplicationAccessor>>, u64 application_id); | ||||||
|  |  | ||||||
|  |     WindowSystem& m_window_system; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| } // namespace Service::AM | } // namespace Service::AM | ||||||
|   | |||||||
| @@ -181,7 +181,8 @@ Result IApplicationFunctions::GetDesiredLanguage(Out<u64> out_language_code) { | |||||||
| } | } | ||||||
|  |  | ||||||
| Result IApplicationFunctions::SetTerminateResult(Result terminate_result) { | Result IApplicationFunctions::SetTerminateResult(Result terminate_result) { | ||||||
|     LOG_INFO(Service_AM, "(STUBBED) called, result={:#x} ({}-{})", terminate_result.GetInnerValue(), |     LOG_INFO(Service_AM, "(STUBBED) called, result={:#x} ({:04}-{:04})", | ||||||
|  |              terminate_result.GetInnerValue(), | ||||||
|              static_cast<u32>(terminate_result.GetModule()) + 2000, |              static_cast<u32>(terminate_result.GetModule()) + 2000, | ||||||
|              terminate_result.GetDescription()); |              terminate_result.GetDescription()); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -17,9 +17,9 @@ | |||||||
| namespace Service::AM { | namespace Service::AM { | ||||||
|  |  | ||||||
| IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet, | IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet, | ||||||
|                                      Kernel::KProcess* process) |                                      Kernel::KProcess* process, WindowSystem& window_system) | ||||||
|     : ServiceFramework{system_, "IApplicationProxy"}, m_process{process}, m_applet{ |     : ServiceFramework{system_, "IApplicationProxy"}, | ||||||
|                                                                               std::move(applet)} { |       m_window_system{window_system}, m_process{process}, m_applet{std::move(applet)} { | ||||||
|     // clang-format off |     // clang-format off | ||||||
|     static const FunctionInfo functions[] = { |     static const FunctionInfo functions[] = { | ||||||
|         {0, D<&IApplicationProxy::GetCommonStateGetter>, "GetCommonStateGetter"}, |         {0, D<&IApplicationProxy::GetCommonStateGetter>, "GetCommonStateGetter"}, | ||||||
| @@ -70,7 +70,7 @@ Result IApplicationProxy::GetDebugFunctions( | |||||||
| Result IApplicationProxy::GetWindowController( | Result IApplicationProxy::GetWindowController( | ||||||
|     Out<SharedPointer<IWindowController>> out_window_controller) { |     Out<SharedPointer<IWindowController>> out_window_controller) { | ||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|     *out_window_controller = std::make_shared<IWindowController>(system, m_applet); |     *out_window_controller = std::make_shared<IWindowController>(system, m_applet, m_window_system); | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -91,7 +91,8 @@ Result IApplicationProxy::GetCommonStateGetter( | |||||||
| Result IApplicationProxy::GetLibraryAppletCreator( | Result IApplicationProxy::GetLibraryAppletCreator( | ||||||
|     Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) { |     Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) { | ||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|     *out_library_applet_creator = std::make_shared<ILibraryAppletCreator>(system, m_applet); |     *out_library_applet_creator = | ||||||
|  |         std::make_shared<ILibraryAppletCreator>(system, m_applet, m_window_system); | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,11 +18,12 @@ class ILibraryAppletCreator; | |||||||
| class IProcessWindingController; | class IProcessWindingController; | ||||||
| class ISelfController; | class ISelfController; | ||||||
| class IWindowController; | class IWindowController; | ||||||
|  | class WindowSystem; | ||||||
|  |  | ||||||
| class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { | class IApplicationProxy final : public ServiceFramework<IApplicationProxy> { | ||||||
| public: | public: | ||||||
|     explicit IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet, |     explicit IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet, | ||||||
|                                Kernel::KProcess* process); |                                Kernel::KProcess* process, WindowSystem& window_system); | ||||||
|     ~IApplicationProxy(); |     ~IApplicationProxy(); | ||||||
|  |  | ||||||
| private: | private: | ||||||
| @@ -40,6 +41,7 @@ private: | |||||||
|         Out<SharedPointer<IApplicationFunctions>> out_application_functions); |         Out<SharedPointer<IApplicationFunctions>> out_application_functions); | ||||||
|  |  | ||||||
| private: | private: | ||||||
|  |     WindowSystem& m_window_system; | ||||||
|     Kernel::KProcess* const m_process; |     Kernel::KProcess* const m_process; | ||||||
|     const std::shared_ptr<Applet> m_applet; |     const std::shared_ptr<Applet> m_applet; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -6,12 +6,14 @@ | |||||||
| #include "core/hle/service/am/applet_manager.h" | #include "core/hle/service/am/applet_manager.h" | ||||||
| #include "core/hle/service/am/service/application_proxy.h" | #include "core/hle/service/am/service/application_proxy.h" | ||||||
| #include "core/hle/service/am/service/application_proxy_service.h" | #include "core/hle/service/am/service/application_proxy_service.h" | ||||||
|  | #include "core/hle/service/am/window_system.h" | ||||||
| #include "core/hle/service/cmif_serialization.h" | #include "core/hle/service/cmif_serialization.h" | ||||||
|  |  | ||||||
| namespace Service::AM { | namespace Service::AM { | ||||||
|  |  | ||||||
| IApplicationProxyService::IApplicationProxyService(Core::System& system_) | IApplicationProxyService::IApplicationProxyService(Core::System& system_, | ||||||
|     : ServiceFramework{system_, "appletOE"} { |                                                    WindowSystem& window_system) | ||||||
|  |     : ServiceFramework{system_, "appletOE"}, m_window_system{window_system} { | ||||||
|     static const FunctionInfo functions[] = { |     static const FunctionInfo functions[] = { | ||||||
|         {0, D<&IApplicationProxyService::OpenApplicationProxy>, "OpenApplicationProxy"}, |         {0, D<&IApplicationProxyService::OpenApplicationProxy>, "OpenApplicationProxy"}, | ||||||
|     }; |     }; | ||||||
| @@ -26,8 +28,8 @@ Result IApplicationProxyService::OpenApplicationProxy( | |||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|  |  | ||||||
|     if (const auto applet = this->GetAppletFromProcessId(pid)) { |     if (const auto applet = this->GetAppletFromProcessId(pid)) { | ||||||
|         *out_application_proxy = |         *out_application_proxy = std::make_shared<IApplicationProxy>( | ||||||
|             std::make_shared<IApplicationProxy>(system, applet, process_handle.Get()); |             system, applet, process_handle.Get(), m_window_system); | ||||||
|         R_SUCCEED(); |         R_SUCCEED(); | ||||||
|     } else { |     } else { | ||||||
|         UNIMPLEMENTED(); |         UNIMPLEMENTED(); | ||||||
| @@ -36,7 +38,7 @@ Result IApplicationProxyService::OpenApplicationProxy( | |||||||
| } | } | ||||||
|  |  | ||||||
| std::shared_ptr<Applet> IApplicationProxyService::GetAppletFromProcessId(ProcessId process_id) { | std::shared_ptr<Applet> IApplicationProxyService::GetAppletFromProcessId(ProcessId process_id) { | ||||||
|     return system.GetAppletManager().GetByAppletResourceUserId(process_id.pid); |     return m_window_system.GetByAppletResourceUserId(process_id.pid); | ||||||
| } | } | ||||||
|  |  | ||||||
| } // namespace Service::AM | } // namespace Service::AM | ||||||
|   | |||||||
| @@ -12,10 +12,11 @@ namespace AM { | |||||||
|  |  | ||||||
| struct Applet; | struct Applet; | ||||||
| class IApplicationProxy; | class IApplicationProxy; | ||||||
|  | class WindowSystem; | ||||||
|  |  | ||||||
| class IApplicationProxyService final : public ServiceFramework<IApplicationProxyService> { | class IApplicationProxyService final : public ServiceFramework<IApplicationProxyService> { | ||||||
| public: | public: | ||||||
|     explicit IApplicationProxyService(Core::System& system_); |     explicit IApplicationProxyService(Core::System& system_, WindowSystem& window_system); | ||||||
|     ~IApplicationProxyService() override; |     ~IApplicationProxyService() override; | ||||||
|  |  | ||||||
| private: | private: | ||||||
| @@ -24,6 +25,8 @@ private: | |||||||
|  |  | ||||||
| private: | private: | ||||||
|     std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid); |     std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid); | ||||||
|  |  | ||||||
|  |     WindowSystem& m_window_system; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| } // namespace AM | } // namespace AM | ||||||
|   | |||||||
| @@ -80,15 +80,14 @@ ICommonStateGetter::~ICommonStateGetter() = default; | |||||||
|  |  | ||||||
| Result ICommonStateGetter::GetEventHandle(OutCopyHandle<Kernel::KReadableEvent> out_event) { | Result ICommonStateGetter::GetEventHandle(OutCopyHandle<Kernel::KReadableEvent> out_event) { | ||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|     *out_event = &m_applet->message_queue.GetMessageReceiveEvent(); |     *out_event = m_applet->lifecycle_manager.GetSystemEvent().GetHandle(); | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
| Result ICommonStateGetter::ReceiveMessage(Out<AppletMessage> out_applet_message) { | Result ICommonStateGetter::ReceiveMessage(Out<AppletMessage> out_applet_message) { | ||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|  |  | ||||||
|     *out_applet_message = m_applet->message_queue.PopMessage(); |     if (!m_applet->lifecycle_manager.PopMessage(out_applet_message)) { | ||||||
|     if (*out_applet_message == AppletMessage::None) { |  | ||||||
|         LOG_ERROR(Service_AM, "Tried to pop message but none was available!"); |         LOG_ERROR(Service_AM, "Tried to pop message but none was available!"); | ||||||
|         R_THROW(AM::ResultNoMessages); |         R_THROW(AM::ResultNoMessages); | ||||||
|     } |     } | ||||||
| @@ -100,7 +99,7 @@ Result ICommonStateGetter::GetCurrentFocusState(Out<FocusState> out_focus_state) | |||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|  |  | ||||||
|     std::scoped_lock lk{m_applet->lock}; |     std::scoped_lock lk{m_applet->lock}; | ||||||
|     *out_focus_state = m_applet->focus_state; |     *out_focus_state = m_applet->lifecycle_manager.GetAndClearFocusState(); | ||||||
|  |  | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
| @@ -137,7 +136,7 @@ Result ICommonStateGetter::GetWriterLockAccessorEx( | |||||||
| Result ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent( | Result ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent( | ||||||
|     OutCopyHandle<Kernel::KReadableEvent> out_event) { |     OutCopyHandle<Kernel::KReadableEvent> out_event) { | ||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|     *out_event = &m_applet->message_queue.GetOperationModeChangedEvent(); |     *out_event = m_applet->lifecycle_manager.GetOperationModeChangedSystemEvent().GetHandle(); | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,13 +4,16 @@ | |||||||
| #include "core/hle/result.h" | #include "core/hle/result.h" | ||||||
| #include "core/hle/service/am/applet_manager.h" | #include "core/hle/service/am/applet_manager.h" | ||||||
| #include "core/hle/service/am/service/home_menu_functions.h" | #include "core/hle/service/am/service/home_menu_functions.h" | ||||||
|  | #include "core/hle/service/am/window_system.h" | ||||||
| #include "core/hle/service/cmif_serialization.h" | #include "core/hle/service/cmif_serialization.h" | ||||||
|  |  | ||||||
| namespace Service::AM { | namespace Service::AM { | ||||||
|  |  | ||||||
| IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Applet> applet) | IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Applet> applet, | ||||||
|     : ServiceFramework{system_, "IHomeMenuFunctions"}, m_applet{std::move(applet)}, |                                        WindowSystem& window_system) | ||||||
|       m_context{system, "IHomeMenuFunctions"}, m_pop_from_general_channel_event{m_context} { |     : ServiceFramework{system_, "IHomeMenuFunctions"}, m_window_system{window_system}, | ||||||
|  |       m_applet{std::move(applet)}, m_context{system, "IHomeMenuFunctions"}, | ||||||
|  |       m_pop_from_general_channel_event{m_context} { | ||||||
|     // clang-format off |     // clang-format off | ||||||
|     static const FunctionInfo functions[] = { |     static const FunctionInfo functions[] = { | ||||||
|         {10, D<&IHomeMenuFunctions::RequestToGetForeground>, "RequestToGetForeground"}, |         {10, D<&IHomeMenuFunctions::RequestToGetForeground>, "RequestToGetForeground"}, | ||||||
| @@ -37,17 +40,20 @@ IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Ap | |||||||
| IHomeMenuFunctions::~IHomeMenuFunctions() = default; | IHomeMenuFunctions::~IHomeMenuFunctions() = default; | ||||||
|  |  | ||||||
| Result IHomeMenuFunctions::RequestToGetForeground() { | Result IHomeMenuFunctions::RequestToGetForeground() { | ||||||
|     LOG_WARNING(Service_AM, "(STUBBED) called"); |     LOG_INFO(Service_AM, "called"); | ||||||
|  |     m_window_system.RequestHomeMenuToGetForeground(); | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
| Result IHomeMenuFunctions::LockForeground() { | Result IHomeMenuFunctions::LockForeground() { | ||||||
|     LOG_WARNING(Service_AM, "(STUBBED) called"); |     LOG_INFO(Service_AM, "called"); | ||||||
|  |     m_window_system.RequestLockHomeMenuIntoForeground(); | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
| Result IHomeMenuFunctions::UnlockForeground() { | Result IHomeMenuFunctions::UnlockForeground() { | ||||||
|     LOG_WARNING(Service_AM, "(STUBBED) called"); |     LOG_INFO(Service_AM, "called"); | ||||||
|  |     m_window_system.RequestUnlockHomeMenuIntoForeground(); | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,10 +11,12 @@ | |||||||
| namespace Service::AM { | namespace Service::AM { | ||||||
|  |  | ||||||
| struct Applet; | struct Applet; | ||||||
|  | class WindowSystem; | ||||||
|  |  | ||||||
| class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> { | class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> { | ||||||
| public: | public: | ||||||
|     explicit IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Applet> applet); |     explicit IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Applet> applet, | ||||||
|  |                                 WindowSystem& window_system); | ||||||
|     ~IHomeMenuFunctions() override; |     ~IHomeMenuFunctions() override; | ||||||
|  |  | ||||||
| private: | private: | ||||||
| @@ -26,6 +28,7 @@ private: | |||||||
|     Result IsForceTerminateApplicationDisabledForDebug( |     Result IsForceTerminateApplicationDisabledForDebug( | ||||||
|         Out<bool> out_is_force_terminate_application_disabled_for_debug); |         Out<bool> out_is_force_terminate_application_disabled_for_debug); | ||||||
|  |  | ||||||
|  |     WindowSystem& m_window_system; | ||||||
|     const std::shared_ptr<Applet> m_applet; |     const std::shared_ptr<Applet> m_applet; | ||||||
|     KernelHelpers::ServiceContext m_context; |     KernelHelpers::ServiceContext m_context; | ||||||
|     Event m_pop_from_general_channel_event; |     Event m_pop_from_general_channel_event; | ||||||
|   | |||||||
| @@ -47,20 +47,21 @@ ILibraryAppletAccessor::~ILibraryAppletAccessor() = default; | |||||||
| Result ILibraryAppletAccessor::GetAppletStateChangedEvent( | Result ILibraryAppletAccessor::GetAppletStateChangedEvent( | ||||||
|     OutCopyHandle<Kernel::KReadableEvent> out_event) { |     OutCopyHandle<Kernel::KReadableEvent> out_event) { | ||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|     *out_event = m_broker->GetStateChangedEvent().GetHandle(); |     *out_event = m_applet->state_changed_event.GetHandle(); | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
| Result ILibraryAppletAccessor::IsCompleted(Out<bool> out_is_completed) { | Result ILibraryAppletAccessor::IsCompleted(Out<bool> out_is_completed) { | ||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|     *out_is_completed = m_broker->IsCompleted(); |     std::scoped_lock lk{m_applet->lock}; | ||||||
|  |     *out_is_completed = m_applet->is_completed; | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
| Result ILibraryAppletAccessor::GetResult(Out<Result> out_result) { | Result ILibraryAppletAccessor::GetResult() { | ||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|     *out_result = m_applet->terminate_result; |     std::scoped_lock lk{m_applet->lock}; | ||||||
|     R_SUCCEED(); |     R_RETURN(m_applet->terminate_result); | ||||||
| } | } | ||||||
|  |  | ||||||
| Result ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero() { | Result ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero() { | ||||||
| @@ -77,7 +78,10 @@ Result ILibraryAppletAccessor::Start() { | |||||||
|  |  | ||||||
| Result ILibraryAppletAccessor::RequestExit() { | Result ILibraryAppletAccessor::RequestExit() { | ||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|     m_applet->message_queue.RequestExit(); |     { | ||||||
|  |         std::scoped_lock lk{m_applet->lock}; | ||||||
|  |         m_applet->lifecycle_manager.RequestExit(); | ||||||
|  |     } | ||||||
|     FrontendRequestExit(); |     FrontendRequestExit(); | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -21,7 +21,7 @@ public: | |||||||
| private: | private: | ||||||
|     Result GetAppletStateChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); |     Result GetAppletStateChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); | ||||||
|     Result IsCompleted(Out<bool> out_is_completed); |     Result IsCompleted(Out<bool> out_is_completed); | ||||||
|     Result GetResult(Out<Result> out_result); |     Result GetResult(); | ||||||
|     Result PresetLibraryAppletGpuTimeSliceZero(); |     Result PresetLibraryAppletGpuTimeSliceZero(); | ||||||
|     Result Start(); |     Result Start(); | ||||||
|     Result RequestExit(); |     Result RequestExit(); | ||||||
|   | |||||||
| @@ -7,9 +7,11 @@ | |||||||
| #include "core/hle/service/am/applet_manager.h" | #include "core/hle/service/am/applet_manager.h" | ||||||
| #include "core/hle/service/am/frontend/applets.h" | #include "core/hle/service/am/frontend/applets.h" | ||||||
| #include "core/hle/service/am/library_applet_storage.h" | #include "core/hle/service/am/library_applet_storage.h" | ||||||
|  | #include "core/hle/service/am/process_creation.h" | ||||||
| #include "core/hle/service/am/service/library_applet_accessor.h" | #include "core/hle/service/am/service/library_applet_accessor.h" | ||||||
| #include "core/hle/service/am/service/library_applet_creator.h" | #include "core/hle/service/am/service/library_applet_creator.h" | ||||||
| #include "core/hle/service/am/service/storage.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/cmif_serialization.h" | ||||||
| #include "core/hle/service/sm/sm.h" | #include "core/hle/service/sm/sm.h" | ||||||
|  |  | ||||||
| @@ -93,6 +95,7 @@ AppletProgramId AppletIdToProgramId(AppletId applet_id) { | |||||||
| } | } | ||||||
|  |  | ||||||
| std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system, | std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system, | ||||||
|  |                                                           WindowSystem& window_system, | ||||||
|                                                           std::shared_ptr<Applet> caller_applet, |                                                           std::shared_ptr<Applet> caller_applet, | ||||||
|                                                           AppletId applet_id, |                                                           AppletId applet_id, | ||||||
|                                                           LibraryAppletMode mode) { |                                                           LibraryAppletMode mode) { | ||||||
| @@ -110,53 +113,38 @@ std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system, | |||||||
|         Firmware1700 = 17, |         Firmware1700 = 17, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     auto process = std::make_unique<Process>(system); |     auto process = CreateProcess(system, program_id, Firmware1400, Firmware1700); | ||||||
|     if (!process->Initialize(program_id, Firmware1400, Firmware1700)) { |     if (!process) { | ||||||
|         // Couldn't initialize the guest process |         // Couldn't initialize the guest process | ||||||
|         return {}; |         return {}; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const auto applet = std::make_shared<Applet>(system, std::move(process)); |     const auto applet = std::make_shared<Applet>(system, std::move(process), false); | ||||||
|     applet->program_id = program_id; |     applet->program_id = program_id; | ||||||
|     applet->applet_id = applet_id; |     applet->applet_id = applet_id; | ||||||
|     applet->type = AppletType::LibraryApplet; |     applet->type = AppletType::LibraryApplet; | ||||||
|     applet->library_applet_mode = mode; |     applet->library_applet_mode = mode; | ||||||
|  |     applet->window_visible = mode != LibraryAppletMode::AllForegroundInitiallyHidden; | ||||||
|     // Set focus state |  | ||||||
|     switch (mode) { |  | ||||||
|     case LibraryAppletMode::AllForeground: |  | ||||||
|     case LibraryAppletMode::NoUi: |  | ||||||
|     case LibraryAppletMode::PartialForeground: |  | ||||||
|     case LibraryAppletMode::PartialForegroundIndirectDisplay: |  | ||||||
|         applet->hid_registration.EnableAppletToGetInput(true); |  | ||||||
|         applet->focus_state = FocusState::InFocus; |  | ||||||
|         applet->message_queue.PushMessage(AppletMessage::ChangeIntoForeground); |  | ||||||
|         break; |  | ||||||
|     case LibraryAppletMode::AllForegroundInitiallyHidden: |  | ||||||
|         applet->hid_registration.EnableAppletToGetInput(false); |  | ||||||
|         applet->focus_state = FocusState::NotInFocus; |  | ||||||
|         applet->display_layer_manager.SetWindowVisibility(false); |  | ||||||
|         applet->message_queue.PushMessage(AppletMessage::ChangeIntoBackground); |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     auto broker = std::make_shared<AppletDataBroker>(system); |     auto broker = std::make_shared<AppletDataBroker>(system); | ||||||
|     applet->caller_applet = caller_applet; |     applet->caller_applet = caller_applet; | ||||||
|     applet->caller_applet_broker = broker; |     applet->caller_applet_broker = broker; | ||||||
|  |     caller_applet->child_applets.push_back(applet); | ||||||
|  |  | ||||||
|     system.GetAppletManager().InsertApplet(applet); |     window_system.TrackApplet(applet, false); | ||||||
|  |  | ||||||
|     return std::make_shared<ILibraryAppletAccessor>(system, broker, applet); |     return std::make_shared<ILibraryAppletAccessor>(system, broker, applet); | ||||||
| } | } | ||||||
|  |  | ||||||
| std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& system, | std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& system, | ||||||
|  |                                                              WindowSystem& window_system, | ||||||
|                                                              std::shared_ptr<Applet> caller_applet, |                                                              std::shared_ptr<Applet> caller_applet, | ||||||
|                                                              AppletId applet_id, |                                                              AppletId applet_id, | ||||||
|                                                              LibraryAppletMode mode) { |                                                              LibraryAppletMode mode) { | ||||||
|     const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id)); |     const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id)); | ||||||
|  |  | ||||||
|     auto process = std::make_unique<Process>(system); |     auto process = std::make_unique<Process>(system); | ||||||
|     auto applet = std::make_shared<Applet>(system, std::move(process)); |     auto applet = std::make_shared<Applet>(system, std::move(process), false); | ||||||
|     applet->program_id = program_id; |     applet->program_id = program_id; | ||||||
|     applet->applet_id = applet_id; |     applet->applet_id = applet_id; | ||||||
|     applet->type = AppletType::LibraryApplet; |     applet->type = AppletType::LibraryApplet; | ||||||
| @@ -166,14 +154,19 @@ std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& syste | |||||||
|     applet->caller_applet = caller_applet; |     applet->caller_applet = caller_applet; | ||||||
|     applet->caller_applet_broker = storage; |     applet->caller_applet_broker = storage; | ||||||
|     applet->frontend = system.GetFrontendAppletHolder().GetApplet(applet, applet_id, mode); |     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); |     return std::make_shared<ILibraryAppletAccessor>(system, storage, applet); | ||||||
| } | } | ||||||
|  |  | ||||||
| } // namespace | } // namespace | ||||||
|  |  | ||||||
| ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet) | ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet, | ||||||
|     : ServiceFramework{system_, "ILibraryAppletCreator"}, m_applet{std::move(applet)} { |                                              WindowSystem& window_system) | ||||||
|  |     : ServiceFramework{system_, "ILibraryAppletCreator"}, | ||||||
|  |       m_window_system{window_system}, 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"}, | ||||||
| @@ -195,10 +188,12 @@ Result ILibraryAppletCreator::CreateLibraryApplet( | |||||||
|  |  | ||||||
|     std::shared_ptr<ILibraryAppletAccessor> library_applet; |     std::shared_ptr<ILibraryAppletAccessor> library_applet; | ||||||
|     if (ShouldCreateGuestApplet(applet_id)) { |     if (ShouldCreateGuestApplet(applet_id)) { | ||||||
|         library_applet = CreateGuestApplet(system, m_applet, applet_id, library_applet_mode); |         library_applet = | ||||||
|  |             CreateGuestApplet(system, m_window_system, m_applet, applet_id, library_applet_mode); | ||||||
|     } |     } | ||||||
|     if (!library_applet) { |     if (!library_applet) { | ||||||
|         library_applet = CreateFrontendApplet(system, m_applet, applet_id, library_applet_mode); |         library_applet = | ||||||
|  |             CreateFrontendApplet(system, m_window_system, m_applet, applet_id, library_applet_mode); | ||||||
|     } |     } | ||||||
|     if (!library_applet) { |     if (!library_applet) { | ||||||
|         LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); |         LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id); | ||||||
|   | |||||||
| @@ -12,10 +12,12 @@ namespace Service::AM { | |||||||
| struct Applet; | struct Applet; | ||||||
| class ILibraryAppletAccessor; | class ILibraryAppletAccessor; | ||||||
| class IStorage; | class IStorage; | ||||||
|  | class WindowSystem; | ||||||
|  |  | ||||||
| class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { | class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> { | ||||||
| public: | public: | ||||||
|     explicit ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet); |     explicit ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet, | ||||||
|  |                                    WindowSystem& window_system); | ||||||
|     ~ILibraryAppletCreator() override; |     ~ILibraryAppletCreator() override; | ||||||
|  |  | ||||||
| private: | private: | ||||||
| @@ -29,6 +31,7 @@ private: | |||||||
|     Result CreateHandleStorage(Out<SharedPointer<IStorage>> out_storage, s64 size, |     Result CreateHandleStorage(Out<SharedPointer<IStorage>> out_storage, s64 size, | ||||||
|                                InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle); |                                InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle); | ||||||
|  |  | ||||||
|  |     WindowSystem& m_window_system; | ||||||
|     const std::shared_ptr<Applet> m_applet; |     const std::shared_ptr<Applet> m_applet; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -19,9 +19,9 @@ | |||||||
| namespace Service::AM { | namespace Service::AM { | ||||||
|  |  | ||||||
| ILibraryAppletProxy::ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, | ILibraryAppletProxy::ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, | ||||||
|                                          Kernel::KProcess* process) |                                          Kernel::KProcess* process, WindowSystem& window_system) | ||||||
|     : ServiceFramework{system_, "ILibraryAppletProxy"}, m_process{process}, m_applet{ |     : ServiceFramework{system_, "ILibraryAppletProxy"}, | ||||||
|                                                                                 std::move(applet)} { |       m_window_system{window_system}, m_process{process}, m_applet{std::move(applet)} { | ||||||
|     // clang-format off |     // clang-format off | ||||||
|     static const FunctionInfo functions[] = { |     static const FunctionInfo functions[] = { | ||||||
|         {0, D<&ILibraryAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"}, |         {0, D<&ILibraryAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"}, | ||||||
| @@ -75,7 +75,7 @@ Result ILibraryAppletProxy::GetDebugFunctions( | |||||||
| Result ILibraryAppletProxy::GetWindowController( | Result ILibraryAppletProxy::GetWindowController( | ||||||
|     Out<SharedPointer<IWindowController>> out_window_controller) { |     Out<SharedPointer<IWindowController>> out_window_controller) { | ||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|     *out_window_controller = std::make_shared<IWindowController>(system, m_applet); |     *out_window_controller = std::make_shared<IWindowController>(system, m_applet, m_window_system); | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -96,7 +96,8 @@ Result ILibraryAppletProxy::GetCommonStateGetter( | |||||||
| Result ILibraryAppletProxy::GetLibraryAppletCreator( | Result ILibraryAppletProxy::GetLibraryAppletCreator( | ||||||
|     Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) { |     Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) { | ||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|     *out_library_applet_creator = std::make_shared<ILibraryAppletCreator>(system, m_applet); |     *out_library_applet_creator = | ||||||
|  |         std::make_shared<ILibraryAppletCreator>(system, m_applet, m_window_system); | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -118,7 +119,8 @@ Result ILibraryAppletProxy::GetAppletCommonFunctions( | |||||||
| Result ILibraryAppletProxy::GetHomeMenuFunctions( | Result ILibraryAppletProxy::GetHomeMenuFunctions( | ||||||
|     Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions) { |     Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions) { | ||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|     *out_home_menu_functions = std::make_shared<IHomeMenuFunctions>(system, m_applet); |     *out_home_menu_functions = | ||||||
|  |         std::make_shared<IHomeMenuFunctions>(system, m_applet, m_window_system); | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -21,11 +21,12 @@ class ILibraryAppletSelfAccessor; | |||||||
| class IProcessWindingController; | class IProcessWindingController; | ||||||
| class ISelfController; | class ISelfController; | ||||||
| class IWindowController; | class IWindowController; | ||||||
|  | class WindowSystem; | ||||||
|  |  | ||||||
| class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { | class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> { | ||||||
| public: | public: | ||||||
|     explicit ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, |     explicit ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, | ||||||
|                                  Kernel::KProcess* process); |                                  Kernel::KProcess* process, WindowSystem& window_system); | ||||||
|     ~ILibraryAppletProxy(); |     ~ILibraryAppletProxy(); | ||||||
|  |  | ||||||
| private: | private: | ||||||
| @@ -47,6 +48,7 @@ private: | |||||||
|     Result GetGlobalStateController( |     Result GetGlobalStateController( | ||||||
|         Out<SharedPointer<IGlobalStateController>> out_global_state_controller); |         Out<SharedPointer<IGlobalStateController>> out_global_state_controller); | ||||||
|  |  | ||||||
|  |     WindowSystem& m_window_system; | ||||||
|     Kernel::KProcess* const m_process; |     Kernel::KProcess* const m_process; | ||||||
|     const std::shared_ptr<Applet> m_applet; |     const std::shared_ptr<Applet> m_applet; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -176,8 +176,7 @@ Result ILibraryAppletSelfAccessor::GetMainAppletStorageId(Out<FileSys::StorageId | |||||||
|  |  | ||||||
| Result ILibraryAppletSelfAccessor::ExitProcessAndReturn() { | Result ILibraryAppletSelfAccessor::ExitProcessAndReturn() { | ||||||
|     LOG_INFO(Service_AM, "called"); |     LOG_INFO(Service_AM, "called"); | ||||||
|     system.GetAppletManager().TerminateAndRemoveApplet(m_applet->aruid); |     m_applet->process->Terminate(); | ||||||
|     m_broker->SignalCompletion(); |  | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -86,8 +86,7 @@ ISelfController::~ISelfController() { | |||||||
| Result ISelfController::Exit() { | Result ISelfController::Exit() { | ||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|  |  | ||||||
|     // TODO |     m_applet->process->Terminate(); | ||||||
|     system.Exit(); |  | ||||||
|  |  | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
| @@ -95,7 +94,16 @@ Result ISelfController::Exit() { | |||||||
| Result ISelfController::LockExit() { | Result ISelfController::LockExit() { | ||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|  |  | ||||||
|     system.SetExitLocked(true); |     std::scoped_lock lk{m_applet->lock}; | ||||||
|  |  | ||||||
|  |     if (m_applet->lifecycle_manager.GetExitRequested()) { | ||||||
|  |         // With exit already requested, ignore and terminate immediately. | ||||||
|  |         m_applet->process->Terminate(); | ||||||
|  |     } else { | ||||||
|  |         // Otherwise, set exit lock state. | ||||||
|  |         m_applet->exit_locked = true; | ||||||
|  |         system.SetExitLocked(true); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
| @@ -103,10 +111,13 @@ Result ISelfController::LockExit() { | |||||||
| Result ISelfController::UnlockExit() { | Result ISelfController::UnlockExit() { | ||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|  |  | ||||||
|  |     std::scoped_lock lk{m_applet->lock}; | ||||||
|  |  | ||||||
|  |     m_applet->exit_locked = false; | ||||||
|     system.SetExitLocked(false); |     system.SetExitLocked(false); | ||||||
|  |  | ||||||
|     if (system.GetExitRequested()) { |     if (m_applet->lifecycle_manager.GetExitRequested()) { | ||||||
|         system.Exit(); |         m_applet->process->Terminate(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| @@ -155,7 +166,7 @@ Result ISelfController::SetOperationModeChangedNotification(bool enabled) { | |||||||
|     LOG_INFO(Service_AM, "called, enabled={}", enabled); |     LOG_INFO(Service_AM, "called, enabled={}", enabled); | ||||||
|  |  | ||||||
|     std::scoped_lock lk{m_applet->lock}; |     std::scoped_lock lk{m_applet->lock}; | ||||||
|     m_applet->operation_mode_changed_notification_enabled = enabled; |     m_applet->lifecycle_manager.SetOperationModeChangedNotificationEnabled(enabled); | ||||||
|  |  | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
| @@ -164,17 +175,18 @@ Result ISelfController::SetPerformanceModeChangedNotification(bool enabled) { | |||||||
|     LOG_INFO(Service_AM, "called, enabled={}", enabled); |     LOG_INFO(Service_AM, "called, enabled={}", enabled); | ||||||
|  |  | ||||||
|     std::scoped_lock lk{m_applet->lock}; |     std::scoped_lock lk{m_applet->lock}; | ||||||
|     m_applet->performance_mode_changed_notification_enabled = enabled; |     m_applet->lifecycle_manager.SetPerformanceModeChangedNotificationEnabled(enabled); | ||||||
|  |  | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
| Result ISelfController::SetFocusHandlingMode(bool notify, bool background, bool suspend) { | Result ISelfController::SetFocusHandlingMode(bool notify, bool background, bool suspend) { | ||||||
|     LOG_WARNING(Service_AM, "(STUBBED) called, notify={} background={} suspend={}", notify, |     LOG_INFO(Service_AM, "called, notify={} background={} suspend={}", notify, background, suspend); | ||||||
|                 background, suspend); |  | ||||||
|  |  | ||||||
|     std::scoped_lock lk{m_applet->lock}; |     std::scoped_lock lk{m_applet->lock}; | ||||||
|     m_applet->focus_handling_mode = {notify, background, suspend}; |     m_applet->lifecycle_manager.SetFocusStateChangedNotificationEnabled(notify); | ||||||
|  |     m_applet->lifecycle_manager.SetFocusHandlingMode(suspend); | ||||||
|  |     m_applet->UpdateSuspensionStateLocked(true); | ||||||
|  |  | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
| @@ -183,7 +195,7 @@ Result ISelfController::SetRestartMessageEnabled(bool enabled) { | |||||||
|     LOG_INFO(Service_AM, "called, enabled={}", enabled); |     LOG_INFO(Service_AM, "called, enabled={}", enabled); | ||||||
|  |  | ||||||
|     std::scoped_lock lk{m_applet->lock}; |     std::scoped_lock lk{m_applet->lock}; | ||||||
|     m_applet->restart_message_enabled = enabled; |     m_applet->lifecycle_manager.SetResumeNotificationEnabled(enabled); | ||||||
|  |  | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
| @@ -202,7 +214,8 @@ Result ISelfController::SetOutOfFocusSuspendingEnabled(bool enabled) { | |||||||
|     LOG_INFO(Service_AM, "called, enabled={}", enabled); |     LOG_INFO(Service_AM, "called, enabled={}", enabled); | ||||||
|  |  | ||||||
|     std::scoped_lock lk{m_applet->lock}; |     std::scoped_lock lk{m_applet->lock}; | ||||||
|     m_applet->out_of_focus_suspension_enabled = enabled; |     m_applet->lifecycle_manager.SetOutOfFocusSuspendingEnabled(enabled); | ||||||
|  |     m_applet->UpdateSuspensionStateLocked(false); | ||||||
|  |  | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -19,9 +19,9 @@ | |||||||
| namespace Service::AM { | namespace Service::AM { | ||||||
|  |  | ||||||
| ISystemAppletProxy::ISystemAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, | ISystemAppletProxy::ISystemAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet, | ||||||
|                                        Kernel::KProcess* process) |                                        Kernel::KProcess* process, WindowSystem& window_system) | ||||||
|     : ServiceFramework{system_, "ISystemAppletProxy"}, m_process{process}, m_applet{ |     : ServiceFramework{system_, "ISystemAppletProxy"}, | ||||||
|                                                                                std::move(applet)} { |       m_window_system{window_system}, m_process{process}, m_applet{std::move(applet)} { | ||||||
|     // clang-format off |     // clang-format off | ||||||
|     static const FunctionInfo functions[] = { |     static const FunctionInfo functions[] = { | ||||||
|         {0, D<&ISystemAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"}, |         {0, D<&ISystemAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"}, | ||||||
| @@ -75,7 +75,7 @@ Result ISystemAppletProxy::GetDebugFunctions( | |||||||
| Result ISystemAppletProxy::GetWindowController( | Result ISystemAppletProxy::GetWindowController( | ||||||
|     Out<SharedPointer<IWindowController>> out_window_controller) { |     Out<SharedPointer<IWindowController>> out_window_controller) { | ||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|     *out_window_controller = std::make_shared<IWindowController>(system, m_applet); |     *out_window_controller = std::make_shared<IWindowController>(system, m_applet, m_window_system); | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -96,14 +96,15 @@ Result ISystemAppletProxy::GetCommonStateGetter( | |||||||
| Result ISystemAppletProxy::GetLibraryAppletCreator( | Result ISystemAppletProxy::GetLibraryAppletCreator( | ||||||
|     Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) { |     Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) { | ||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|     *out_library_applet_creator = std::make_shared<ILibraryAppletCreator>(system, m_applet); |     *out_library_applet_creator = | ||||||
|  |         std::make_shared<ILibraryAppletCreator>(system, m_applet, m_window_system); | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
| Result ISystemAppletProxy::GetApplicationCreator( | Result ISystemAppletProxy::GetApplicationCreator( | ||||||
|     Out<SharedPointer<IApplicationCreator>> out_application_creator) { |     Out<SharedPointer<IApplicationCreator>> out_application_creator) { | ||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|     *out_application_creator = std::make_shared<IApplicationCreator>(system); |     *out_application_creator = std::make_shared<IApplicationCreator>(system, m_window_system); | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -117,7 +118,8 @@ Result ISystemAppletProxy::GetAppletCommonFunctions( | |||||||
| Result ISystemAppletProxy::GetHomeMenuFunctions( | Result ISystemAppletProxy::GetHomeMenuFunctions( | ||||||
|     Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions) { |     Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions) { | ||||||
|     LOG_DEBUG(Service_AM, "called"); |     LOG_DEBUG(Service_AM, "called"); | ||||||
|     *out_home_menu_functions = std::make_shared<IHomeMenuFunctions>(system, m_applet); |     *out_home_menu_functions = | ||||||
|  |         std::make_shared<IHomeMenuFunctions>(system, m_applet, m_window_system); | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -21,11 +21,12 @@ class ILibraryAppletCreator; | |||||||
| class IProcessWindingController; | class IProcessWindingController; | ||||||
| class ISelfController; | class ISelfController; | ||||||
| class IWindowController; | class IWindowController; | ||||||
|  | class WindowSystem; | ||||||
|  |  | ||||||
| class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { | class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> { | ||||||
| public: | public: | ||||||
|     explicit ISystemAppletProxy(Core::System& system, std::shared_ptr<Applet> applet, |     explicit ISystemAppletProxy(Core::System& system, std::shared_ptr<Applet> applet, | ||||||
|                                 Kernel::KProcess* process); |                                 Kernel::KProcess* process, WindowSystem& window_system); | ||||||
|     ~ISystemAppletProxy(); |     ~ISystemAppletProxy(); | ||||||
|  |  | ||||||
| private: | private: | ||||||
| @@ -46,6 +47,7 @@ private: | |||||||
|     Result GetGlobalStateController( |     Result GetGlobalStateController( | ||||||
|         Out<SharedPointer<IGlobalStateController>> out_global_state_controller); |         Out<SharedPointer<IGlobalStateController>> out_global_state_controller); | ||||||
|  |  | ||||||
|  |     WindowSystem& m_window_system; | ||||||
|     Kernel::KProcess* const m_process; |     Kernel::KProcess* const m_process; | ||||||
|     const std::shared_ptr<Applet> m_applet; |     const std::shared_ptr<Applet> m_applet; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -4,12 +4,15 @@ | |||||||
| #include "core/hle/service/am/applet.h" | #include "core/hle/service/am/applet.h" | ||||||
| #include "core/hle/service/am/applet_manager.h" | #include "core/hle/service/am/applet_manager.h" | ||||||
| #include "core/hle/service/am/service/window_controller.h" | #include "core/hle/service/am/service/window_controller.h" | ||||||
|  | #include "core/hle/service/am/window_system.h" | ||||||
| #include "core/hle/service/cmif_serialization.h" | #include "core/hle/service/cmif_serialization.h" | ||||||
|  |  | ||||||
| namespace Service::AM { | namespace Service::AM { | ||||||
|  |  | ||||||
| IWindowController::IWindowController(Core::System& system_, std::shared_ptr<Applet> applet) | IWindowController::IWindowController(Core::System& system_, std::shared_ptr<Applet> applet, | ||||||
|     : ServiceFramework{system_, "IWindowController"}, m_applet{std::move(applet)} { |                                      WindowSystem& window_system) | ||||||
|  |     : ServiceFramework{system_, "IWindowController"}, | ||||||
|  |       m_window_system{window_system}, m_applet{std::move(applet)} { | ||||||
|     // clang-format off |     // clang-format off | ||||||
|     static const FunctionInfo functions[] = { |     static const FunctionInfo functions[] = { | ||||||
|         {0, nullptr, "CreateWindow"}, |         {0, nullptr, "CreateWindow"}, | ||||||
| @@ -63,17 +66,9 @@ Result IWindowController::RejectToChangeIntoBackground() { | |||||||
| } | } | ||||||
|  |  | ||||||
| Result IWindowController::SetAppletWindowVisibility(bool visible) { | Result IWindowController::SetAppletWindowVisibility(bool visible) { | ||||||
|     m_applet->display_layer_manager.SetWindowVisibility(visible); |     LOG_INFO(Service_AM, "called"); | ||||||
|     m_applet->hid_registration.EnableAppletToGetInput(visible); |  | ||||||
|  |  | ||||||
|     if (visible) { |     m_window_system.RequestAppletVisibilityState(*m_applet, visible); | ||||||
|         m_applet->message_queue.PushMessage(AppletMessage::ChangeIntoForeground); |  | ||||||
|         m_applet->focus_state = FocusState::InFocus; |  | ||||||
|     } else { |  | ||||||
|         m_applet->focus_state = FocusState::NotInFocus; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     m_applet->message_queue.PushMessage(AppletMessage::FocusStateChanged); |  | ||||||
|  |  | ||||||
|     R_SUCCEED(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -9,10 +9,12 @@ | |||||||
| namespace Service::AM { | namespace Service::AM { | ||||||
|  |  | ||||||
| struct Applet; | struct Applet; | ||||||
|  | class WindowSystem; | ||||||
|  |  | ||||||
| class IWindowController final : public ServiceFramework<IWindowController> { | class IWindowController final : public ServiceFramework<IWindowController> { | ||||||
| public: | public: | ||||||
|     explicit IWindowController(Core::System& system_, std::shared_ptr<Applet> applet); |     explicit IWindowController(Core::System& system_, std::shared_ptr<Applet> applet, | ||||||
|  |                                WindowSystem& window_system); | ||||||
|     ~IWindowController() override; |     ~IWindowController() override; | ||||||
|  |  | ||||||
| private: | private: | ||||||
| @@ -24,6 +26,7 @@ private: | |||||||
|     Result SetAppletWindowVisibility(bool visible); |     Result SetAppletWindowVisibility(bool visible); | ||||||
|     Result SetAppletGpuTimeSlice(s64 time_slice); |     Result SetAppletGpuTimeSlice(s64 time_slice); | ||||||
|  |  | ||||||
|  |     WindowSystem& m_window_system; | ||||||
|     const std::shared_ptr<Applet> m_applet; |     const std::shared_ptr<Applet> m_applet; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -23,11 +23,7 @@ void LoopProcess(Core::System& system) { | |||||||
|     std::shared_ptr<ResourceManager> resource_manager = |     std::shared_ptr<ResourceManager> resource_manager = | ||||||
|         std::make_shared<ResourceManager>(system, firmware_settings); |         std::make_shared<ResourceManager>(system, firmware_settings); | ||||||
|  |  | ||||||
|     // TODO: Remove this hack when am is emulated properly. |  | ||||||
|     resource_manager->Initialize(); |     resource_manager->Initialize(); | ||||||
|     resource_manager->RegisterAppletResourceUserId(system.ApplicationProcess()->GetProcessId(), |  | ||||||
|                                                    true); |  | ||||||
|     resource_manager->SetAruidValidForVibration(system.ApplicationProcess()->GetProcessId(), true); |  | ||||||
|  |  | ||||||
|     server_manager->RegisterNamedService( |     server_manager->RegisterNamedService( | ||||||
|         "hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings)); |         "hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings)); | ||||||
|   | |||||||
| @@ -49,8 +49,7 @@ struct Memory::Impl { | |||||||
|     void SetCurrentPageTable(Kernel::KProcess& process) { |     void SetCurrentPageTable(Kernel::KProcess& process) { | ||||||
|         current_page_table = &process.GetPageTable().GetImpl(); |         current_page_table = &process.GetPageTable().GetImpl(); | ||||||
|  |  | ||||||
|         if (std::addressof(process) == system.ApplicationProcess() && |         if (process.IsApplication() && Settings::IsFastmemEnabled()) { | ||||||
|             Settings::IsFastmemEnabled()) { |  | ||||||
|             current_page_table->fastmem_arena = system.DeviceMemory().buffer.VirtualBasePointer(); |             current_page_table->fastmem_arena = system.DeviceMemory().buffer.VirtualBasePointer(); | ||||||
|         } else { |         } else { | ||||||
|             current_page_table->fastmem_arena = nullptr; |             current_page_table->fastmem_arena = nullptr; | ||||||
|   | |||||||
| @@ -248,16 +248,19 @@ void Vic::ReadProgressiveY8__V8U8_N420(const SlotStruct& slot, | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) | #if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) | ||||||
|  |     const auto alpha_linear{static_cast<u16>(slot.config.planar_alpha.Value())}; | ||||||
|     const auto alpha = |     const auto alpha = | ||||||
|         _mm_slli_epi64(_mm_set1_epi64x(static_cast<s64>(slot.config.planar_alpha.Value())), 48); |         _mm_slli_epi64(_mm_set1_epi64x(static_cast<s64>(slot.config.planar_alpha.Value())), 48); | ||||||
|  |  | ||||||
|     const auto shuffle_mask = _mm_set_epi8(13, 15, 14, 12, 9, 11, 10, 8, 5, 7, 6, 4, 1, 3, 2, 0); |     const auto shuffle_mask = _mm_set_epi8(13, 15, 14, 12, 9, 11, 10, 8, 5, 7, 6, 4, 1, 3, 2, 0); | ||||||
|  |     const auto sse_aligned_width = Common::AlignDown(in_luma_width, 16); | ||||||
|  |  | ||||||
|     for (s32 y = 0; y < in_luma_height; y++) { |     for (s32 y = 0; y < in_luma_height; y++) { | ||||||
|         const auto src_luma{y * in_luma_stride}; |         const auto src_luma{y * in_luma_stride}; | ||||||
|         const auto src_chroma{(y / 2) * in_chroma_stride}; |         const auto src_chroma{(y / 2) * in_chroma_stride}; | ||||||
|         const auto dst{y * out_luma_stride}; |         const auto dst{y * out_luma_stride}; | ||||||
|         for (s32 x = 0; x < in_luma_width; x += 16) { |         s32 x = 0; | ||||||
|  |         for (; x < sse_aligned_width; x += 16) { | ||||||
|             // clang-format off |             // clang-format off | ||||||
|             // Prefetch next iteration's memory |             // Prefetch next iteration's memory | ||||||
|             _mm_prefetch((const char*)&luma_buffer[src_luma + x + 16], _MM_HINT_T0); |             _mm_prefetch((const char*)&luma_buffer[src_luma + x + 16], _MM_HINT_T0); | ||||||
| @@ -381,6 +384,23 @@ void Vic::ReadProgressiveY8__V8U8_N420(const SlotStruct& slot, | |||||||
|  |  | ||||||
|             // clang-format on |             // clang-format on | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         for (; x < in_luma_width; x++) { | ||||||
|  |             slot_surface[dst + x].r = static_cast<u16>(luma_buffer[src_luma + x] << 2); | ||||||
|  |             // Chroma samples are duplicated horizontally and vertically. | ||||||
|  |             if constexpr (Planar) { | ||||||
|  |                 slot_surface[dst + x].g = | ||||||
|  |                     static_cast<u16>(chroma_u_buffer[src_chroma + x / 2] << 2); | ||||||
|  |                 slot_surface[dst + x].b = | ||||||
|  |                     static_cast<u16>(chroma_v_buffer[src_chroma + x / 2] << 2); | ||||||
|  |             } else { | ||||||
|  |                 slot_surface[dst + x].g = | ||||||
|  |                     static_cast<u16>(chroma_u_buffer[src_chroma + (x & ~1) + 0] << 2); | ||||||
|  |                 slot_surface[dst + x].b = | ||||||
|  |                     static_cast<u16>(chroma_u_buffer[src_chroma + (x & ~1) + 1] << 2); | ||||||
|  |             } | ||||||
|  |             slot_surface[dst + x].a = alpha_linear; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| #else | #else | ||||||
|     DecodeLinear(); |     DecodeLinear(); | ||||||
| @@ -827,11 +847,14 @@ void Vic::WriteY8__V8U8_N420(const OutputSurfaceConfig& output_surface_config) { | |||||||
|         // luma_mask   = [00 00] [00 00] [00 00] [FF FF] [00 00] [00 00] [00 00] [FF FF] |         // luma_mask   = [00 00] [00 00] [00 00] [FF FF] [00 00] [00 00] [00 00] [FF FF] | ||||||
|         const auto luma_mask = _mm_set_epi16(0, 0, 0, -1, 0, 0, 0, -1); |         const auto luma_mask = _mm_set_epi16(0, 0, 0, -1, 0, 0, 0, -1); | ||||||
|  |  | ||||||
|  |         const auto sse_aligned_width = Common::AlignDown(surface_width, 16); | ||||||
|  |  | ||||||
|         for (u32 y = 0; y < surface_height; ++y) { |         for (u32 y = 0; y < surface_height; ++y) { | ||||||
|             const auto src = y * surface_stride; |             const auto src = y * surface_stride; | ||||||
|             const auto dst_luma = y * out_luma_stride; |             const auto dst_luma = y * out_luma_stride; | ||||||
|             const auto dst_chroma = (y / 2) * out_chroma_stride; |             const auto dst_chroma = (y / 2) * out_chroma_stride; | ||||||
|             for (u32 x = 0; x < surface_width; x += 16) { |             u32 x = 0; | ||||||
|  |             for (; x < sse_aligned_width; x += 16) { | ||||||
|                 // clang-format off |                 // clang-format off | ||||||
|                 // Prefetch the next cache lines, 2 per iteration |                 // Prefetch the next cache lines, 2 per iteration | ||||||
|                 _mm_prefetch((const char*)&output_surface[src + x + 16], _MM_HINT_T0); |                 _mm_prefetch((const char*)&output_surface[src + x + 16], _MM_HINT_T0); | ||||||
| @@ -949,6 +972,16 @@ void Vic::WriteY8__V8U8_N420(const OutputSurfaceConfig& output_surface_config) { | |||||||
|  |  | ||||||
|                 // clang-format on |                 // clang-format on | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             const auto src_chroma = y * surface_stride; | ||||||
|  |             for (; x < surface_width; x += 2) { | ||||||
|  |                 out_luma[dst_luma + x + 0] = static_cast<u8>(output_surface[src + x + 0].r >> 2); | ||||||
|  |                 out_luma[dst_luma + x + 1] = static_cast<u8>(output_surface[src + x + 1].r >> 2); | ||||||
|  |                 out_chroma[dst_chroma + x + 0] = | ||||||
|  |                     static_cast<u8>(output_surface[src_chroma + x].g >> 2); | ||||||
|  |                 out_chroma[dst_chroma + x + 1] = | ||||||
|  |                     static_cast<u8>(output_surface[src_chroma + x].b >> 2); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| #else | #else | ||||||
|         DecodeLinear(out_luma, out_chroma); |         DecodeLinear(out_luma, out_chroma); | ||||||
| @@ -1083,10 +1116,14 @@ void Vic::WriteABGR(const OutputSurfaceConfig& output_surface_config) { | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) | #if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) | ||||||
|  |         constexpr size_t SseAlignment = 16; | ||||||
|  |         const auto sse_aligned_width = Common::AlignDown(surface_width, SseAlignment); | ||||||
|  |  | ||||||
|         for (u32 y = 0; y < surface_height; y++) { |         for (u32 y = 0; y < surface_height; y++) { | ||||||
|             const auto src = y * surface_stride; |             const auto src = y * surface_stride; | ||||||
|             const auto dst = y * out_luma_stride; |             const auto dst = y * out_luma_stride; | ||||||
|             for (u32 x = 0; x < surface_width; x += 16) { |             u32 x = 0; | ||||||
|  |             for (; x < sse_aligned_width; x += SseAlignment) { | ||||||
|                 // clang-format off |                 // clang-format off | ||||||
|                 // Prefetch the next 2 cache lines |                 // Prefetch the next 2 cache lines | ||||||
|                 _mm_prefetch((const char*)&output_surface[src + x + 16], _MM_HINT_T0); |                 _mm_prefetch((const char*)&output_surface[src + x + 16], _MM_HINT_T0); | ||||||
| @@ -1146,6 +1183,20 @@ void Vic::WriteABGR(const OutputSurfaceConfig& output_surface_config) { | |||||||
|  |  | ||||||
|                 // clang-format on |                 // clang-format on | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             for (; x < surface_width; x++) { | ||||||
|  |                 if constexpr (Format == VideoPixelFormat::A8R8G8B8) { | ||||||
|  |                     out_buffer[dst + x * 4 + 0] = static_cast<u8>(output_surface[src + x].b >> 2); | ||||||
|  |                     out_buffer[dst + x * 4 + 1] = static_cast<u8>(output_surface[src + x].g >> 2); | ||||||
|  |                     out_buffer[dst + x * 4 + 2] = static_cast<u8>(output_surface[src + x].r >> 2); | ||||||
|  |                     out_buffer[dst + x * 4 + 3] = static_cast<u8>(output_surface[src + x].a >> 2); | ||||||
|  |                 } else { | ||||||
|  |                     out_buffer[dst + x * 4 + 0] = static_cast<u8>(output_surface[src + x].r >> 2); | ||||||
|  |                     out_buffer[dst + x * 4 + 1] = static_cast<u8>(output_surface[src + x].g >> 2); | ||||||
|  |                     out_buffer[dst + x * 4 + 2] = static_cast<u8>(output_surface[src + x].b >> 2); | ||||||
|  |                     out_buffer[dst + x * 4 + 3] = static_cast<u8>(output_surface[src + x].a >> 2); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| #else | #else | ||||||
|         DecodeLinear(out_buffer); |         DecodeLinear(out_buffer); | ||||||
|   | |||||||
| @@ -2114,7 +2114,9 @@ void TextureCache<P>::TrackImage(ImageBase& image, ImageId image_id) { | |||||||
|     ASSERT(False(image.flags & ImageFlagBits::Tracked)); |     ASSERT(False(image.flags & ImageFlagBits::Tracked)); | ||||||
|     image.flags |= ImageFlagBits::Tracked; |     image.flags |= ImageFlagBits::Tracked; | ||||||
|     if (False(image.flags & ImageFlagBits::Sparse)) { |     if (False(image.flags & ImageFlagBits::Sparse)) { | ||||||
|         device_memory.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, 1); |         if (image.cpu_addr < ~(1ULL << 40)) { | ||||||
|  |             device_memory.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, 1); | ||||||
|  |         } | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     if (True(image.flags & ImageFlagBits::Registered)) { |     if (True(image.flags & ImageFlagBits::Registered)) { | ||||||
| @@ -2140,7 +2142,9 @@ void TextureCache<P>::UntrackImage(ImageBase& image, ImageId image_id) { | |||||||
|     ASSERT(True(image.flags & ImageFlagBits::Tracked)); |     ASSERT(True(image.flags & ImageFlagBits::Tracked)); | ||||||
|     image.flags &= ~ImageFlagBits::Tracked; |     image.flags &= ~ImageFlagBits::Tracked; | ||||||
|     if (False(image.flags & ImageFlagBits::Sparse)) { |     if (False(image.flags & ImageFlagBits::Sparse)) { | ||||||
|         device_memory.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, -1); |         if (image.cpu_addr < ~(1ULL << 40)) { | ||||||
|  |             device_memory.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, -1); | ||||||
|  |         } | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     ASSERT(True(image.flags & ImageFlagBits::Registered)); |     ASSERT(True(image.flags & ImageFlagBits::Registered)); | ||||||
|   | |||||||
| @@ -1461,7 +1461,6 @@ void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) { | |||||||
|             OnPauseGame(); |             OnPauseGame(); | ||||||
|         } else if (!emu_thread->IsRunning() && auto_paused && state == Qt::ApplicationActive) { |         } else if (!emu_thread->IsRunning() && auto_paused && state == Qt::ApplicationActive) { | ||||||
|             auto_paused = false; |             auto_paused = false; | ||||||
|             RequestGameResume(); |  | ||||||
|             OnStartGame(); |             OnStartGame(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -1702,7 +1701,6 @@ void GMainWindow::OnPrepareForSleep(bool prepare_sleep) { | |||||||
|     } else { |     } else { | ||||||
|         if (!emu_thread->IsRunning() && auto_paused) { |         if (!emu_thread->IsRunning() && auto_paused) { | ||||||
|             auto_paused = false; |             auto_paused = false; | ||||||
|             RequestGameResume(); |  | ||||||
|             OnStartGame(); |             OnStartGame(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -3457,7 +3455,6 @@ void GMainWindow::OnPauseContinueGame() { | |||||||
|         if (emu_thread->IsRunning()) { |         if (emu_thread->IsRunning()) { | ||||||
|             OnPauseGame(); |             OnPauseGame(); | ||||||
|         } else { |         } else { | ||||||
|             RequestGameResume(); |  | ||||||
|             OnStartGame(); |             OnStartGame(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -5013,10 +5010,6 @@ void GMainWindow::RequestGameExit() { | |||||||
|     system->GetAppletManager().RequestExit(); |     system->GetAppletManager().RequestExit(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void GMainWindow::RequestGameResume() { |  | ||||||
|     system->GetAppletManager().RequestResume(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void GMainWindow::filterBarSetChecked(bool state) { | void GMainWindow::filterBarSetChecked(bool state) { | ||||||
|     ui->action_Show_Filter_Bar->setChecked(state); |     ui->action_Show_Filter_Bar->setChecked(state); | ||||||
|     emit(OnToggleFilterBar()); |     emit(OnToggleFilterBar()); | ||||||
|   | |||||||
| @@ -310,7 +310,6 @@ private: | |||||||
|     bool ConfirmChangeGame(); |     bool ConfirmChangeGame(); | ||||||
|     bool ConfirmForceLockedExit(); |     bool ConfirmForceLockedExit(); | ||||||
|     void RequestGameExit(); |     void RequestGameExit(); | ||||||
|     void RequestGameResume(); |  | ||||||
|     void changeEvent(QEvent* event) override; |     void changeEvent(QEvent* event) override; | ||||||
|     void closeEvent(QCloseEvent* event) override; |     void closeEvent(QCloseEvent* event) override; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user