early-access version 4173
This commit is contained in:
parent
09fb494463
commit
6cc741a886
@ -1,7 +1,7 @@
|
||||
yuzu emulator early access
|
||||
=============
|
||||
|
||||
This is the source code for early-access 4172.
|
||||
This is the source code for early-access 4173.
|
||||
|
||||
## 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
|
||||
#define SSE2NEON_H
|
||||
|
||||
|
@ -401,14 +401,16 @@ add_library(core STATIC
|
||||
hle/service/am/am_types.h
|
||||
hle/service/am/applet.cpp
|
||||
hle/service/am/applet.h
|
||||
hle/service/am/applet_manager.cpp
|
||||
hle/service/am/applet_data_broker.cpp
|
||||
hle/service/am/applet_data_broker.h
|
||||
hle/service/am/applet_manager.cpp
|
||||
hle/service/am/applet_manager.h
|
||||
hle/service/am/applet_message_queue.cpp
|
||||
hle/service/am/applet_message_queue.h
|
||||
hle/service/am/button_poller.cpp
|
||||
hle/service/am/button_poller.h
|
||||
hle/service/am/display_layer_manager.cpp
|
||||
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.h
|
||||
hle/service/am/frontend/applet_controller.cpp
|
||||
@ -434,8 +436,12 @@ add_library(core STATIC
|
||||
hle/service/am/hid_registration.h
|
||||
hle/service/am/library_applet_storage.cpp
|
||||
hle/service/am/library_applet_storage.h
|
||||
hle/service/am/process.cpp
|
||||
hle/service/am/process.h
|
||||
hle/service/am/lifecycle_manager.cpp
|
||||
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.h
|
||||
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/window_controller.cpp
|
||||
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.h
|
||||
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/mutex.cpp
|
||||
hle/service/os/mutex.h
|
||||
hle/service/os/process.cpp
|
||||
hle/service/os/process.h
|
||||
hle/service/pcie/pcie.cpp
|
||||
hle/service/pcie/pcie.h
|
||||
hle/service/pctl/parental_control_service_factory.cpp
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
@ -20,7 +19,6 @@
|
||||
#include "core/cpu_manager.h"
|
||||
#include "core/debugger/debugger.h"
|
||||
#include "core/device_memory.h"
|
||||
#include "core/file_sys/bis_factory.h"
|
||||
#include "core/file_sys/fs_filesystem.h"
|
||||
#include "core/file_sys/patch_manager.h"
|
||||
#include "core/file_sys/registered_cache.h"
|
||||
@ -38,6 +36,7 @@
|
||||
#include "core/hle/service/acc/profile_manager.h"
|
||||
#include "core/hle/service/am/applet_manager.h"
|
||||
#include "core/hle/service/am/frontend/applets.h"
|
||||
#include "core/hle/service/am/process_creation.h"
|
||||
#include "core/hle/service/apm/apm_controller.h"
|
||||
#include "core/hle/service/filesystem/filesystem.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 {
|
||||
|
||||
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,
|
||||
const std::string& path) {
|
||||
// To account for split 00+01+etc files.
|
||||
@ -297,9 +272,6 @@ struct System::Impl {
|
||||
}
|
||||
|
||||
SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) {
|
||||
/// Reset all glue registrations
|
||||
arp_manager.ResetAll();
|
||||
|
||||
telemetry_session = std::make_unique<Core::TelemetrySession>();
|
||||
|
||||
host1x_core = std::make_unique<Tegra::Host1x::Host1x>(system);
|
||||
@ -335,33 +307,17 @@ struct System::Impl {
|
||||
SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
|
||||
const std::string& filepath,
|
||||
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);
|
||||
|
||||
// Create the application process.
|
||||
auto main_process = Kernel::KProcess::Create(system.Kernel());
|
||||
Kernel::KProcess::Register(system.Kernel(), main_process);
|
||||
kernel.AppendNewProcess(main_process);
|
||||
kernel.MakeApplicationProcess(main_process);
|
||||
const auto [load_result, load_parameters] = app_loader->Load(*main_process, system);
|
||||
const auto file = GetGameFileFromPath(virtual_filesystem, filepath);
|
||||
|
||||
// Create the application process
|
||||
Loader::ResultStatus load_result{};
|
||||
std::vector<u8> control;
|
||||
auto process =
|
||||
Service::AM::CreateApplicationProcess(control, app_loader, load_result, system, file,
|
||||
params.program_id, params.program_index);
|
||||
|
||||
if (load_result != Loader::ResultStatus::Success) {
|
||||
LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result);
|
||||
ShutdownMainProcess();
|
||||
@ -370,6 +326,25 @@ struct System::Impl {
|
||||
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.
|
||||
SystemResultStatus init_result{SetupForApplicationProcess(system, emu_window)};
|
||||
if (init_result != SystemResultStatus::Success) {
|
||||
@ -379,7 +354,6 @@ struct System::Impl {
|
||||
return init_result;
|
||||
}
|
||||
|
||||
AddGlueRegistrationForProcess(*app_loader, *main_process);
|
||||
telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider);
|
||||
|
||||
// Initialize cheat engine
|
||||
@ -387,14 +361,9 @@ struct System::Impl {
|
||||
cheat_engine->Initialize();
|
||||
}
|
||||
|
||||
// Register with applet manager.
|
||||
applet_manager.CreateAndInsertByFrontendAppletParameters(main_process->GetProcessId(),
|
||||
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();
|
||||
// Register with applet manager
|
||||
// All threads are started, begin main process execution, now that we're in the clear
|
||||
applet_manager.CreateAndInsertByFrontendAppletParameters(std::move(process), params);
|
||||
|
||||
if (Settings::values.gamecard_inserted) {
|
||||
if (Settings::values.gamecard_current_game) {
|
||||
@ -466,7 +435,6 @@ struct System::Impl {
|
||||
kernel.SuspendEmulation(true);
|
||||
kernel.CloseServices();
|
||||
kernel.ShutdownCores();
|
||||
applet_manager.Reset();
|
||||
services.reset();
|
||||
service_manager.reset();
|
||||
fs_controller.Reset();
|
||||
@ -492,6 +460,9 @@ struct System::Impl {
|
||||
// Workarounds
|
||||
Settings::values.renderer_amdvlk_depth_bias_workaround = false;
|
||||
|
||||
// Reset all glue registrations
|
||||
arp_manager.ResetAll();
|
||||
|
||||
LOG_DEBUG(Core, "Shutdown OK");
|
||||
}
|
||||
|
||||
@ -509,31 +480,6 @@ struct System::Impl {
|
||||
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) {
|
||||
status = new_status;
|
||||
if (details) {
|
||||
|
@ -1170,6 +1170,7 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
|
||||
// Determine if we are an application.
|
||||
if (pool == KMemoryManager::Pool::Application) {
|
||||
flag |= Svc::CreateProcessFlag::IsApplication;
|
||||
m_is_application = true;
|
||||
}
|
||||
|
||||
// If we are 64-bit, create as such.
|
||||
|
@ -2,19 +2,26 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#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/application_proxy_service.h"
|
||||
#include "core/hle/service/am/window_system.h"
|
||||
#include "core/hle/service/server_manager.h"
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
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);
|
||||
|
||||
server_manager->RegisterNamedService("appletAE",
|
||||
std::make_shared<IAllSystemAppletProxiesService>(system));
|
||||
server_manager->RegisterNamedService("appletOE",
|
||||
std::make_shared<IApplicationProxyService>(system));
|
||||
server_manager->RegisterNamedService(
|
||||
"appletAE", std::make_shared<IAllSystemAppletProxiesService>(system, window_system));
|
||||
server_manager->RegisterNamedService(
|
||||
"appletOE", std::make_shared<IApplicationProxyService>(system, window_system));
|
||||
ServerManager::RunServer(std::move(server_manager));
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ namespace Service::AM {
|
||||
|
||||
constexpr Result ResultNoDataInChannel{ErrorModule::AM, 2};
|
||||
constexpr Result ResultNoMessages{ErrorModule::AM, 3};
|
||||
constexpr Result ResultLibraryAppletTerminated{ErrorModule::AM, 22};
|
||||
constexpr Result ResultInvalidOffset{ErrorModule::AM, 503};
|
||||
constexpr Result ResultInvalidStorageType{ErrorModule::AM, 511};
|
||||
constexpr Result ResultFatalSectionCountImbalance{ErrorModule::AM, 512};
|
||||
|
@ -61,12 +61,6 @@ enum class ScreenshotPermission : u32 {
|
||||
Disable = 2,
|
||||
};
|
||||
|
||||
struct FocusHandlingMode {
|
||||
bool notify;
|
||||
bool background;
|
||||
bool suspend;
|
||||
};
|
||||
|
||||
enum class IdleTimeDetectionExtension : u32 {
|
||||
Disabled = 0,
|
||||
Extended = 1,
|
||||
@ -239,7 +233,6 @@ struct ApplicationPlayStatistics {
|
||||
static_assert(sizeof(ApplicationPlayStatistics) == 0x18,
|
||||
"ApplicationPlayStatistics has incorrect size.");
|
||||
|
||||
using AppletResourceUserId = u64;
|
||||
using ProgramId = u64;
|
||||
|
||||
struct Applet;
|
||||
|
@ -1,27 +1,71 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/scope_exit.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_manager.h"
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
Applet::Applet(Core::System& system, std::unique_ptr<Process> process_)
|
||||
: context(system, "Applet"), message_queue(system), process(std::move(process_)),
|
||||
hid_registration(system, *process), gpu_error_detected_event(context),
|
||||
friend_invitation_storage_channel_event(context), notification_storage_channel_event(context),
|
||||
health_warning_disappeared_system_event(context), acquired_sleep_lock_event(context),
|
||||
pop_from_general_channel_event(context), library_applet_launchable_event(context),
|
||||
accumulated_suspended_tick_changed_event(context), sleep_lock_event(context) {
|
||||
Applet::Applet(Core::System& system, std::unique_ptr<Process> process_, bool is_application)
|
||||
: context(system, "Applet"), lifecycle_manager(system, context, is_application),
|
||||
process(std::move(process_)), hid_registration(system, *process),
|
||||
gpu_error_detected_event(context), friend_invitation_storage_channel_event(context),
|
||||
notification_storage_channel_event(context), health_warning_disappeared_system_event(context),
|
||||
acquired_sleep_lock_event(context), pop_from_general_channel_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();
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -3,25 +3,28 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <mutex>
|
||||
|
||||
#include "common/math_util.h"
|
||||
#include "core/hle/service/apm/apm_controller.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/os/event.h"
|
||||
#include "core/hle/service/os/process.h"
|
||||
#include "core/hle/service/service.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/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 {
|
||||
|
||||
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();
|
||||
|
||||
// Lock
|
||||
@ -30,11 +33,13 @@ struct Applet {
|
||||
// Event creation helper
|
||||
KernelHelpers::ServiceContext context;
|
||||
|
||||
// Applet message queue
|
||||
AppletMessageQueue message_queue;
|
||||
// Lifecycle manager
|
||||
LifecycleManager lifecycle_manager;
|
||||
|
||||
// Process
|
||||
std::unique_ptr<Process> process;
|
||||
std::optional<ProcessHolder> process_holder;
|
||||
bool is_process_running{};
|
||||
|
||||
// Creation state
|
||||
AppletId applet_id{};
|
||||
@ -75,11 +80,9 @@ struct Applet {
|
||||
bool game_play_recording_supported{};
|
||||
GamePlayRecordingState game_play_recording_state{GamePlayRecordingState::Disabled};
|
||||
bool jit_service_launched{};
|
||||
bool is_running{};
|
||||
bool application_crash_report_enabled{};
|
||||
|
||||
// Common state
|
||||
FocusState focus_state{};
|
||||
bool sleep_lock_enabled{};
|
||||
bool vr_mode_enabled{};
|
||||
bool lcd_backlight_off_enabled{};
|
||||
@ -93,15 +96,12 @@ struct Applet {
|
||||
// Caller applet
|
||||
std::weak_ptr<Applet> caller_applet{};
|
||||
std::shared_ptr<AppletDataBroker> caller_applet_broker{};
|
||||
std::list<std::shared_ptr<Applet>> child_applets{};
|
||||
bool is_completed{};
|
||||
|
||||
// Self state
|
||||
bool exit_locked{};
|
||||
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{};
|
||||
bool handles_request_to_display{};
|
||||
ScreenshotPermission screenshot_permission{};
|
||||
@ -110,6 +110,9 @@ struct Applet {
|
||||
u64 suspended_ticks{};
|
||||
bool album_image_taken_notification_enabled{};
|
||||
bool record_volume_muted{};
|
||||
bool is_activity_runnable{};
|
||||
bool is_interactible{true};
|
||||
bool window_visible{true};
|
||||
|
||||
// Events
|
||||
Event gpu_error_detected_event;
|
||||
@ -121,9 +124,15 @@ struct Applet {
|
||||
Event library_applet_launchable_event;
|
||||
Event accumulated_suspended_tick_changed_event;
|
||||
Event sleep_lock_event;
|
||||
Event state_changed_event;
|
||||
|
||||
// Frontend state
|
||||
std::shared_ptr<Frontend::FrontendApplet> frontend{};
|
||||
|
||||
// Process state management
|
||||
void UpdateSuspensionStateLocked(bool force_message);
|
||||
void SetInteractibleLocked(bool interactible);
|
||||
void OnProcessTerminatedLocked();
|
||||
};
|
||||
|
||||
} // namespace Service::AM
|
||||
|
@ -44,24 +44,8 @@ Kernel::KReadableEvent* AppletStorageChannel::GetEvent() {
|
||||
|
||||
AppletDataBroker::AppletDataBroker(Core::System& system_)
|
||||
: system(system_), context(system_, "AppletDataBroker"), in_data(context),
|
||||
interactive_in_data(context), out_data(context), interactive_out_data(context),
|
||||
state_changed_event(context), is_completed(false) {}
|
||||
interactive_in_data(context), out_data(context), interactive_out_data(context) {}
|
||||
|
||||
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
|
||||
|
@ -53,16 +53,6 @@ public:
|
||||
return interactive_out_data;
|
||||
}
|
||||
|
||||
Event& GetStateChangedEvent() {
|
||||
return state_changed_event;
|
||||
}
|
||||
|
||||
bool IsCompleted() const {
|
||||
return is_completed;
|
||||
}
|
||||
|
||||
void SignalCompletion();
|
||||
|
||||
private:
|
||||
Core::System& system;
|
||||
KernelHelpers::ServiceContext context;
|
||||
@ -71,10 +61,6 @@ private:
|
||||
AppletStorageChannel interactive_in_data;
|
||||
AppletStorageChannel out_data;
|
||||
AppletStorageChannel interactive_out_data;
|
||||
Event state_changed_event;
|
||||
|
||||
std::mutex lock;
|
||||
bool is_completed;
|
||||
};
|
||||
|
||||
} // 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_software_keyboard_types.h"
|
||||
#include "core/hle/service/am/service/storage.h"
|
||||
#include "core/hle/service/am/window_system.h"
|
||||
#include "hid_core/hid_types.h"
|
||||
|
||||
namespace Service::AM {
|
||||
@ -225,49 +226,46 @@ void PushInShowSoftwareKeyboard(Core::System& system, AppletStorageChannel& chan
|
||||
} // namespace
|
||||
|
||||
AppletManager::AppletManager(Core::System& system) : m_system(system) {}
|
||||
AppletManager::~AppletManager() {
|
||||
this->Reset();
|
||||
}
|
||||
AppletManager::~AppletManager() = default;
|
||||
|
||||
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;
|
||||
void AppletManager::CreateAndInsertByFrontendAppletParameters(
|
||||
std::unique_ptr<Process> process, const FrontendAppletParameters& params) {
|
||||
{
|
||||
std::scoped_lock lk{m_lock};
|
||||
m_pending_process = std::move(process);
|
||||
m_pending_parameters = params;
|
||||
}
|
||||
m_cv.notify_all();
|
||||
}
|
||||
|
||||
const auto it = m_applets.find(aruid);
|
||||
if (it == m_applets.end()) {
|
||||
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;
|
||||
}
|
||||
|
||||
applet = it->second;
|
||||
m_applets.erase(it);
|
||||
m_cv.wait(lk, [&] { return m_pending_process != nullptr; });
|
||||
|
||||
should_stop = m_applets.empty();
|
||||
}
|
||||
const auto& params = m_pending_parameters;
|
||||
auto applet = std::make_shared<Applet>(m_system, std::move(m_pending_process),
|
||||
params.applet_id == AppletId::Application);
|
||||
|
||||
// Terminate process.
|
||||
applet->process->Terminate();
|
||||
|
||||
// If there were no applets left, stop emulation.
|
||||
if (should_stop) {
|
||||
m_system.Exit();
|
||||
}
|
||||
}
|
||||
|
||||
void AppletManager::CreateAndInsertByFrontendAppletParameters(
|
||||
AppletResourceUserId aruid, 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
|
||||
auto applet = std::make_shared<Applet>(m_system, std::make_unique<Process>(m_system));
|
||||
|
||||
applet->aruid = aruid;
|
||||
applet->program_id = params.program_id;
|
||||
applet->applet_id = params.applet_id;
|
||||
applet->type = params.applet_type;
|
||||
@ -322,59 +320,19 @@ void AppletManager::CreateAndInsertByFrontendAppletParameters(
|
||||
}
|
||||
|
||||
// Applet was started by frontend, so it is foreground.
|
||||
applet->message_queue.PushMessage(AppletMessage::ChangeIntoForeground);
|
||||
applet->message_queue.PushMessage(AppletMessage::FocusStateChanged);
|
||||
applet->focus_state = FocusState::InFocus;
|
||||
applet->lifecycle_manager.SetFocusState(FocusState::InFocus);
|
||||
|
||||
this->InsertApplet(std::move(applet));
|
||||
}
|
||||
|
||||
std::shared_ptr<Applet> AppletManager::GetByAppletResourceUserId(AppletResourceUserId aruid) const {
|
||||
std::scoped_lock lk{m_lock};
|
||||
|
||||
if (const auto it = m_applets.find(aruid); it != m_applets.end()) {
|
||||
return it->second;
|
||||
if (applet->applet_id == AppletId::QLaunch) {
|
||||
applet->lifecycle_manager.SetFocusHandlingMode(false);
|
||||
applet->lifecycle_manager.SetOutOfFocusSuspendingEnabled(false);
|
||||
m_window_system->TrackApplet(applet, false);
|
||||
m_window_system->RequestHomeMenuToGetForeground();
|
||||
} else {
|
||||
m_window_system->TrackApplet(applet, true);
|
||||
m_window_system->RequestApplicationToGetForeground();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
applet->process->Run();
|
||||
}
|
||||
|
||||
} // namespace Service::AM
|
||||
|
@ -3,17 +3,23 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
#include "core/hle/service/am/applet.h"
|
||||
#include "core/hle/service/am/am_types.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Service {
|
||||
class Process;
|
||||
}
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
class WindowSystem;
|
||||
|
||||
enum class LaunchType {
|
||||
FrontendInitiated,
|
||||
ApplicationInitiated,
|
||||
@ -33,27 +39,24 @@ public:
|
||||
explicit AppletManager(Core::System& system);
|
||||
~AppletManager();
|
||||
|
||||
void InsertApplet(std::shared_ptr<Applet> applet);
|
||||
void TerminateAndRemoveApplet(AppletResourceUserId aruid);
|
||||
|
||||
void CreateAndInsertByFrontendAppletParameters(AppletResourceUserId aruid,
|
||||
void CreateAndInsertByFrontendAppletParameters(std::unique_ptr<Process> process,
|
||||
const FrontendAppletParameters& params);
|
||||
std::shared_ptr<Applet> GetByAppletResourceUserId(AppletResourceUserId aruid) const;
|
||||
|
||||
void Reset();
|
||||
|
||||
void RequestExit();
|
||||
void RequestResume();
|
||||
void OperationModeChanged();
|
||||
void FocusStateChanged();
|
||||
|
||||
public:
|
||||
void SetWindowSystem(WindowSystem* window_system);
|
||||
|
||||
private:
|
||||
Core::System& m_system;
|
||||
|
||||
mutable std::mutex m_lock{};
|
||||
std::map<AppletResourceUserId, std::shared_ptr<Applet>> m_applets{};
|
||||
std::mutex m_lock;
|
||||
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
|
||||
|
@ -69,7 +69,11 @@ void FrontendApplet::PushInteractiveOutData(std::shared_ptr<IStorage> storage) {
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -3,24 +3,28 @@
|
||||
|
||||
#include "core/core.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/os/process.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
#include "hid_core/resource_manager.h"
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
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()) {
|
||||
m_hid_server->GetResourceManager()->RegisterAppletResourceUserId(m_process.GetProcessId(),
|
||||
true);
|
||||
m_hid_server->GetResourceManager()->SetAruidValidForVibration(m_process.GetProcessId(),
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
HidRegistration::~HidRegistration() {
|
||||
if (m_process.IsInitialized()) {
|
||||
m_hid_server->GetResourceManager()->SetAruidValidForVibration(m_process.GetProcessId(),
|
||||
false);
|
||||
m_hid_server->GetResourceManager()->UnregisterAppletResourceUserId(
|
||||
m_process.GetProcessId());
|
||||
}
|
||||
@ -28,6 +32,8 @@ HidRegistration::~HidRegistration() {
|
||||
|
||||
void HidRegistration::EnableAppletToGetInput(bool enable) {
|
||||
if (m_process.IsInitialized()) {
|
||||
m_hid_server->GetResourceManager()->SetAruidValidForVibration(m_process.GetProcessId(),
|
||||
enable);
|
||||
m_hid_server->GetResourceManager()->EnableInput(m_process.GetProcessId(), enable);
|
||||
}
|
||||
}
|
||||
|
@ -13,9 +13,11 @@ namespace Service::HID {
|
||||
class IHidServer;
|
||||
}
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
namespace Service {
|
||||
class Process;
|
||||
}
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
class HidRegistration {
|
||||
public:
|
||||
|
@ -6,12 +6,14 @@
|
||||
#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/system_applet_proxy.h"
|
||||
#include "core/hle/service/am/window_system.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_)
|
||||
: ServiceFramework{system_, "appletAE"} {
|
||||
IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_,
|
||||
WindowSystem& window_system)
|
||||
: ServiceFramework{system_, "appletAE"}, m_window_system{window_system} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"},
|
||||
@ -36,8 +38,8 @@ Result IAllSystemAppletProxiesService::OpenSystemAppletProxy(
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
|
||||
*out_system_applet_proxy =
|
||||
std::make_shared<ISystemAppletProxy>(system, applet, process_handle.Get());
|
||||
*out_system_applet_proxy = std::make_shared<ISystemAppletProxy>(
|
||||
system, applet, process_handle.Get(), m_window_system);
|
||||
R_SUCCEED();
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
@ -52,8 +54,8 @@ Result IAllSystemAppletProxiesService::OpenLibraryAppletProxy(
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
if (const auto applet = this->GetAppletFromProcessId(pid); applet) {
|
||||
*out_library_applet_proxy =
|
||||
std::make_shared<ILibraryAppletProxy>(system, applet, process_handle.Get());
|
||||
*out_library_applet_proxy = std::make_shared<ILibraryAppletProxy>(
|
||||
system, applet, process_handle.Get(), m_window_system);
|
||||
R_SUCCEED();
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
@ -73,7 +75,7 @@ Result IAllSystemAppletProxiesService::OpenLibraryAppletProxyOld(
|
||||
|
||||
std::shared_ptr<Applet> IAllSystemAppletProxiesService::GetAppletFromProcessId(
|
||||
ProcessId process_id) {
|
||||
return system.GetAppletManager().GetByAppletResourceUserId(process_id.pid);
|
||||
return m_window_system.GetByAppletResourceUserId(process_id.pid);
|
||||
}
|
||||
|
||||
} // namespace Service::AM
|
||||
|
@ -14,11 +14,12 @@ struct Applet;
|
||||
struct AppletAttribute;
|
||||
class ILibraryAppletProxy;
|
||||
class ISystemAppletProxy;
|
||||
class WindowSystem;
|
||||
|
||||
class IAllSystemAppletProxiesService final
|
||||
: public ServiceFramework<IAllSystemAppletProxiesService> {
|
||||
public:
|
||||
explicit IAllSystemAppletProxiesService(Core::System& system_);
|
||||
explicit IAllSystemAppletProxiesService(Core::System& system_, WindowSystem& window_system);
|
||||
~IAllSystemAppletProxiesService() override;
|
||||
|
||||
private:
|
||||
@ -35,6 +36,8 @@ private:
|
||||
|
||||
private:
|
||||
std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);
|
||||
|
||||
WindowSystem& m_window_system;
|
||||
};
|
||||
|
||||
} // namespace AM
|
||||
|
@ -19,7 +19,7 @@ IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_,
|
||||
{21, nullptr, "TryPopFromAppletBoundChannel"},
|
||||
{40, nullptr, "GetDisplayLogicalResolution"},
|
||||
{42, nullptr, "SetDisplayMagnification"},
|
||||
{50, nullptr, "SetHomeButtonDoubleClickEnabled"},
|
||||
{50, D<&IAppletCommonFunctions::SetHomeButtonDoubleClickEnabled>, "SetHomeButtonDoubleClickEnabled"},
|
||||
{51, D<&IAppletCommonFunctions::GetHomeButtonDoubleClickEnabled>, "GetHomeButtonDoubleClickEnabled"},
|
||||
{52, nullptr, "IsHomeButtonShortPressedBlocked"},
|
||||
{60, nullptr, "IsVrModeCurtainRequired"},
|
||||
@ -40,6 +40,13 @@ IAppletCommonFunctions::IAppletCommonFunctions(Core::System& system_,
|
||||
|
||||
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(
|
||||
Out<bool> out_home_button_double_click_enabled) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
|
@ -16,6 +16,7 @@ public:
|
||||
~IAppletCommonFunctions() override;
|
||||
|
||||
private:
|
||||
Result SetHomeButtonDoubleClickEnabled(bool home_button_double_click_enabled);
|
||||
Result GetHomeButtonDoubleClickEnabled(Out<bool> out_home_button_double_click_enabled);
|
||||
Result SetCpuBoostRequestPriority(s32 priority);
|
||||
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/library_applet_accessor.h"
|
||||
#include "core/hle/service/am/service/storage.h"
|
||||
#include "core/hle/service/am/window_system.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/glue/glue_manager.h"
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
IApplicationAccessor::IApplicationAccessor(Core::System& system_, std::shared_ptr<Applet> applet)
|
||||
: ServiceFramework{system_, "IApplicationAccessor"}, m_applet(std::move(applet)) {
|
||||
IApplicationAccessor::IApplicationAccessor(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||
WindowSystem& window_system)
|
||||
: ServiceFramework{system_, "IApplicationAccessor"}, m_window_system(window_system),
|
||||
m_applet(std::move(applet)) {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IApplicationAccessor::GetAppletStateChangedEvent>, "GetAppletStateChangedEvent"},
|
||||
@ -59,7 +63,15 @@ Result IApplicationAccessor::Start() {
|
||||
|
||||
Result IApplicationAccessor::RequestExit() {
|
||||
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();
|
||||
}
|
||||
|
||||
@ -71,13 +83,14 @@ Result IApplicationAccessor::Terminate() {
|
||||
|
||||
Result IApplicationAccessor::GetResult() {
|
||||
LOG_INFO(Service_AM, "called");
|
||||
R_SUCCEED();
|
||||
std::scoped_lock lk{m_applet->lock};
|
||||
R_RETURN(m_applet->terminate_result);
|
||||
}
|
||||
|
||||
Result IApplicationAccessor::GetAppletStateChangedEvent(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_INFO(Service_AM, "called");
|
||||
*out_event = m_applet->caller_applet_broker->GetStateChangedEvent().GetHandle();
|
||||
*out_event = m_applet->state_changed_event.GetHandle();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
@ -96,8 +109,15 @@ Result IApplicationAccessor::PushLaunchParameter(LaunchParameterKind kind,
|
||||
|
||||
Result IApplicationAccessor::GetApplicationControlProperty(
|
||||
OutBuffer<BufferAttr_HipcMapAlias> out_control_property) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
R_THROW(ResultUnknown);
|
||||
LOG_INFO(Service_AM, "called");
|
||||
|
||||
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,
|
||||
@ -114,8 +134,9 @@ Result IApplicationAccessor::GetCurrentLibraryApplet(
|
||||
}
|
||||
|
||||
Result IApplicationAccessor::RequestForApplicationToGetForeground() {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
R_THROW(ResultUnknown);
|
||||
LOG_INFO(Service_AM, "called");
|
||||
m_window_system.RequestApplicationToGetForeground();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationAccessor::CheckRightsEnvironmentAvailable(Out<bool> out_is_available) {
|
||||
|
@ -13,10 +13,12 @@ namespace Service::AM {
|
||||
struct Applet;
|
||||
class ILibraryAppletAccessor;
|
||||
class IStorage;
|
||||
class WindowSystem;
|
||||
|
||||
class IApplicationAccessor final : public ServiceFramework<IApplicationAccessor> {
|
||||
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;
|
||||
|
||||
private:
|
||||
@ -34,6 +36,7 @@ private:
|
||||
Result GetNsRightsEnvironmentHandle(Out<u64> out_handle);
|
||||
Result ReportApplicationExitTimeout();
|
||||
|
||||
WindowSystem& m_window_system;
|
||||
const std::shared_ptr<Applet> m_applet;
|
||||
};
|
||||
|
||||
|
@ -1,17 +1,57 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// 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/applet.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_creator.h"
|
||||
#include "core/hle/service/am/window_system.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
IApplicationCreator::IApplicationCreator(Core::System& system_)
|
||||
: ServiceFramework{system_, "IApplicationCreator"} {
|
||||
namespace {
|
||||
|
||||
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
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IApplicationCreator::CreateApplication>, "CreateApplication"},
|
||||
@ -28,8 +68,9 @@ IApplicationCreator::~IApplicationCreator() = default;
|
||||
|
||||
Result IApplicationCreator::CreateApplication(
|
||||
Out<SharedPointer<IApplicationAccessor>> out_application_accessor, u64 application_id) {
|
||||
LOG_ERROR(Service_NS, "called, application_id={:x}", application_id);
|
||||
R_THROW(ResultUnknown);
|
||||
LOG_INFO(Service_NS, "called, application_id={:016X}", application_id);
|
||||
R_RETURN(
|
||||
CreateGuestApplication(out_application_accessor, system, m_window_system, application_id));
|
||||
}
|
||||
|
||||
} // namespace Service::AM
|
||||
|
@ -10,14 +10,17 @@ namespace Service::AM {
|
||||
|
||||
class IApplicationAccessor;
|
||||
struct Applet;
|
||||
class WindowSystem;
|
||||
|
||||
class IApplicationCreator final : public ServiceFramework<IApplicationCreator> {
|
||||
public:
|
||||
explicit IApplicationCreator(Core::System& system_);
|
||||
explicit IApplicationCreator(Core::System& system_, WindowSystem& window_system);
|
||||
~IApplicationCreator() override;
|
||||
|
||||
private:
|
||||
Result CreateApplication(Out<SharedPointer<IApplicationAccessor>>, u64 application_id);
|
||||
|
||||
WindowSystem& m_window_system;
|
||||
};
|
||||
|
||||
} // namespace Service::AM
|
||||
|
@ -181,7 +181,8 @@ Result IApplicationFunctions::GetDesiredLanguage(Out<u64> out_language_code) {
|
||||
}
|
||||
|
||||
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,
|
||||
terminate_result.GetDescription());
|
||||
|
||||
|
@ -17,9 +17,9 @@
|
||||
namespace Service::AM {
|
||||
|
||||
IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||
Kernel::KProcess* process)
|
||||
: ServiceFramework{system_, "IApplicationProxy"}, m_process{process}, m_applet{
|
||||
std::move(applet)} {
|
||||
Kernel::KProcess* process, WindowSystem& window_system)
|
||||
: ServiceFramework{system_, "IApplicationProxy"},
|
||||
m_window_system{window_system}, m_process{process}, m_applet{std::move(applet)} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IApplicationProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
||||
@ -70,7 +70,7 @@ Result IApplicationProxy::GetDebugFunctions(
|
||||
Result IApplicationProxy::GetWindowController(
|
||||
Out<SharedPointer<IWindowController>> out_window_controller) {
|
||||
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();
|
||||
}
|
||||
|
||||
@ -91,7 +91,8 @@ Result IApplicationProxy::GetCommonStateGetter(
|
||||
Result IApplicationProxy::GetLibraryAppletCreator(
|
||||
Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -18,11 +18,12 @@ class ILibraryAppletCreator;
|
||||
class IProcessWindingController;
|
||||
class ISelfController;
|
||||
class IWindowController;
|
||||
class WindowSystem;
|
||||
|
||||
class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
|
||||
public:
|
||||
explicit IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||
Kernel::KProcess* process);
|
||||
Kernel::KProcess* process, WindowSystem& window_system);
|
||||
~IApplicationProxy();
|
||||
|
||||
private:
|
||||
@ -40,6 +41,7 @@ private:
|
||||
Out<SharedPointer<IApplicationFunctions>> out_application_functions);
|
||||
|
||||
private:
|
||||
WindowSystem& m_window_system;
|
||||
Kernel::KProcess* const m_process;
|
||||
const std::shared_ptr<Applet> m_applet;
|
||||
};
|
||||
|
@ -6,12 +6,14 @@
|
||||
#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_service.h"
|
||||
#include "core/hle/service/am/window_system.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
IApplicationProxyService::IApplicationProxyService(Core::System& system_)
|
||||
: ServiceFramework{system_, "appletOE"} {
|
||||
IApplicationProxyService::IApplicationProxyService(Core::System& system_,
|
||||
WindowSystem& window_system)
|
||||
: ServiceFramework{system_, "appletOE"}, m_window_system{window_system} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IApplicationProxyService::OpenApplicationProxy>, "OpenApplicationProxy"},
|
||||
};
|
||||
@ -26,8 +28,8 @@ Result IApplicationProxyService::OpenApplicationProxy(
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
if (const auto applet = this->GetAppletFromProcessId(pid)) {
|
||||
*out_application_proxy =
|
||||
std::make_shared<IApplicationProxy>(system, applet, process_handle.Get());
|
||||
*out_application_proxy = std::make_shared<IApplicationProxy>(
|
||||
system, applet, process_handle.Get(), m_window_system);
|
||||
R_SUCCEED();
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
@ -36,7 +38,7 @@ Result IApplicationProxyService::OpenApplicationProxy(
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -12,10 +12,11 @@ namespace AM {
|
||||
|
||||
struct Applet;
|
||||
class IApplicationProxy;
|
||||
class WindowSystem;
|
||||
|
||||
class IApplicationProxyService final : public ServiceFramework<IApplicationProxyService> {
|
||||
public:
|
||||
explicit IApplicationProxyService(Core::System& system_);
|
||||
explicit IApplicationProxyService(Core::System& system_, WindowSystem& window_system);
|
||||
~IApplicationProxyService() override;
|
||||
|
||||
private:
|
||||
@ -24,6 +25,8 @@ private:
|
||||
|
||||
private:
|
||||
std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);
|
||||
|
||||
WindowSystem& m_window_system;
|
||||
};
|
||||
|
||||
} // namespace AM
|
||||
|
@ -80,15 +80,14 @@ ICommonStateGetter::~ICommonStateGetter() = default;
|
||||
|
||||
Result ICommonStateGetter::GetEventHandle(OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
*out_event = &m_applet->message_queue.GetMessageReceiveEvent();
|
||||
*out_event = m_applet->lifecycle_manager.GetSystemEvent().GetHandle();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ICommonStateGetter::ReceiveMessage(Out<AppletMessage> out_applet_message) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
*out_applet_message = m_applet->message_queue.PopMessage();
|
||||
if (*out_applet_message == AppletMessage::None) {
|
||||
if (!m_applet->lifecycle_manager.PopMessage(out_applet_message)) {
|
||||
LOG_ERROR(Service_AM, "Tried to pop message but none was available!");
|
||||
R_THROW(AM::ResultNoMessages);
|
||||
}
|
||||
@ -100,7 +99,7 @@ Result ICommonStateGetter::GetCurrentFocusState(Out<FocusState> out_focus_state)
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
std::scoped_lock lk{m_applet->lock};
|
||||
*out_focus_state = m_applet->focus_state;
|
||||
*out_focus_state = m_applet->lifecycle_manager.GetAndClearFocusState();
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
@ -137,7 +136,7 @@ Result ICommonStateGetter::GetWriterLockAccessorEx(
|
||||
Result ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
*out_event = &m_applet->message_queue.GetOperationModeChangedEvent();
|
||||
*out_event = m_applet->lifecycle_manager.GetOperationModeChangedSystemEvent().GetHandle();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
@ -4,13 +4,16 @@
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/am/applet_manager.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"
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Applet> applet)
|
||||
: ServiceFramework{system_, "IHomeMenuFunctions"}, m_applet{std::move(applet)},
|
||||
m_context{system, "IHomeMenuFunctions"}, m_pop_from_general_channel_event{m_context} {
|
||||
IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||
WindowSystem& window_system)
|
||||
: 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
|
||||
static const FunctionInfo functions[] = {
|
||||
{10, D<&IHomeMenuFunctions::RequestToGetForeground>, "RequestToGetForeground"},
|
||||
@ -37,17 +40,20 @@ IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_, std::shared_ptr<Ap
|
||||
IHomeMenuFunctions::~IHomeMenuFunctions() = default;
|
||||
|
||||
Result IHomeMenuFunctions::RequestToGetForeground() {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
LOG_INFO(Service_AM, "called");
|
||||
m_window_system.RequestHomeMenuToGetForeground();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHomeMenuFunctions::LockForeground() {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
LOG_INFO(Service_AM, "called");
|
||||
m_window_system.RequestLockHomeMenuIntoForeground();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHomeMenuFunctions::UnlockForeground() {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
LOG_INFO(Service_AM, "called");
|
||||
m_window_system.RequestUnlockHomeMenuIntoForeground();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
@ -11,10 +11,12 @@
|
||||
namespace Service::AM {
|
||||
|
||||
struct Applet;
|
||||
class WindowSystem;
|
||||
|
||||
class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> {
|
||||
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;
|
||||
|
||||
private:
|
||||
@ -26,6 +28,7 @@ private:
|
||||
Result IsForceTerminateApplicationDisabledForDebug(
|
||||
Out<bool> out_is_force_terminate_application_disabled_for_debug);
|
||||
|
||||
WindowSystem& m_window_system;
|
||||
const std::shared_ptr<Applet> m_applet;
|
||||
KernelHelpers::ServiceContext m_context;
|
||||
Event m_pop_from_general_channel_event;
|
||||
|
@ -47,20 +47,21 @@ ILibraryAppletAccessor::~ILibraryAppletAccessor() = default;
|
||||
Result ILibraryAppletAccessor::GetAppletStateChangedEvent(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
*out_event = m_broker->GetStateChangedEvent().GetHandle();
|
||||
*out_event = m_applet->state_changed_event.GetHandle();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ILibraryAppletAccessor::IsCompleted(Out<bool> out_is_completed) {
|
||||
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();
|
||||
}
|
||||
|
||||
Result ILibraryAppletAccessor::GetResult(Out<Result> out_result) {
|
||||
Result ILibraryAppletAccessor::GetResult() {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
*out_result = m_applet->terminate_result;
|
||||
R_SUCCEED();
|
||||
std::scoped_lock lk{m_applet->lock};
|
||||
R_RETURN(m_applet->terminate_result);
|
||||
}
|
||||
|
||||
Result ILibraryAppletAccessor::PresetLibraryAppletGpuTimeSliceZero() {
|
||||
@ -77,7 +78,10 @@ Result ILibraryAppletAccessor::Start() {
|
||||
|
||||
Result ILibraryAppletAccessor::RequestExit() {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
m_applet->message_queue.RequestExit();
|
||||
{
|
||||
std::scoped_lock lk{m_applet->lock};
|
||||
m_applet->lifecycle_manager.RequestExit();
|
||||
}
|
||||
FrontendRequestExit();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ public:
|
||||
private:
|
||||
Result GetAppletStateChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result IsCompleted(Out<bool> out_is_completed);
|
||||
Result GetResult(Out<Result> out_result);
|
||||
Result GetResult();
|
||||
Result PresetLibraryAppletGpuTimeSliceZero();
|
||||
Result Start();
|
||||
Result RequestExit();
|
||||
|
@ -7,9 +7,11 @@
|
||||
#include "core/hle/service/am/applet_manager.h"
|
||||
#include "core/hle/service/am/frontend/applets.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_creator.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/sm/sm.h"
|
||||
|
||||
@ -93,6 +95,7 @@ AppletProgramId AppletIdToProgramId(AppletId applet_id) {
|
||||
}
|
||||
|
||||
std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
|
||||
WindowSystem& window_system,
|
||||
std::shared_ptr<Applet> caller_applet,
|
||||
AppletId applet_id,
|
||||
LibraryAppletMode mode) {
|
||||
@ -110,53 +113,38 @@ std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
|
||||
Firmware1700 = 17,
|
||||
};
|
||||
|
||||
auto process = std::make_unique<Process>(system);
|
||||
if (!process->Initialize(program_id, Firmware1400, Firmware1700)) {
|
||||
auto process = CreateProcess(system, program_id, Firmware1400, Firmware1700);
|
||||
if (!process) {
|
||||
// Couldn't initialize the guest process
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto applet = std::make_shared<Applet>(system, std::move(process));
|
||||
const auto applet = std::make_shared<Applet>(system, std::move(process), false);
|
||||
applet->program_id = program_id;
|
||||
applet->applet_id = applet_id;
|
||||
applet->type = AppletType::LibraryApplet;
|
||||
applet->library_applet_mode = mode;
|
||||
|
||||
// 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;
|
||||
}
|
||||
applet->window_visible = mode != LibraryAppletMode::AllForegroundInitiallyHidden;
|
||||
|
||||
auto broker = std::make_shared<AppletDataBroker>(system);
|
||||
applet->caller_applet = caller_applet;
|
||||
applet->caller_applet_broker = broker;
|
||||
caller_applet->child_applets.push_back(applet);
|
||||
|
||||
system.GetAppletManager().InsertApplet(applet);
|
||||
window_system.TrackApplet(applet, false);
|
||||
|
||||
return std::make_shared<ILibraryAppletAccessor>(system, broker, applet);
|
||||
}
|
||||
|
||||
std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& system,
|
||||
WindowSystem& window_system,
|
||||
std::shared_ptr<Applet> caller_applet,
|
||||
AppletId applet_id,
|
||||
LibraryAppletMode mode) {
|
||||
const auto program_id = static_cast<u64>(AppletIdToProgramId(applet_id));
|
||||
|
||||
auto process = std::make_unique<Process>(system);
|
||||
auto applet = std::make_shared<Applet>(system, std::move(process));
|
||||
auto applet = std::make_shared<Applet>(system, std::move(process), false);
|
||||
applet->program_id = program_id;
|
||||
applet->applet_id = applet_id;
|
||||
applet->type = AppletType::LibraryApplet;
|
||||
@ -166,14 +154,19 @@ std::shared_ptr<ILibraryAppletAccessor> CreateFrontendApplet(Core::System& syste
|
||||
applet->caller_applet = caller_applet;
|
||||
applet->caller_applet_broker = storage;
|
||||
applet->frontend = system.GetFrontendAppletHolder().GetApplet(applet, applet_id, mode);
|
||||
caller_applet->child_applets.push_back(applet);
|
||||
|
||||
window_system.TrackApplet(applet, false);
|
||||
|
||||
return std::make_shared<ILibraryAppletAccessor>(system, storage, applet);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet)
|
||||
: ServiceFramework{system_, "ILibraryAppletCreator"}, m_applet{std::move(applet)} {
|
||||
ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||
WindowSystem& window_system)
|
||||
: ServiceFramework{system_, "ILibraryAppletCreator"},
|
||||
m_window_system{window_system}, m_applet{std::move(applet)} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&ILibraryAppletCreator::CreateLibraryApplet>, "CreateLibraryApplet"},
|
||||
{1, nullptr, "TerminateAllLibraryApplets"},
|
||||
@ -195,10 +188,12 @@ Result ILibraryAppletCreator::CreateLibraryApplet(
|
||||
|
||||
std::shared_ptr<ILibraryAppletAccessor> library_applet;
|
||||
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) {
|
||||
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) {
|
||||
LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
|
||||
|
@ -12,10 +12,12 @@ namespace Service::AM {
|
||||
struct Applet;
|
||||
class ILibraryAppletAccessor;
|
||||
class IStorage;
|
||||
class WindowSystem;
|
||||
|
||||
class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
|
||||
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;
|
||||
|
||||
private:
|
||||
@ -29,6 +31,7 @@ private:
|
||||
Result CreateHandleStorage(Out<SharedPointer<IStorage>> out_storage, s64 size,
|
||||
InCopyHandle<Kernel::KTransferMemory> transfer_memory_handle);
|
||||
|
||||
WindowSystem& m_window_system;
|
||||
const std::shared_ptr<Applet> m_applet;
|
||||
};
|
||||
|
||||
|
@ -19,9 +19,9 @@
|
||||
namespace Service::AM {
|
||||
|
||||
ILibraryAppletProxy::ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||
Kernel::KProcess* process)
|
||||
: ServiceFramework{system_, "ILibraryAppletProxy"}, m_process{process}, m_applet{
|
||||
std::move(applet)} {
|
||||
Kernel::KProcess* process, WindowSystem& window_system)
|
||||
: ServiceFramework{system_, "ILibraryAppletProxy"},
|
||||
m_window_system{window_system}, m_process{process}, m_applet{std::move(applet)} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&ILibraryAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
||||
@ -75,7 +75,7 @@ Result ILibraryAppletProxy::GetDebugFunctions(
|
||||
Result ILibraryAppletProxy::GetWindowController(
|
||||
Out<SharedPointer<IWindowController>> out_window_controller) {
|
||||
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();
|
||||
}
|
||||
|
||||
@ -96,7 +96,8 @@ Result ILibraryAppletProxy::GetCommonStateGetter(
|
||||
Result ILibraryAppletProxy::GetLibraryAppletCreator(
|
||||
Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
|
||||
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();
|
||||
}
|
||||
|
||||
@ -118,7 +119,8 @@ Result ILibraryAppletProxy::GetAppletCommonFunctions(
|
||||
Result ILibraryAppletProxy::GetHomeMenuFunctions(
|
||||
Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions) {
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -21,11 +21,12 @@ class ILibraryAppletSelfAccessor;
|
||||
class IProcessWindingController;
|
||||
class ISelfController;
|
||||
class IWindowController;
|
||||
class WindowSystem;
|
||||
|
||||
class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
|
||||
public:
|
||||
explicit ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||
Kernel::KProcess* process);
|
||||
Kernel::KProcess* process, WindowSystem& window_system);
|
||||
~ILibraryAppletProxy();
|
||||
|
||||
private:
|
||||
@ -47,6 +48,7 @@ private:
|
||||
Result GetGlobalStateController(
|
||||
Out<SharedPointer<IGlobalStateController>> out_global_state_controller);
|
||||
|
||||
WindowSystem& m_window_system;
|
||||
Kernel::KProcess* const m_process;
|
||||
const std::shared_ptr<Applet> m_applet;
|
||||
};
|
||||
|
@ -176,8 +176,7 @@ Result ILibraryAppletSelfAccessor::GetMainAppletStorageId(Out<FileSys::StorageId
|
||||
|
||||
Result ILibraryAppletSelfAccessor::ExitProcessAndReturn() {
|
||||
LOG_INFO(Service_AM, "called");
|
||||
system.GetAppletManager().TerminateAndRemoveApplet(m_applet->aruid);
|
||||
m_broker->SignalCompletion();
|
||||
m_applet->process->Terminate();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
@ -86,8 +86,7 @@ ISelfController::~ISelfController() {
|
||||
Result ISelfController::Exit() {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
// TODO
|
||||
system.Exit();
|
||||
m_applet->process->Terminate();
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
@ -95,7 +94,16 @@ Result ISelfController::Exit() {
|
||||
Result ISelfController::LockExit() {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
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();
|
||||
}
|
||||
@ -103,10 +111,13 @@ Result ISelfController::LockExit() {
|
||||
Result ISelfController::UnlockExit() {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
|
||||
std::scoped_lock lk{m_applet->lock};
|
||||
|
||||
m_applet->exit_locked = false;
|
||||
system.SetExitLocked(false);
|
||||
|
||||
if (system.GetExitRequested()) {
|
||||
system.Exit();
|
||||
if (m_applet->lifecycle_manager.GetExitRequested()) {
|
||||
m_applet->process->Terminate();
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
@ -155,7 +166,7 @@ Result ISelfController::SetOperationModeChangedNotification(bool enabled) {
|
||||
LOG_INFO(Service_AM, "called, enabled={}", enabled);
|
||||
|
||||
std::scoped_lock lk{m_applet->lock};
|
||||
m_applet->operation_mode_changed_notification_enabled = enabled;
|
||||
m_applet->lifecycle_manager.SetOperationModeChangedNotificationEnabled(enabled);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
@ -164,17 +175,18 @@ Result ISelfController::SetPerformanceModeChangedNotification(bool enabled) {
|
||||
LOG_INFO(Service_AM, "called, enabled={}", enabled);
|
||||
|
||||
std::scoped_lock lk{m_applet->lock};
|
||||
m_applet->performance_mode_changed_notification_enabled = enabled;
|
||||
m_applet->lifecycle_manager.SetPerformanceModeChangedNotificationEnabled(enabled);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISelfController::SetFocusHandlingMode(bool notify, bool background, bool suspend) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called, notify={} background={} suspend={}", notify,
|
||||
background, suspend);
|
||||
LOG_INFO(Service_AM, "called, notify={} background={} suspend={}", notify, background, suspend);
|
||||
|
||||
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();
|
||||
}
|
||||
@ -183,7 +195,7 @@ Result ISelfController::SetRestartMessageEnabled(bool enabled) {
|
||||
LOG_INFO(Service_AM, "called, enabled={}", enabled);
|
||||
|
||||
std::scoped_lock lk{m_applet->lock};
|
||||
m_applet->restart_message_enabled = enabled;
|
||||
m_applet->lifecycle_manager.SetResumeNotificationEnabled(enabled);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
@ -202,7 +214,8 @@ Result ISelfController::SetOutOfFocusSuspendingEnabled(bool enabled) {
|
||||
LOG_INFO(Service_AM, "called, enabled={}", enabled);
|
||||
|
||||
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();
|
||||
}
|
||||
|
@ -19,9 +19,9 @@
|
||||
namespace Service::AM {
|
||||
|
||||
ISystemAppletProxy::ISystemAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||
Kernel::KProcess* process)
|
||||
: ServiceFramework{system_, "ISystemAppletProxy"}, m_process{process}, m_applet{
|
||||
std::move(applet)} {
|
||||
Kernel::KProcess* process, WindowSystem& window_system)
|
||||
: ServiceFramework{system_, "ISystemAppletProxy"},
|
||||
m_window_system{window_system}, m_process{process}, m_applet{std::move(applet)} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&ISystemAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
||||
@ -75,7 +75,7 @@ Result ISystemAppletProxy::GetDebugFunctions(
|
||||
Result ISystemAppletProxy::GetWindowController(
|
||||
Out<SharedPointer<IWindowController>> out_window_controller) {
|
||||
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();
|
||||
}
|
||||
|
||||
@ -96,14 +96,15 @@ Result ISystemAppletProxy::GetCommonStateGetter(
|
||||
Result ISystemAppletProxy::GetLibraryAppletCreator(
|
||||
Out<SharedPointer<ILibraryAppletCreator>> out_library_applet_creator) {
|
||||
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();
|
||||
}
|
||||
|
||||
Result ISystemAppletProxy::GetApplicationCreator(
|
||||
Out<SharedPointer<IApplicationCreator>> out_application_creator) {
|
||||
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();
|
||||
}
|
||||
|
||||
@ -117,7 +118,8 @@ Result ISystemAppletProxy::GetAppletCommonFunctions(
|
||||
Result ISystemAppletProxy::GetHomeMenuFunctions(
|
||||
Out<SharedPointer<IHomeMenuFunctions>> out_home_menu_functions) {
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -21,11 +21,12 @@ class ILibraryAppletCreator;
|
||||
class IProcessWindingController;
|
||||
class ISelfController;
|
||||
class IWindowController;
|
||||
class WindowSystem;
|
||||
|
||||
class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
|
||||
public:
|
||||
explicit ISystemAppletProxy(Core::System& system, std::shared_ptr<Applet> applet,
|
||||
Kernel::KProcess* process);
|
||||
Kernel::KProcess* process, WindowSystem& window_system);
|
||||
~ISystemAppletProxy();
|
||||
|
||||
private:
|
||||
@ -46,6 +47,7 @@ private:
|
||||
Result GetGlobalStateController(
|
||||
Out<SharedPointer<IGlobalStateController>> out_global_state_controller);
|
||||
|
||||
WindowSystem& m_window_system;
|
||||
Kernel::KProcess* const m_process;
|
||||
const std::shared_ptr<Applet> m_applet;
|
||||
};
|
||||
|
@ -4,12 +4,15 @@
|
||||
#include "core/hle/service/am/applet.h"
|
||||
#include "core/hle/service/am/applet_manager.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"
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
IWindowController::IWindowController(Core::System& system_, std::shared_ptr<Applet> applet)
|
||||
: ServiceFramework{system_, "IWindowController"}, m_applet{std::move(applet)} {
|
||||
IWindowController::IWindowController(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||
WindowSystem& window_system)
|
||||
: ServiceFramework{system_, "IWindowController"},
|
||||
m_window_system{window_system}, m_applet{std::move(applet)} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "CreateWindow"},
|
||||
@ -63,17 +66,9 @@ Result IWindowController::RejectToChangeIntoBackground() {
|
||||
}
|
||||
|
||||
Result IWindowController::SetAppletWindowVisibility(bool visible) {
|
||||
m_applet->display_layer_manager.SetWindowVisibility(visible);
|
||||
m_applet->hid_registration.EnableAppletToGetInput(visible);
|
||||
LOG_INFO(Service_AM, "called");
|
||||
|
||||
if (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);
|
||||
m_window_system.RequestAppletVisibilityState(*m_applet, visible);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
@ -9,10 +9,12 @@
|
||||
namespace Service::AM {
|
||||
|
||||
struct Applet;
|
||||
class WindowSystem;
|
||||
|
||||
class IWindowController final : public ServiceFramework<IWindowController> {
|
||||
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;
|
||||
|
||||
private:
|
||||
@ -24,6 +26,7 @@ private:
|
||||
Result SetAppletWindowVisibility(bool visible);
|
||||
Result SetAppletGpuTimeSlice(s64 time_slice);
|
||||
|
||||
WindowSystem& m_window_system;
|
||||
const std::shared_ptr<Applet> m_applet;
|
||||
};
|
||||
|
||||
|
@ -23,11 +23,7 @@ void LoopProcess(Core::System& system) {
|
||||
std::shared_ptr<ResourceManager> resource_manager =
|
||||
std::make_shared<ResourceManager>(system, firmware_settings);
|
||||
|
||||
// TODO: Remove this hack when am is emulated properly.
|
||||
resource_manager->Initialize();
|
||||
resource_manager->RegisterAppletResourceUserId(system.ApplicationProcess()->GetProcessId(),
|
||||
true);
|
||||
resource_manager->SetAruidValidForVibration(system.ApplicationProcess()->GetProcessId(), true);
|
||||
|
||||
server_manager->RegisterNamedService(
|
||||
"hid", std::make_shared<IHidServer>(system, resource_manager, firmware_settings));
|
||||
|
@ -49,8 +49,7 @@ struct Memory::Impl {
|
||||
void SetCurrentPageTable(Kernel::KProcess& process) {
|
||||
current_page_table = &process.GetPageTable().GetImpl();
|
||||
|
||||
if (std::addressof(process) == system.ApplicationProcess() &&
|
||||
Settings::IsFastmemEnabled()) {
|
||||
if (process.IsApplication() && Settings::IsFastmemEnabled()) {
|
||||
current_page_table->fastmem_arena = system.DeviceMemory().buffer.VirtualBasePointer();
|
||||
} else {
|
||||
current_page_table->fastmem_arena = nullptr;
|
||||
|
@ -248,16 +248,19 @@ void Vic::ReadProgressiveY8__V8U8_N420(const SlotStruct& slot,
|
||||
#endif
|
||||
|
||||
#if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64)
|
||||
const auto alpha_linear{static_cast<u16>(slot.config.planar_alpha.Value())};
|
||||
const auto alpha =
|
||||
_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 sse_aligned_width = Common::AlignDown(in_luma_width, 16);
|
||||
|
||||
for (s32 y = 0; y < in_luma_height; y++) {
|
||||
const auto src_luma{y * in_luma_stride};
|
||||
const auto src_chroma{(y / 2) * in_chroma_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
|
||||
// Prefetch next iteration's memory
|
||||
_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
|
||||
}
|
||||
|
||||
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
|
||||
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]
|
||||
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) {
|
||||
const auto src = y * surface_stride;
|
||||
const auto dst_luma = y * out_luma_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
|
||||
// Prefetch the next cache lines, 2 per iteration
|
||||
_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
|
||||
}
|
||||
|
||||
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
|
||||
DecodeLinear(out_luma, out_chroma);
|
||||
@ -1083,10 +1116,14 @@ void Vic::WriteABGR(const OutputSurfaceConfig& output_surface_config) {
|
||||
#endif
|
||||
|
||||
#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++) {
|
||||
const auto src = y * surface_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
|
||||
// Prefetch the next 2 cache lines
|
||||
_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
|
||||
}
|
||||
|
||||
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
|
||||
DecodeLinear(out_buffer);
|
||||
|
@ -2114,7 +2114,9 @@ void TextureCache<P>::TrackImage(ImageBase& image, ImageId image_id) {
|
||||
ASSERT(False(image.flags & ImageFlagBits::Tracked));
|
||||
image.flags |= ImageFlagBits::Tracked;
|
||||
if (False(image.flags & ImageFlagBits::Sparse)) {
|
||||
if (image.cpu_addr < ~(1ULL << 40)) {
|
||||
device_memory.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
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));
|
||||
image.flags &= ~ImageFlagBits::Tracked;
|
||||
if (False(image.flags & ImageFlagBits::Sparse)) {
|
||||
if (image.cpu_addr < ~(1ULL << 40)) {
|
||||
device_memory.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, -1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
ASSERT(True(image.flags & ImageFlagBits::Registered));
|
||||
|
@ -1461,7 +1461,6 @@ void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) {
|
||||
OnPauseGame();
|
||||
} else if (!emu_thread->IsRunning() && auto_paused && state == Qt::ApplicationActive) {
|
||||
auto_paused = false;
|
||||
RequestGameResume();
|
||||
OnStartGame();
|
||||
}
|
||||
}
|
||||
@ -1702,7 +1701,6 @@ void GMainWindow::OnPrepareForSleep(bool prepare_sleep) {
|
||||
} else {
|
||||
if (!emu_thread->IsRunning() && auto_paused) {
|
||||
auto_paused = false;
|
||||
RequestGameResume();
|
||||
OnStartGame();
|
||||
}
|
||||
}
|
||||
@ -3457,7 +3455,6 @@ void GMainWindow::OnPauseContinueGame() {
|
||||
if (emu_thread->IsRunning()) {
|
||||
OnPauseGame();
|
||||
} else {
|
||||
RequestGameResume();
|
||||
OnStartGame();
|
||||
}
|
||||
}
|
||||
@ -5013,10 +5010,6 @@ void GMainWindow::RequestGameExit() {
|
||||
system->GetAppletManager().RequestExit();
|
||||
}
|
||||
|
||||
void GMainWindow::RequestGameResume() {
|
||||
system->GetAppletManager().RequestResume();
|
||||
}
|
||||
|
||||
void GMainWindow::filterBarSetChecked(bool state) {
|
||||
ui->action_Show_Filter_Bar->setChecked(state);
|
||||
emit(OnToggleFilterBar());
|
||||
|
@ -310,7 +310,6 @@ private:
|
||||
bool ConfirmChangeGame();
|
||||
bool ConfirmForceLockedExit();
|
||||
void RequestGameExit();
|
||||
void RequestGameResume();
|
||||
void changeEvent(QEvent* event) override;
|
||||
void closeEvent(QCloseEvent* event) override;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user