early-access version 4145
This commit is contained in:
parent
e2005d9149
commit
ebd0305be1
@ -1,7 +1,7 @@
|
||||
yuzu emulator early access
|
||||
=============
|
||||
|
||||
This is the source code for early-access 4144.
|
||||
This is the source code for early-access 4145.
|
||||
|
||||
## Legal Notice
|
||||
|
||||
|
@ -423,12 +423,12 @@ add_library(core STATIC
|
||||
hle/service/am/applet_manager.h
|
||||
hle/service/am/applet_message_queue.cpp
|
||||
hle/service/am/applet_message_queue.h
|
||||
hle/service/am/display_layer_manager.cpp
|
||||
hle/service/am/display_layer_manager.h
|
||||
hle/service/am/hid_registration.cpp
|
||||
hle/service/am/hid_registration.h
|
||||
hle/service/am/library_applet_storage.cpp
|
||||
hle/service/am/library_applet_storage.h
|
||||
hle/service/am/managed_layer_holder.cpp
|
||||
hle/service/am/managed_layer_holder.h
|
||||
hle/service/am/process.cpp
|
||||
hle/service/am/process.h
|
||||
hle/service/am/service/all_system_applet_proxies_service.cpp
|
||||
@ -481,8 +481,6 @@ 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/system_buffer_manager.cpp
|
||||
hle/service/am/system_buffer_manager.h
|
||||
hle/service/aoc/aoc_u.cpp
|
||||
hle/service/aoc/aoc_u.h
|
||||
hle/service/apm/apm.cpp
|
||||
@ -491,12 +489,12 @@ add_library(core STATIC
|
||||
hle/service/apm/apm_controller.h
|
||||
hle/service/apm/apm_interface.cpp
|
||||
hle/service/apm/apm_interface.h
|
||||
hle/service/audio/audctl.cpp
|
||||
hle/service/audio/audctl.h
|
||||
hle/service/audio/audin_u.cpp
|
||||
hle/service/audio/audin_u.h
|
||||
hle/service/audio/audio.cpp
|
||||
hle/service/audio/audio.h
|
||||
hle/service/audio/audio_controller.cpp
|
||||
hle/service/audio/audio_controller.h
|
||||
hle/service/audio/audout_u.cpp
|
||||
hle/service/audio/audout_u.h
|
||||
hle/service/audio/audrec_a.cpp
|
||||
@ -739,15 +737,48 @@ add_library(core STATIC
|
||||
hle/service/nim/nim.h
|
||||
hle/service/npns/npns.cpp
|
||||
hle/service/npns/npns.h
|
||||
hle/service/ns/errors.h
|
||||
hle/service/ns/iplatform_service_manager.cpp
|
||||
hle/service/ns/iplatform_service_manager.h
|
||||
hle/service/ns/account_proxy_interface.cpp
|
||||
hle/service/ns/account_proxy_interface.h
|
||||
hle/service/ns/application_manager_interface.cpp
|
||||
hle/service/ns/application_manager_interface.h
|
||||
hle/service/ns/application_version_interface.cpp
|
||||
hle/service/ns/application_version_interface.h
|
||||
hle/service/ns/content_management_interface.cpp
|
||||
hle/service/ns/content_management_interface.h
|
||||
hle/service/ns/develop_interface.cpp
|
||||
hle/service/ns/develop_interface.h
|
||||
hle/service/ns/document_interface.cpp
|
||||
hle/service/ns/document_interface.h
|
||||
hle/service/ns/download_task_interface.cpp
|
||||
hle/service/ns/download_task_interface.h
|
||||
hle/service/ns/dynamic_rights_interface.cpp
|
||||
hle/service/ns/dynamic_rights_interface.h
|
||||
hle/service/ns/ecommerce_interface.cpp
|
||||
hle/service/ns/ecommerce_interface.h
|
||||
hle/service/ns/factory_reset_interface.cpp
|
||||
hle/service/ns/factory_reset_interface.h
|
||||
hle/service/ns/language.cpp
|
||||
hle/service/ns/language.h
|
||||
hle/service/ns/ns_results.h
|
||||
hle/service/ns/ns_types.h
|
||||
hle/service/ns/ns.cpp
|
||||
hle/service/ns/ns.h
|
||||
hle/service/ns/pdm_qry.cpp
|
||||
hle/service/ns/pdm_qry.h
|
||||
hle/service/ns/platform_service_manager.cpp
|
||||
hle/service/ns/platform_service_manager.h
|
||||
hle/service/ns/query_service.cpp
|
||||
hle/service/ns/query_service.h
|
||||
hle/service/ns/read_only_application_control_data_interface.cpp
|
||||
hle/service/ns/read_only_application_control_data_interface.h
|
||||
hle/service/ns/read_only_application_record_interface.cpp
|
||||
hle/service/ns/read_only_application_record_interface.h
|
||||
hle/service/ns/service_getter_interface.cpp
|
||||
hle/service/ns/service_getter_interface.h
|
||||
hle/service/ns/system_update_control.cpp
|
||||
hle/service/ns/system_update_control.h
|
||||
hle/service/ns/system_update_interface.cpp
|
||||
hle/service/ns/system_update_interface.h
|
||||
hle/service/ns/vulnerability_manager_interface.cpp
|
||||
hle/service/ns/vulnerability_manager_interface.h
|
||||
hle/service/nvdrv/core/container.cpp
|
||||
hle/service/nvdrv/core/container.h
|
||||
hle/service/nvdrv/core/heap_mapper.cpp
|
||||
@ -800,12 +831,12 @@ add_library(core STATIC
|
||||
hle/service/nvnflinger/consumer_base.cpp
|
||||
hle/service/nvnflinger/consumer_base.h
|
||||
hle/service/nvnflinger/consumer_listener.h
|
||||
hle/service/nvnflinger/fb_share_buffer_manager.cpp
|
||||
hle/service/nvnflinger/fb_share_buffer_manager.h
|
||||
hle/service/nvnflinger/graphic_buffer_producer.cpp
|
||||
hle/service/nvnflinger/graphic_buffer_producer.h
|
||||
hle/service/nvnflinger/hos_binder_driver_server.cpp
|
||||
hle/service/nvnflinger/hos_binder_driver_server.h
|
||||
hle/service/nvnflinger/hos_binder_driver.cpp
|
||||
hle/service/nvnflinger/hos_binder_driver.h
|
||||
hle/service/nvnflinger/hardware_composer.cpp
|
||||
hle/service/nvnflinger/hardware_composer.h
|
||||
hle/service/nvnflinger/hwc_layer.h
|
||||
@ -815,6 +846,8 @@ add_library(core STATIC
|
||||
hle/service/nvnflinger/pixel_format.h
|
||||
hle/service/nvnflinger/producer_listener.h
|
||||
hle/service/nvnflinger/status.h
|
||||
hle/service/nvnflinger/surface_flinger.cpp
|
||||
hle/service/nvnflinger/surface_flinger.h
|
||||
hle/service/nvnflinger/ui/fence.h
|
||||
hle/service/nvnflinger/ui/graphic_buffer.cpp
|
||||
hle/service/nvnflinger/ui/graphic_buffer.h
|
||||
@ -908,6 +941,8 @@ add_library(core STATIC
|
||||
hle/service/server_manager.h
|
||||
hle/service/service.cpp
|
||||
hle/service/service.h
|
||||
hle/service/services.cpp
|
||||
hle/service/services.h
|
||||
hle/service/set/setting_formats/appln_settings.cpp
|
||||
hle/service/set/setting_formats/appln_settings.h
|
||||
hle/service/set/setting_formats/device_settings.cpp
|
||||
@ -955,22 +990,26 @@ add_library(core STATIC
|
||||
hle/service/ssl/ssl_backend.h
|
||||
hle/service/usb/usb.cpp
|
||||
hle/service/usb/usb.h
|
||||
hle/service/vi/display/vi_display.cpp
|
||||
hle/service/vi/display/vi_display.h
|
||||
hle/service/vi/layer/vi_layer.cpp
|
||||
hle/service/vi/layer/vi_layer.h
|
||||
hle/service/vi/application_display_service.cpp
|
||||
hle/service/vi/application_display_service.h
|
||||
hle/service/vi/application_root_service.cpp
|
||||
hle/service/vi/application_root_service.h
|
||||
hle/service/vi/hos_binder_driver.cpp
|
||||
hle/service/vi/hos_binder_driver.h
|
||||
hle/service/vi/conductor.cpp
|
||||
hle/service/vi/conductor.h
|
||||
hle/service/vi/container.cpp
|
||||
hle/service/vi/container.h
|
||||
hle/service/vi/display_list.h
|
||||
hle/service/vi/display.h
|
||||
hle/service/vi/layer_list.h
|
||||
hle/service/vi/layer.h
|
||||
hle/service/vi/manager_display_service.cpp
|
||||
hle/service/vi/manager_display_service.h
|
||||
hle/service/vi/manager_root_service.cpp
|
||||
hle/service/vi/manager_root_service.h
|
||||
hle/service/vi/service_creator.cpp
|
||||
hle/service/vi/service_creator.h
|
||||
hle/service/vi/shared_buffer_manager.cpp
|
||||
hle/service/vi/shared_buffer_manager.h
|
||||
hle/service/vi/system_display_service.cpp
|
||||
hle/service/vi/system_display_service.h
|
||||
hle/service/vi/system_root_service.cpp
|
||||
@ -979,6 +1018,8 @@ add_library(core STATIC
|
||||
hle/service/vi/vi_types.h
|
||||
hle/service/vi/vi.cpp
|
||||
hle/service/vi/vi.h
|
||||
hle/service/vi/vsync_manager.cpp
|
||||
hle/service/vi/vsync_manager.h
|
||||
internal_network/network.cpp
|
||||
internal_network/network.h
|
||||
internal_network/network_interface.cpp
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "core/hle/service/psc/time/system_clock.h"
|
||||
#include "core/hle/service/psc/time/time_zone_service.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/services.h"
|
||||
#include "core/hle/service/set/system_settings_server.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
#include "core/internal_network/network.h"
|
||||
@ -310,7 +311,8 @@ struct System::Impl {
|
||||
audio_core = std::make_unique<AudioCore::AudioCore>(system);
|
||||
|
||||
service_manager = std::make_shared<Service::SM::ServiceManager>(kernel);
|
||||
services = std::make_unique<Service::Services>(service_manager, system);
|
||||
services =
|
||||
std::make_unique<Service::Services>(service_manager, system, stop_event.get_token());
|
||||
|
||||
is_powered_on = true;
|
||||
exit_locked = false;
|
||||
@ -458,11 +460,10 @@ struct System::Impl {
|
||||
gpu_core->NotifyShutdown();
|
||||
}
|
||||
|
||||
stop_event.request_stop();
|
||||
core_timing.SyncPause(false);
|
||||
Network::CancelPendingSocketOperations();
|
||||
kernel.SuspendEmulation(true);
|
||||
if (services) {
|
||||
services->KillNVNFlinger();
|
||||
}
|
||||
kernel.CloseServices();
|
||||
kernel.ShutdownCores();
|
||||
applet_manager.Reset();
|
||||
@ -480,6 +481,7 @@ struct System::Impl {
|
||||
cpu_manager.Shutdown();
|
||||
debugger.reset();
|
||||
kernel.Shutdown();
|
||||
stop_event = {};
|
||||
Network::RestartSocketOperations();
|
||||
|
||||
if (auto room_member = room_network.GetRoomMember().lock()) {
|
||||
@ -615,6 +617,7 @@ struct System::Impl {
|
||||
|
||||
ExecuteProgramCallback execute_program_callback;
|
||||
ExitCallback exit_callback;
|
||||
std::stop_source stop_event;
|
||||
|
||||
std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{};
|
||||
std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_cpu{};
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "core/file_sys/system_archive/data/font_standard.h"
|
||||
#include "core/file_sys/system_archive/shared_font.h"
|
||||
#include "core/file_sys/vfs/vfs_vector.h"
|
||||
#include "core/hle/service/ns/iplatform_service_manager.h"
|
||||
#include "core/hle/service/ns/platform_service_manager.h"
|
||||
|
||||
namespace FileSys::SystemArchive {
|
||||
|
||||
|
@ -329,9 +329,8 @@ bool ProfileManager::GetProfileBaseAndData(const ProfileInfo& user, ProfileBase&
|
||||
|
||||
/// Returns if the system is allowing user registrations or not
|
||||
bool ProfileManager::CanSystemRegisterUser() const {
|
||||
return false; // TODO(ogniK): Games shouldn't have
|
||||
// access to user registration, when we
|
||||
// emulate qlaunch. Update this to dynamically change.
|
||||
// TODO: Both games and applets can register users. Determine when this condition is not meet.
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProfileManager::RemoveUser(UUID uuid) {
|
||||
|
@ -8,13 +8,13 @@
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
|
||||
void LoopProcess(Core::System& system) {
|
||||
auto server_manager = std::make_unique<ServerManager>(system);
|
||||
|
||||
server_manager->RegisterNamedService(
|
||||
"appletAE", std::make_shared<IAllSystemAppletProxiesService>(system, nvnflinger));
|
||||
server_manager->RegisterNamedService(
|
||||
"appletOE", std::make_shared<IApplicationProxyService>(system, nvnflinger));
|
||||
server_manager->RegisterNamedService("appletAE",
|
||||
std::make_shared<IAllSystemAppletProxiesService>(system));
|
||||
server_manager->RegisterNamedService("appletOE",
|
||||
std::make_shared<IApplicationProxyService>(system));
|
||||
ServerManager::RunServer(std::move(server_manager));
|
||||
}
|
||||
|
||||
|
@ -7,12 +7,8 @@ namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Service::Nvnflinger {
|
||||
class Nvnflinger;
|
||||
}
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system);
|
||||
void LoopProcess(Core::System& system);
|
||||
|
||||
} // namespace Service::AM
|
||||
|
@ -14,10 +14,9 @@
|
||||
|
||||
#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/managed_layer_holder.h"
|
||||
#include "core/hle/service/am/process.h"
|
||||
#include "core/hle/service/am/system_buffer_manager.h"
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
@ -54,8 +53,7 @@ struct Applet {
|
||||
HidRegistration hid_registration;
|
||||
|
||||
// vi state
|
||||
SystemBufferManager system_buffer_manager{};
|
||||
ManagedLayerHolder managed_layer_holder{};
|
||||
DisplayLayerManager display_layer_manager{};
|
||||
|
||||
// Applet common functions
|
||||
Result terminate_result{};
|
||||
|
@ -35,6 +35,21 @@ AppletStorageChannel& InitializeFakeCallerApplet(Core::System& system,
|
||||
return applet->caller_applet_broker->GetInData();
|
||||
}
|
||||
|
||||
void PushInShowQlaunch(Core::System& system, AppletStorageChannel& channel) {
|
||||
const CommonArguments arguments{
|
||||
.arguments_version = CommonArgumentVersion::Version3,
|
||||
.size = CommonArgumentSize::Version3,
|
||||
.library_version = 0,
|
||||
.theme_color = ThemeColor::BasicBlack,
|
||||
.play_startup_sound = true,
|
||||
.system_tick = system.CoreTiming().GetClockTicks(),
|
||||
};
|
||||
|
||||
std::vector<u8> argument_data(sizeof(arguments));
|
||||
std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
|
||||
channel.Push(std::make_shared<IStorage>(system, std::move(argument_data)));
|
||||
}
|
||||
|
||||
void PushInShowAlbum(Core::System& system, AppletStorageChannel& channel) {
|
||||
const CommonArguments arguments{
|
||||
.arguments_version = CommonArgumentVersion::Version3,
|
||||
@ -284,6 +299,9 @@ void AppletManager::CreateAndInsertByFrontendAppletParameters(
|
||||
|
||||
// Starting from frontend, some applets require input data.
|
||||
switch (applet->applet_id) {
|
||||
case AppletId::QLaunch:
|
||||
PushInShowQlaunch(m_system, InitializeFakeCallerApplet(m_system, applet));
|
||||
break;
|
||||
case AppletId::Cabinet:
|
||||
PushInShowCabinetData(m_system, InitializeFakeCallerApplet(m_system, applet));
|
||||
break;
|
||||
|
151
src/core/hle/service/am/display_layer_manager.cpp
Executable file
151
src/core/hle/service/am/display_layer_manager.cpp
Executable file
@ -0,0 +1,151 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/hle/service/am/display_layer_manager.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
#include "core/hle/service/vi/application_display_service.h"
|
||||
#include "core/hle/service/vi/container.h"
|
||||
#include "core/hle/service/vi/manager_display_service.h"
|
||||
#include "core/hle/service/vi/manager_root_service.h"
|
||||
#include "core/hle/service/vi/shared_buffer_manager.h"
|
||||
#include "core/hle/service/vi/vi_results.h"
|
||||
#include "core/hle/service/vi/vi_types.h"
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
DisplayLayerManager::DisplayLayerManager() = default;
|
||||
DisplayLayerManager::~DisplayLayerManager() {
|
||||
this->Finalize();
|
||||
}
|
||||
|
||||
void DisplayLayerManager::Initialize(Core::System& system, Kernel::KProcess* process,
|
||||
AppletId applet_id, LibraryAppletMode mode) {
|
||||
R_ASSERT(system.ServiceManager()
|
||||
.GetService<VI::IManagerRootService>("vi:m", true)
|
||||
->GetDisplayService(&m_display_service, VI::Policy::Compositor));
|
||||
R_ASSERT(m_display_service->GetManagerDisplayService(&m_manager_display_service));
|
||||
|
||||
m_process = process;
|
||||
m_system_shared_buffer_id = 0;
|
||||
m_system_shared_layer_id = 0;
|
||||
m_applet_id = applet_id;
|
||||
m_buffer_sharing_enabled = false;
|
||||
m_blending_enabled = mode == LibraryAppletMode::PartialForeground ||
|
||||
mode == LibraryAppletMode::PartialForegroundIndirectDisplay;
|
||||
}
|
||||
|
||||
void DisplayLayerManager::Finalize() {
|
||||
if (!m_manager_display_service) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clean up managed layers.
|
||||
for (const auto& layer : m_managed_display_layers) {
|
||||
m_manager_display_service->DestroyManagedLayer(layer);
|
||||
}
|
||||
|
||||
for (const auto& layer : m_managed_display_recording_layers) {
|
||||
m_manager_display_service->DestroyManagedLayer(layer);
|
||||
}
|
||||
|
||||
// Clean up shared layers.
|
||||
if (m_buffer_sharing_enabled) {
|
||||
m_manager_display_service->DestroySharedLayerSession(m_process);
|
||||
}
|
||||
|
||||
m_manager_display_service = nullptr;
|
||||
m_display_service = nullptr;
|
||||
}
|
||||
|
||||
Result DisplayLayerManager::CreateManagedDisplayLayer(u64* out_layer_id) {
|
||||
R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed);
|
||||
|
||||
// TODO(Subv): Find out how AM determines the display to use, for now just
|
||||
// create the layer in the Default display.
|
||||
u64 display_id;
|
||||
R_TRY(m_display_service->OpenDisplay(&display_id, VI::DisplayName{"Default"}));
|
||||
R_TRY(m_manager_display_service->CreateManagedLayer(
|
||||
out_layer_id, 0, display_id, Service::AppletResourceUserId{m_process->GetProcessId()}));
|
||||
|
||||
m_manager_display_service->SetLayerVisibility(m_visible, *out_layer_id);
|
||||
m_managed_display_layers.emplace(*out_layer_id);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result DisplayLayerManager::CreateManagedDisplaySeparableLayer(u64* out_layer_id,
|
||||
u64* out_recording_layer_id) {
|
||||
R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed);
|
||||
|
||||
// TODO(Subv): Find out how AM determines the display to use, for now just
|
||||
// create the layer in the Default display.
|
||||
// This calls nn::vi::CreateRecordingLayer() which creates another layer.
|
||||
// Currently we do not support more than 1 layer per display, output 1 layer id for now.
|
||||
// Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse
|
||||
// side effects.
|
||||
*out_recording_layer_id = 0;
|
||||
R_RETURN(this->CreateManagedDisplayLayer(out_layer_id));
|
||||
}
|
||||
|
||||
Result DisplayLayerManager::IsSystemBufferSharingEnabled() {
|
||||
// Succeed if already enabled.
|
||||
R_SUCCEED_IF(m_buffer_sharing_enabled);
|
||||
|
||||
// Ensure we can access shared layers.
|
||||
R_UNLESS(m_manager_display_service != nullptr, VI::ResultOperationFailed);
|
||||
R_UNLESS(m_applet_id != AppletId::Application, VI::ResultPermissionDenied);
|
||||
|
||||
// Create the shared layer.
|
||||
u64 display_id;
|
||||
R_TRY(m_display_service->OpenDisplay(&display_id, VI::DisplayName{"Default"}));
|
||||
R_TRY(m_manager_display_service->CreateSharedLayerSession(m_process, &m_system_shared_buffer_id,
|
||||
&m_system_shared_layer_id, display_id,
|
||||
m_blending_enabled));
|
||||
|
||||
// We succeeded, so set up remaining state.
|
||||
m_buffer_sharing_enabled = true;
|
||||
m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result DisplayLayerManager::GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id,
|
||||
u64* out_system_shared_layer_id) {
|
||||
R_TRY(this->IsSystemBufferSharingEnabled());
|
||||
|
||||
*out_system_shared_buffer_id = m_system_shared_buffer_id;
|
||||
*out_system_shared_layer_id = m_system_shared_layer_id;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void DisplayLayerManager::SetWindowVisibility(bool visible) {
|
||||
if (m_visible == visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_visible = visible;
|
||||
|
||||
if (m_manager_display_service) {
|
||||
if (m_system_shared_layer_id) {
|
||||
m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id);
|
||||
}
|
||||
|
||||
for (const auto layer_id : m_managed_display_layers) {
|
||||
m_manager_display_service->SetLayerVisibility(m_visible, layer_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DisplayLayerManager::GetWindowVisibility() const {
|
||||
return m_visible;
|
||||
}
|
||||
|
||||
Result DisplayLayerManager::WriteAppletCaptureBuffer(bool* out_was_written,
|
||||
s32* out_fbshare_layer_index) {
|
||||
R_UNLESS(m_buffer_sharing_enabled, VI::ResultPermissionDenied);
|
||||
R_RETURN(m_display_service->GetContainer()->GetSharedBufferManager()->WriteAppletCaptureBuffer(
|
||||
out_was_written, out_fbshare_layer_index));
|
||||
}
|
||||
|
||||
} // namespace Service::AM
|
62
src/core/hle/service/am/display_layer_manager.h
Executable file
62
src/core/hle/service/am/display_layer_manager.h
Executable file
@ -0,0 +1,62 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/am/am_types.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Kernel {
|
||||
class KProcess;
|
||||
}
|
||||
|
||||
namespace Service::VI {
|
||||
class IApplicationDisplayService;
|
||||
class IManagerDisplayService;
|
||||
} // namespace Service::VI
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
class DisplayLayerManager {
|
||||
public:
|
||||
explicit DisplayLayerManager();
|
||||
~DisplayLayerManager();
|
||||
|
||||
void Initialize(Core::System& system, Kernel::KProcess* process, AppletId applet_id,
|
||||
LibraryAppletMode mode);
|
||||
void Finalize();
|
||||
|
||||
Result CreateManagedDisplayLayer(u64* out_layer_id);
|
||||
Result CreateManagedDisplaySeparableLayer(u64* out_layer_id, u64* out_recording_layer_id);
|
||||
|
||||
Result IsSystemBufferSharingEnabled();
|
||||
Result GetSystemSharedLayerHandle(u64* out_system_shared_buffer_id,
|
||||
u64* out_system_shared_layer_id);
|
||||
|
||||
void SetWindowVisibility(bool visible);
|
||||
bool GetWindowVisibility() const;
|
||||
|
||||
Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index);
|
||||
|
||||
private:
|
||||
Kernel::KProcess* m_process{};
|
||||
std::shared_ptr<VI::IApplicationDisplayService> m_display_service{};
|
||||
std::shared_ptr<VI::IManagerDisplayService> m_manager_display_service{};
|
||||
std::set<u64> m_managed_display_layers{};
|
||||
std::set<u64> m_managed_display_recording_layers{};
|
||||
u64 m_system_shared_buffer_id{};
|
||||
u64 m_system_shared_layer_id{};
|
||||
AppletId m_applet_id{};
|
||||
bool m_buffer_sharing_enabled{};
|
||||
bool m_blending_enabled{};
|
||||
bool m_visible{true};
|
||||
};
|
||||
|
||||
} // namespace Service::AM
|
@ -22,7 +22,7 @@
|
||||
#include "core/hle/service/am/frontend/applet_web_browser.h"
|
||||
#include "core/hle/service/am/service/storage.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/hle/service/ns/iplatform_service_manager.h"
|
||||
#include "core/hle/service/ns/platform_service_manager.h"
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
namespace Service::AM::Frontend {
|
||||
|
@ -10,9 +10,8 @@
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_,
|
||||
Nvnflinger::Nvnflinger& nvnflinger)
|
||||
: ServiceFramework{system_, "appletAE"}, m_nvnflinger{nvnflinger} {
|
||||
IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& system_)
|
||||
: ServiceFramework{system_, "appletAE"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{100, D<&IAllSystemAppletProxiesService::OpenSystemAppletProxy>, "OpenSystemAppletProxy"},
|
||||
@ -37,8 +36,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(), m_nvnflinger);
|
||||
*out_system_applet_proxy =
|
||||
std::make_shared<ISystemAppletProxy>(system, applet, process_handle.Get());
|
||||
R_SUCCEED();
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
@ -53,8 +52,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(), m_nvnflinger);
|
||||
*out_library_applet_proxy =
|
||||
std::make_shared<ILibraryAppletProxy>(system, applet, process_handle.Get());
|
||||
R_SUCCEED();
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
|
@ -8,10 +8,6 @@
|
||||
|
||||
namespace Service {
|
||||
|
||||
namespace Nvnflinger {
|
||||
class Nvnflinger;
|
||||
}
|
||||
|
||||
namespace AM {
|
||||
|
||||
struct Applet;
|
||||
@ -22,8 +18,7 @@ class ISystemAppletProxy;
|
||||
class IAllSystemAppletProxiesService final
|
||||
: public ServiceFramework<IAllSystemAppletProxiesService> {
|
||||
public:
|
||||
explicit IAllSystemAppletProxiesService(Core::System& system_,
|
||||
Nvnflinger::Nvnflinger& nvnflinger);
|
||||
explicit IAllSystemAppletProxiesService(Core::System& system_);
|
||||
~IAllSystemAppletProxiesService() override;
|
||||
|
||||
private:
|
||||
@ -40,7 +35,6 @@ private:
|
||||
|
||||
private:
|
||||
std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);
|
||||
Nvnflinger::Nvnflinger& m_nvnflinger;
|
||||
};
|
||||
|
||||
} // namespace AM
|
||||
|
@ -15,7 +15,8 @@
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/hle/service/filesystem/save_data_controller.h"
|
||||
#include "core/hle/service/ns/ns.h"
|
||||
#include "core/hle/service/ns/application_manager_interface.h"
|
||||
#include "core/hle/service/ns/service_getter_interface.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Service::AM {
|
||||
@ -162,11 +163,13 @@ Result IApplicationFunctions::GetDesiredLanguage(Out<u64> out_language_code) {
|
||||
|
||||
// Call IApplicationManagerInterface implementation.
|
||||
auto& service_manager = system.ServiceManager();
|
||||
auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2");
|
||||
auto app_man = ns_am2->GetApplicationManagerInterface();
|
||||
auto ns_am2 = service_manager.GetService<NS::IServiceGetterInterface>("ns:am2");
|
||||
|
||||
std::shared_ptr<NS::IApplicationManagerInterface> app_man;
|
||||
R_TRY(ns_am2->GetApplicationManagerInterface(&app_man));
|
||||
|
||||
// Get desired application language
|
||||
u8 desired_language{};
|
||||
NS::ApplicationLanguage desired_language{};
|
||||
R_TRY(app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages));
|
||||
|
||||
// Convert to settings language code.
|
||||
|
@ -17,9 +17,9 @@
|
||||
namespace Service::AM {
|
||||
|
||||
IApplicationProxy::IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||
Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger)
|
||||
: ServiceFramework{system_, "IApplicationProxy"},
|
||||
m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} {
|
||||
Kernel::KProcess* process)
|
||||
: ServiceFramework{system_, "IApplicationProxy"}, m_process{process}, m_applet{
|
||||
std::move(applet)} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IApplicationProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
||||
@ -77,8 +77,7 @@ Result IApplicationProxy::GetWindowController(
|
||||
Result IApplicationProxy::GetSelfController(
|
||||
Out<SharedPointer<ISelfController>> out_self_controller) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
*out_self_controller =
|
||||
std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger);
|
||||
*out_self_controller = std::make_shared<ISelfController>(system, m_applet, m_process);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ class IWindowController;
|
||||
class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
|
||||
public:
|
||||
explicit IApplicationProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||
Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger);
|
||||
Kernel::KProcess* process);
|
||||
~IApplicationProxy();
|
||||
|
||||
private:
|
||||
@ -40,7 +40,6 @@ private:
|
||||
Out<SharedPointer<IApplicationFunctions>> out_application_functions);
|
||||
|
||||
private:
|
||||
Nvnflinger::Nvnflinger& m_nvnflinger;
|
||||
Kernel::KProcess* const m_process;
|
||||
const std::shared_ptr<Applet> m_applet;
|
||||
};
|
||||
|
@ -10,9 +10,8 @@
|
||||
|
||||
namespace Service::AM {
|
||||
|
||||
IApplicationProxyService::IApplicationProxyService(Core::System& system_,
|
||||
Nvnflinger::Nvnflinger& nvnflinger)
|
||||
: ServiceFramework{system_, "appletOE"}, m_nvnflinger{nvnflinger} {
|
||||
IApplicationProxyService::IApplicationProxyService(Core::System& system_)
|
||||
: ServiceFramework{system_, "appletOE"} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IApplicationProxyService::OpenApplicationProxy>, "OpenApplicationProxy"},
|
||||
};
|
||||
@ -28,7 +27,7 @@ Result IApplicationProxyService::OpenApplicationProxy(
|
||||
|
||||
if (const auto applet = this->GetAppletFromProcessId(pid)) {
|
||||
*out_application_proxy =
|
||||
std::make_shared<IApplicationProxy>(system, applet, process_handle.Get(), m_nvnflinger);
|
||||
std::make_shared<IApplicationProxy>(system, applet, process_handle.Get());
|
||||
R_SUCCEED();
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
|
@ -8,10 +8,6 @@
|
||||
|
||||
namespace Service {
|
||||
|
||||
namespace Nvnflinger {
|
||||
class Nvnflinger;
|
||||
}
|
||||
|
||||
namespace AM {
|
||||
|
||||
struct Applet;
|
||||
@ -19,7 +15,7 @@ class IApplicationProxy;
|
||||
|
||||
class IApplicationProxyService final : public ServiceFramework<IApplicationProxyService> {
|
||||
public:
|
||||
explicit IApplicationProxyService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger);
|
||||
explicit IApplicationProxyService(Core::System& system_);
|
||||
~IApplicationProxyService() override;
|
||||
|
||||
private:
|
||||
@ -28,7 +24,6 @@ private:
|
||||
|
||||
private:
|
||||
std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);
|
||||
Nvnflinger::Nvnflinger& m_nvnflinger;
|
||||
};
|
||||
|
||||
} // namespace AM
|
||||
|
@ -69,7 +69,7 @@ Result IDisplayController::ClearCaptureBuffer(bool unknown0, s32 fbshare_layer_i
|
||||
Result IDisplayController::AcquireLastForegroundCaptureSharedBuffer(
|
||||
Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written,
|
||||
R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written,
|
||||
out_fbshare_layer_index));
|
||||
}
|
||||
|
||||
@ -81,7 +81,7 @@ Result IDisplayController::ReleaseLastForegroundCaptureSharedBuffer() {
|
||||
Result IDisplayController::AcquireCallerAppletCaptureSharedBuffer(
|
||||
Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written,
|
||||
R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written,
|
||||
out_fbshare_layer_index));
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ Result IDisplayController::ReleaseCallerAppletCaptureSharedBuffer() {
|
||||
Result IDisplayController::AcquireLastApplicationCaptureSharedBuffer(
|
||||
Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
R_RETURN(applet->system_buffer_manager.WriteAppletCaptureBuffer(out_was_written,
|
||||
R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written,
|
||||
out_fbshare_layer_index));
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,7 @@ std::shared_ptr<ILibraryAppletAccessor> CreateGuestApplet(Core::System& system,
|
||||
case LibraryAppletMode::AllForegroundInitiallyHidden:
|
||||
applet->hid_registration.EnableAppletToGetInput(false);
|
||||
applet->focus_state = FocusState::NotInFocus;
|
||||
applet->system_buffer_manager.SetWindowVisibility(false);
|
||||
applet->display_layer_manager.SetWindowVisibility(false);
|
||||
applet->message_queue.PushMessage(AppletMessage::ChangeIntoBackground);
|
||||
break;
|
||||
}
|
||||
|
@ -19,10 +19,9 @@
|
||||
namespace Service::AM {
|
||||
|
||||
ILibraryAppletProxy::ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||
Kernel::KProcess* process,
|
||||
Nvnflinger::Nvnflinger& nvnflinger)
|
||||
: ServiceFramework{system_, "ILibraryAppletProxy"},
|
||||
m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} {
|
||||
Kernel::KProcess* process)
|
||||
: ServiceFramework{system_, "ILibraryAppletProxy"}, m_process{process}, m_applet{
|
||||
std::move(applet)} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&ILibraryAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
||||
@ -83,8 +82,7 @@ Result ILibraryAppletProxy::GetWindowController(
|
||||
Result ILibraryAppletProxy::GetSelfController(
|
||||
Out<SharedPointer<ISelfController>> out_self_controller) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
*out_self_controller =
|
||||
std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger);
|
||||
*out_self_controller = std::make_shared<ISelfController>(system, m_applet, m_process);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ class IWindowController;
|
||||
class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
|
||||
public:
|
||||
explicit ILibraryAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||
Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger);
|
||||
Kernel::KProcess* process);
|
||||
~ILibraryAppletProxy();
|
||||
|
||||
private:
|
||||
@ -47,7 +47,6 @@ private:
|
||||
Result GetGlobalStateController(
|
||||
Out<SharedPointer<IGlobalStateController>> out_global_state_controller);
|
||||
|
||||
Nvnflinger::Nvnflinger& m_nvnflinger;
|
||||
Kernel::KProcess* const m_process;
|
||||
const std::shared_ptr<Applet> m_applet;
|
||||
};
|
||||
|
@ -14,7 +14,8 @@
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/hle/service/glue/glue_manager.h"
|
||||
#include "core/hle/service/ns/ns.h"
|
||||
#include "core/hle/service/ns/application_manager_interface.h"
|
||||
#include "core/hle/service/ns/service_getter_interface.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Service::AM {
|
||||
@ -256,11 +257,13 @@ Result ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage(
|
||||
|
||||
// Call IApplicationManagerInterface implementation.
|
||||
auto& service_manager = system.ServiceManager();
|
||||
auto ns_am2 = service_manager.GetService<NS::NS>("ns:am2");
|
||||
auto app_man = ns_am2->GetApplicationManagerInterface();
|
||||
auto ns_am2 = service_manager.GetService<NS::IServiceGetterInterface>("ns:am2");
|
||||
|
||||
std::shared_ptr<NS::IApplicationManagerInterface> app_man;
|
||||
R_TRY(ns_am2->GetApplicationManagerInterface(&app_man));
|
||||
|
||||
// Get desired application language
|
||||
u8 desired_language{};
|
||||
NS::ApplicationLanguage desired_language{};
|
||||
R_TRY(app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages));
|
||||
|
||||
// Convert to settings language code.
|
||||
@ -284,17 +287,17 @@ Result ILibraryAppletSelfAccessor::GetCurrentApplicationId(Out<u64> out_applicat
|
||||
}
|
||||
|
||||
Result ILibraryAppletSelfAccessor::GetMainAppletAvailableUsers(
|
||||
Out<bool> out_no_users_available, Out<s32> out_users_count,
|
||||
Out<bool> out_can_select_any_user, Out<s32> out_users_count,
|
||||
OutArray<Common::UUID, BufferAttr_HipcMapAlias> out_users) {
|
||||
const Service::Account::ProfileManager manager{};
|
||||
|
||||
*out_no_users_available = true;
|
||||
*out_can_select_any_user = false;
|
||||
*out_users_count = -1;
|
||||
|
||||
LOG_INFO(Service_AM, "called");
|
||||
|
||||
if (manager.GetUserCount() > 0) {
|
||||
*out_no_users_available = false;
|
||||
*out_can_select_any_user = true;
|
||||
*out_users_count = static_cast<s32>(manager.GetUserCount());
|
||||
|
||||
const auto users = manager.GetAllUsers();
|
||||
|
@ -71,7 +71,7 @@ private:
|
||||
ErrorCode error_code, InLargeData<ErrorContext, BufferAttr_HipcMapAlias> error_context);
|
||||
Result GetMainAppletApplicationDesiredLanguage(Out<u64> out_desired_language);
|
||||
Result GetCurrentApplicationId(Out<u64> out_application_id);
|
||||
Result GetMainAppletAvailableUsers(Out<bool> out_no_users_available, Out<s32> out_users_count,
|
||||
Result GetMainAppletAvailableUsers(Out<bool> out_can_select_any_user, Out<s32> out_users_count,
|
||||
OutArray<Common::UUID, BufferAttr_HipcMapAlias> out_users);
|
||||
Result ShouldSetGpuTimeSliceManually(Out<bool> out_should_set_gpu_time_slice_manually);
|
||||
Result Cmd160(Out<u64> out_unknown0);
|
||||
|
@ -15,9 +15,9 @@
|
||||
namespace Service::AM {
|
||||
|
||||
ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||
Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger)
|
||||
: ServiceFramework{system_, "ISelfController"},
|
||||
m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} {
|
||||
Kernel::KProcess* process)
|
||||
: ServiceFramework{system_, "ISelfController"}, m_process{process}, m_applet{
|
||||
std::move(applet)} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&ISelfController::Exit>, "Exit"},
|
||||
@ -72,9 +72,16 @@ ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet>
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
std::scoped_lock lk{m_applet->lock};
|
||||
m_applet->display_layer_manager.Initialize(system, m_process, m_applet->applet_id,
|
||||
m_applet->library_applet_mode);
|
||||
}
|
||||
|
||||
ISelfController::~ISelfController() = default;
|
||||
ISelfController::~ISelfController() {
|
||||
std::scoped_lock lk{m_applet->lock};
|
||||
m_applet->display_layer_manager.Finalize();
|
||||
}
|
||||
|
||||
Result ISelfController::Exit() {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
@ -212,48 +219,42 @@ Result ISelfController::SetAlbumImageOrientation(
|
||||
|
||||
Result ISelfController::IsSystemBufferSharingEnabled() {
|
||||
LOG_INFO(Service_AM, "called");
|
||||
R_SUCCEED_IF(m_applet->system_buffer_manager.Initialize(
|
||||
&m_nvnflinger, m_process, m_applet->applet_id, m_applet->library_applet_mode));
|
||||
R_THROW(VI::ResultOperationFailed);
|
||||
|
||||
std::scoped_lock lk{m_applet->lock};
|
||||
R_RETURN(m_applet->display_layer_manager.IsSystemBufferSharingEnabled());
|
||||
}
|
||||
|
||||
Result ISelfController::GetSystemSharedBufferHandle(Out<u64> out_buffer_id) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
|
||||
R_TRY(this->IsSystemBufferSharingEnabled());
|
||||
LOG_INFO(Service_AM, "called");
|
||||
|
||||
u64 layer_id;
|
||||
m_applet->system_buffer_manager.GetSystemSharedLayerHandle(out_buffer_id, &layer_id);
|
||||
R_SUCCEED();
|
||||
|
||||
std::scoped_lock lk{m_applet->lock};
|
||||
R_RETURN(m_applet->display_layer_manager.GetSystemSharedLayerHandle(out_buffer_id, &layer_id));
|
||||
}
|
||||
|
||||
Result ISelfController::GetSystemSharedLayerHandle(Out<u64> out_buffer_id, Out<u64> out_layer_id) {
|
||||
LOG_INFO(Service_AM, "(STUBBED) called");
|
||||
LOG_INFO(Service_AM, "called");
|
||||
|
||||
R_TRY(this->IsSystemBufferSharingEnabled());
|
||||
|
||||
m_applet->system_buffer_manager.GetSystemSharedLayerHandle(out_buffer_id, out_layer_id);
|
||||
R_SUCCEED();
|
||||
std::scoped_lock lk{m_applet->lock};
|
||||
R_RETURN(
|
||||
m_applet->display_layer_manager.GetSystemSharedLayerHandle(out_buffer_id, out_layer_id));
|
||||
}
|
||||
|
||||
Result ISelfController::CreateManagedDisplayLayer(Out<u64> out_layer_id) {
|
||||
LOG_INFO(Service_AM, "called");
|
||||
|
||||
m_applet->managed_layer_holder.Initialize(&m_nvnflinger);
|
||||
m_applet->managed_layer_holder.CreateManagedDisplayLayer(out_layer_id);
|
||||
|
||||
R_SUCCEED();
|
||||
std::scoped_lock lk{m_applet->lock};
|
||||
R_RETURN(m_applet->display_layer_manager.CreateManagedDisplayLayer(out_layer_id));
|
||||
}
|
||||
|
||||
Result ISelfController::CreateManagedDisplaySeparableLayer(Out<u64> out_layer_id,
|
||||
Out<u64> out_recording_layer_id) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
|
||||
m_applet->managed_layer_holder.Initialize(&m_nvnflinger);
|
||||
m_applet->managed_layer_holder.CreateManagedDisplaySeparableLayer(out_layer_id,
|
||||
out_recording_layer_id);
|
||||
|
||||
R_SUCCEED();
|
||||
std::scoped_lock lk{m_applet->lock};
|
||||
R_RETURN(m_applet->display_layer_manager.CreateManagedDisplaySeparableLayer(
|
||||
out_layer_id, out_recording_layer_id));
|
||||
}
|
||||
|
||||
Result ISelfController::SetHandlesRequestToDisplay(bool enable) {
|
||||
|
@ -23,7 +23,7 @@ struct Applet;
|
||||
class ISelfController final : public ServiceFramework<ISelfController> {
|
||||
public:
|
||||
explicit ISelfController(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||
Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger);
|
||||
Kernel::KProcess* process);
|
||||
~ISelfController() override;
|
||||
|
||||
private:
|
||||
@ -64,7 +64,6 @@ private:
|
||||
Result SaveCurrentScreenshot(Capture::AlbumReportOption album_report_option);
|
||||
Result SetRecordVolumeMuted(bool muted);
|
||||
|
||||
Nvnflinger::Nvnflinger& m_nvnflinger;
|
||||
Kernel::KProcess* const m_process;
|
||||
const std::shared_ptr<Applet> m_applet;
|
||||
};
|
||||
|
@ -19,10 +19,9 @@
|
||||
namespace Service::AM {
|
||||
|
||||
ISystemAppletProxy::ISystemAppletProxy(Core::System& system_, std::shared_ptr<Applet> applet,
|
||||
Kernel::KProcess* process,
|
||||
Nvnflinger::Nvnflinger& nvnflinger)
|
||||
: ServiceFramework{system_, "ISystemAppletProxy"},
|
||||
m_nvnflinger{nvnflinger}, m_process{process}, m_applet{std::move(applet)} {
|
||||
Kernel::KProcess* process)
|
||||
: ServiceFramework{system_, "ISystemAppletProxy"}, m_process{process}, m_applet{
|
||||
std::move(applet)} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&ISystemAppletProxy::GetCommonStateGetter>, "GetCommonStateGetter"},
|
||||
@ -83,8 +82,7 @@ Result ISystemAppletProxy::GetWindowController(
|
||||
Result ISystemAppletProxy::GetSelfController(
|
||||
Out<SharedPointer<ISelfController>> out_self_controller) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
*out_self_controller =
|
||||
std::make_shared<ISelfController>(system, m_applet, m_process, m_nvnflinger);
|
||||
*out_self_controller = std::make_shared<ISelfController>(system, m_applet, m_process);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ class IWindowController;
|
||||
class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
|
||||
public:
|
||||
explicit ISystemAppletProxy(Core::System& system, std::shared_ptr<Applet> applet,
|
||||
Kernel::KProcess* process, Nvnflinger::Nvnflinger& nvnflinger);
|
||||
Kernel::KProcess* process);
|
||||
~ISystemAppletProxy();
|
||||
|
||||
private:
|
||||
@ -46,7 +46,6 @@ private:
|
||||
Result GetGlobalStateController(
|
||||
Out<SharedPointer<IGlobalStateController>> out_global_state_controller);
|
||||
|
||||
Nvnflinger::Nvnflinger& m_nvnflinger;
|
||||
Kernel::KProcess* const m_process;
|
||||
const std::shared_ptr<Applet> m_applet;
|
||||
};
|
||||
|
@ -63,7 +63,7 @@ Result IWindowController::RejectToChangeIntoBackground() {
|
||||
}
|
||||
|
||||
Result IWindowController::SetAppletWindowVisibility(bool visible) {
|
||||
m_applet->system_buffer_manager.SetWindowVisibility(visible);
|
||||
m_applet->display_layer_manager.SetWindowVisibility(visible);
|
||||
m_applet->hid_registration.EnableAppletToGetInput(visible);
|
||||
|
||||
if (visible) {
|
||||
|
@ -2,9 +2,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/hle/service/audio/audctl.h"
|
||||
#include "core/hle/service/audio/audin_u.h"
|
||||
#include "core/hle/service/audio/audio.h"
|
||||
#include "core/hle/service/audio/audio_controller.h"
|
||||
#include "core/hle/service/audio/audout_u.h"
|
||||
#include "core/hle/service/audio/audrec_a.h"
|
||||
#include "core/hle/service/audio/audrec_u.h"
|
||||
@ -18,7 +18,7 @@ namespace Service::Audio {
|
||||
void LoopProcess(Core::System& system) {
|
||||
auto server_manager = std::make_unique<ServerManager>(system);
|
||||
|
||||
server_manager->RegisterNamedService("audctl", std::make_shared<AudCtl>(system));
|
||||
server_manager->RegisterNamedService("audctl", std::make_shared<IAudioController>(system));
|
||||
server_manager->RegisterNamedService("audout:u", std::make_shared<AudOutU>(system));
|
||||
server_manager->RegisterNamedService("audin:u", std::make_shared<AudInU>(system));
|
||||
server_manager->RegisterNamedService("audrec:a", std::make_shared<AudRecA>(system));
|
||||
|
174
src/core/hle/service/audio/audio_controller.cpp
Executable file
174
src/core/hle/service/audio/audio_controller.cpp
Executable file
@ -0,0 +1,174 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/service/audio/audio_controller.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/set/system_settings_server.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Service::Audio {
|
||||
|
||||
IAudioController::IAudioController(Core::System& system_)
|
||||
: ServiceFramework{system_, "audctl"}, service_context{system, "audctl"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetTargetVolume"},
|
||||
{1, nullptr, "SetTargetVolume"},
|
||||
{2, C<&IAudioController::GetTargetVolumeMin>, "GetTargetVolumeMin"},
|
||||
{3, C<&IAudioController::GetTargetVolumeMax>, "GetTargetVolumeMax"},
|
||||
{4, nullptr, "IsTargetMute"},
|
||||
{5, nullptr, "SetTargetMute"},
|
||||
{6, nullptr, "IsTargetConnected"},
|
||||
{7, nullptr, "SetDefaultTarget"},
|
||||
{8, nullptr, "GetDefaultTarget"},
|
||||
{9, C<&IAudioController::GetAudioOutputMode>, "GetAudioOutputMode"},
|
||||
{10, C<&IAudioController::SetAudioOutputMode>, "SetAudioOutputMode"},
|
||||
{11, nullptr, "SetForceMutePolicy"},
|
||||
{12, C<&IAudioController::GetForceMutePolicy>, "GetForceMutePolicy"},
|
||||
{13, C<&IAudioController::GetOutputModeSetting>, "GetOutputModeSetting"},
|
||||
{14, C<&IAudioController::SetOutputModeSetting>, "SetOutputModeSetting"},
|
||||
{15, nullptr, "SetOutputTarget"},
|
||||
{16, nullptr, "SetInputTargetForceEnabled"},
|
||||
{17, C<&IAudioController::SetHeadphoneOutputLevelMode>, "SetHeadphoneOutputLevelMode"},
|
||||
{18, C<&IAudioController::GetHeadphoneOutputLevelMode>, "GetHeadphoneOutputLevelMode"},
|
||||
{19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"},
|
||||
{20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
|
||||
{21, nullptr, "GetAudioOutputTargetForPlayReport"},
|
||||
{22, nullptr, "NotifyHeadphoneVolumeWarningDisplayedEvent"},
|
||||
{23, nullptr, "SetSystemOutputMasterVolume"},
|
||||
{24, nullptr, "GetSystemOutputMasterVolume"},
|
||||
{25, nullptr, "GetAudioVolumeDataForPlayReport"},
|
||||
{26, nullptr, "UpdateHeadphoneSettings"},
|
||||
{27, nullptr, "SetVolumeMappingTableForDev"},
|
||||
{28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
|
||||
{29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
|
||||
{30, C<&IAudioController::SetSpeakerAutoMuteEnabled>, "SetSpeakerAutoMuteEnabled"},
|
||||
{31, C<&IAudioController::IsSpeakerAutoMuteEnabled>, "IsSpeakerAutoMuteEnabled"},
|
||||
{32, nullptr, "GetActiveOutputTarget"},
|
||||
{33, nullptr, "GetTargetDeviceInfo"},
|
||||
{34, C<&IAudioController::AcquireTargetNotification>, "AcquireTargetNotification"},
|
||||
{35, nullptr, "SetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
|
||||
{36, nullptr, "GetHearingProtectionSafeguardTimerRemainingTimeForDebug"},
|
||||
{37, nullptr, "SetHearingProtectionSafeguardEnabled"},
|
||||
{38, nullptr, "IsHearingProtectionSafeguardEnabled"},
|
||||
{39, nullptr, "IsHearingProtectionSafeguardMonitoringOutputForDebug"},
|
||||
{40, nullptr, "GetSystemInformationForDebug"},
|
||||
{41, nullptr, "SetVolumeButtonLongPressTime"},
|
||||
{42, nullptr, "SetNativeVolumeForDebug"},
|
||||
{10000, nullptr, "NotifyAudioOutputTargetForPlayReport"},
|
||||
{10001, nullptr, "NotifyAudioOutputChannelCountForPlayReport"},
|
||||
{10002, nullptr, "NotifyUnsupportedUsbOutputDeviceAttachedForPlayReport"},
|
||||
{10100, nullptr, "GetAudioVolumeDataForPlayReport"},
|
||||
{10101, nullptr, "BindAudioVolumeUpdateEventForPlayReport"},
|
||||
{10102, nullptr, "BindAudioOutputTargetUpdateEventForPlayReport"},
|
||||
{10103, nullptr, "GetAudioOutputTargetForPlayReport"},
|
||||
{10104, nullptr, "GetAudioOutputChannelCountForPlayReport"},
|
||||
{10105, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
|
||||
{10106, nullptr, "GetDefaultAudioOutputTargetForPlayReport"},
|
||||
{50000, nullptr, "SetAnalogInputBoostGainForPrototyping"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
m_set_sys =
|
||||
system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
|
||||
notification_event = service_context.CreateEvent("IAudioController:NotificationEvent");
|
||||
}
|
||||
|
||||
IAudioController::~IAudioController() {
|
||||
service_context.CloseEvent(notification_event);
|
||||
};
|
||||
|
||||
Result IAudioController::GetTargetVolumeMin(Out<s32> out_target_min_volume) {
|
||||
LOG_DEBUG(Audio, "called.");
|
||||
|
||||
// This service function is currently hardcoded on the
|
||||
// actual console to this value (as of 8.0.0).
|
||||
*out_target_min_volume = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IAudioController::GetTargetVolumeMax(Out<s32> out_target_max_volume) {
|
||||
LOG_DEBUG(Audio, "called.");
|
||||
|
||||
// This service function is currently hardcoded on the
|
||||
// actual console to this value (as of 8.0.0).
|
||||
*out_target_max_volume = 15;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IAudioController::GetAudioOutputMode(Out<Set::AudioOutputMode> out_output_mode,
|
||||
Set::AudioOutputModeTarget target) {
|
||||
const auto result = m_set_sys->GetAudioOutputMode(out_output_mode, target);
|
||||
|
||||
LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, *out_output_mode);
|
||||
R_RETURN(result);
|
||||
}
|
||||
|
||||
Result IAudioController::SetAudioOutputMode(Set::AudioOutputModeTarget target,
|
||||
Set::AudioOutputMode output_mode) {
|
||||
LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
|
||||
|
||||
R_RETURN(m_set_sys->SetAudioOutputMode(target, output_mode));
|
||||
}
|
||||
|
||||
Result IAudioController::GetForceMutePolicy(Out<ForceMutePolicy> out_mute_policy) {
|
||||
LOG_WARNING(Audio, "(STUBBED) called");
|
||||
|
||||
// Removed on FW 13.2.1+
|
||||
*out_mute_policy = ForceMutePolicy::Disable;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IAudioController::GetOutputModeSetting(Out<Set::AudioOutputMode> out_output_mode,
|
||||
Set::AudioOutputModeTarget target) {
|
||||
LOG_WARNING(Audio, "(STUBBED) called, target={}", target);
|
||||
|
||||
*out_output_mode = Set::AudioOutputMode::ch_7_1;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IAudioController::SetOutputModeSetting(Set::AudioOutputModeTarget target,
|
||||
Set::AudioOutputMode output_mode) {
|
||||
LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IAudioController::SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode) {
|
||||
LOG_WARNING(Audio, "(STUBBED) called");
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IAudioController::GetHeadphoneOutputLevelMode(
|
||||
Out<HeadphoneOutputLevelMode> out_output_level_mode) {
|
||||
LOG_INFO(Audio, "called");
|
||||
|
||||
*out_output_level_mode = HeadphoneOutputLevelMode::Normal;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IAudioController::SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled) {
|
||||
LOG_INFO(Audio, "called, is_speaker_auto_mute_enabled={}", is_speaker_auto_mute_enabled);
|
||||
|
||||
R_RETURN(m_set_sys->SetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled));
|
||||
}
|
||||
|
||||
Result IAudioController::IsSpeakerAutoMuteEnabled(Out<bool> out_is_speaker_auto_mute_enabled) {
|
||||
const auto result = m_set_sys->GetSpeakerAutoMuteFlag(out_is_speaker_auto_mute_enabled);
|
||||
|
||||
LOG_INFO(Audio, "called, is_speaker_auto_mute_enabled={}", *out_is_speaker_auto_mute_enabled);
|
||||
R_RETURN(result);
|
||||
}
|
||||
|
||||
Result IAudioController::AcquireTargetNotification(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_notification_event) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
|
||||
*out_notification_event = ¬ification_event->GetReadableEvent();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::Audio
|
58
src/core/hle/service/audio/audio_controller.h
Executable file
58
src/core/hle/service/audio/audio_controller.h
Executable file
@ -0,0 +1,58 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/set/settings_types.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Service::Set {
|
||||
class ISystemSettingsServer;
|
||||
}
|
||||
|
||||
namespace Service::Audio {
|
||||
|
||||
class IAudioController final : public ServiceFramework<IAudioController> {
|
||||
public:
|
||||
explicit IAudioController(Core::System& system_);
|
||||
~IAudioController() override;
|
||||
|
||||
private:
|
||||
enum class ForceMutePolicy {
|
||||
Disable,
|
||||
SpeakerMuteOnHeadphoneUnplugged,
|
||||
};
|
||||
|
||||
enum class HeadphoneOutputLevelMode {
|
||||
Normal,
|
||||
HighPower,
|
||||
};
|
||||
|
||||
Result GetTargetVolumeMin(Out<s32> out_target_min_volume);
|
||||
Result GetTargetVolumeMax(Out<s32> out_target_max_volume);
|
||||
Result GetAudioOutputMode(Out<Set::AudioOutputMode> out_output_mode,
|
||||
Set::AudioOutputModeTarget target);
|
||||
Result SetAudioOutputMode(Set::AudioOutputModeTarget target, Set::AudioOutputMode output_mode);
|
||||
Result GetForceMutePolicy(Out<ForceMutePolicy> out_mute_policy);
|
||||
Result GetOutputModeSetting(Out<Set::AudioOutputMode> out_output_mode,
|
||||
Set::AudioOutputModeTarget target);
|
||||
Result SetOutputModeSetting(Set::AudioOutputModeTarget target,
|
||||
Set::AudioOutputMode output_mode);
|
||||
Result SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode);
|
||||
Result GetHeadphoneOutputLevelMode(Out<HeadphoneOutputLevelMode> out_output_level_mode);
|
||||
Result SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled);
|
||||
Result IsSpeakerAutoMuteEnabled(Out<bool> out_is_speaker_auto_mute_enabled);
|
||||
Result AcquireTargetNotification(OutCopyHandle<Kernel::KReadableEvent> out_notification_event);
|
||||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
|
||||
Kernel::KEvent* notification_event;
|
||||
std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
|
||||
};
|
||||
|
||||
} // namespace Service::Audio
|
@ -16,7 +16,7 @@ IAlbumAccessorService::IAlbumAccessorService(Core::System& system_,
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetAlbumFileCount"},
|
||||
{1, nullptr, "GetAlbumFileList"},
|
||||
{1, C<&IAlbumAccessorService::GetAlbumFileList>, "GetAlbumFileList"},
|
||||
{2, nullptr, "LoadAlbumFile"},
|
||||
{3, C<&IAlbumAccessorService::DeleteAlbumFile>, "DeleteAlbumFile"},
|
||||
{4, nullptr, "StorageCopyAlbumFile"},
|
||||
@ -62,6 +62,15 @@ IAlbumAccessorService::IAlbumAccessorService(Core::System& system_,
|
||||
|
||||
IAlbumAccessorService::~IAlbumAccessorService() = default;
|
||||
|
||||
Result IAlbumAccessorService::GetAlbumFileList(
|
||||
Out<u64> out_count, AlbumStorage storage,
|
||||
OutArray<AlbumEntry, BufferAttr_HipcMapAlias> out_entries) {
|
||||
LOG_INFO(Service_Capture, "called, storage={}", storage);
|
||||
|
||||
const Result result = manager->GetAlbumFileList(out_entries, *out_count, storage, 0);
|
||||
R_RETURN(TranslateResult(result));
|
||||
}
|
||||
|
||||
Result IAlbumAccessorService::DeleteAlbumFile(AlbumFileId file_id) {
|
||||
LOG_INFO(Service_Capture, "called, application_id=0x{:0x}, storage={}, type={}",
|
||||
file_id.application_id, file_id.storage, file_id.type);
|
||||
|
@ -21,6 +21,9 @@ public:
|
||||
~IAlbumAccessorService() override;
|
||||
|
||||
private:
|
||||
Result GetAlbumFileList(Out<u64> out_count, AlbumStorage storage,
|
||||
OutArray<AlbumEntry, BufferAttr_HipcMapAlias> out_entries);
|
||||
|
||||
Result DeleteAlbumFile(AlbumFileId file_id);
|
||||
|
||||
Result IsAlbumMounted(Out<bool> out_is_mounted, AlbumStorage storage);
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/erpt/erpt.h"
|
||||
#include "core/hle/service/server_manager.h"
|
||||
#include "core/hle/service/service.h"
|
||||
@ -15,7 +17,7 @@ public:
|
||||
explicit ErrorReportContext(Core::System& system_) : ServiceFramework{system_, "erpt:c"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "SubmitContext"},
|
||||
{0, C<&ErrorReportContext::SubmitContext>, "SubmitContext"},
|
||||
{1, nullptr, "CreateReportV0"},
|
||||
{2, nullptr, "SetInitialLaunchSettingsCompletionTime"},
|
||||
{3, nullptr, "ClearInitialLaunchSettingsCompletionTime"},
|
||||
@ -36,6 +38,14 @@ public:
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
private:
|
||||
Result SubmitContext(InBuffer<BufferAttr_HipcMapAlias> buffer_a,
|
||||
InBuffer<BufferAttr_HipcMapAlias> buffer_b) {
|
||||
LOG_WARNING(Service_SET, "(STUBBED) called, buffer_a_size={}, buffer_b_size={}",
|
||||
buffer_a.size(), buffer_b.size());
|
||||
R_SUCCEED();
|
||||
}
|
||||
};
|
||||
|
||||
class ErrorReportSession final : public ServiceFramework<ErrorReportSession> {
|
||||
|
@ -186,6 +186,10 @@ TimeManager::TimeManager(Core::System& system)
|
||||
}
|
||||
}
|
||||
|
||||
TimeManager::~TimeManager() {
|
||||
ResetTimeZoneBinary();
|
||||
}
|
||||
|
||||
Result TimeManager::SetupStandardSteadyClockCore() {
|
||||
Common::UUID external_clock_source_id{};
|
||||
auto res = m_set_sys->GetExternalSteadyClockSourceId(&external_clock_source_id);
|
||||
|
@ -26,6 +26,7 @@ namespace Service::Glue::Time {
|
||||
class TimeManager {
|
||||
public:
|
||||
explicit TimeManager(Core::System& system);
|
||||
~TimeManager();
|
||||
|
||||
std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
|
||||
|
||||
|
21
src/core/hle/service/ns/account_proxy_interface.cpp
Executable file
21
src/core/hle/service/ns/account_proxy_interface.cpp
Executable file
@ -0,0 +1,21 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/ns/account_proxy_interface.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
IAccountProxyInterface::IAccountProxyInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "IAccountProxyInterface"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "CreateUserAccount"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IAccountProxyInterface::~IAccountProxyInterface() = default;
|
||||
|
||||
} // namespace Service::NS
|
16
src/core/hle/service/ns/account_proxy_interface.h
Executable file
16
src/core/hle/service/ns/account_proxy_interface.h
Executable file
@ -0,0 +1,16 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
class IAccountProxyInterface final : public ServiceFramework<IAccountProxyInterface> {
|
||||
public:
|
||||
explicit IAccountProxyInterface(Core::System& system_);
|
||||
~IAccountProxyInterface() override;
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
518
src/core/hle/service/ns/application_manager_interface.cpp
Executable file
518
src/core/hle/service/ns/application_manager_interface.cpp
Executable file
@ -0,0 +1,518 @@
|
||||
// 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/cmif_serialization.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/hle/service/ns/application_manager_interface.h"
|
||||
#include "core/hle/service/ns/content_management_interface.h"
|
||||
#include "core/hle/service/ns/read_only_application_control_data_interface.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "IApplicationManagerInterface"},
|
||||
service_context{system, "IApplicationManagerInterface"},
|
||||
record_update_system_event{service_context}, sd_card_mount_status_event{service_context},
|
||||
gamecard_update_detection_event{service_context},
|
||||
gamecard_mount_status_event{service_context}, gamecard_mount_failure_event{service_context} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IApplicationManagerInterface::ListApplicationRecord>, "ListApplicationRecord"},
|
||||
{1, nullptr, "GenerateApplicationRecordCount"},
|
||||
{2, D<&IApplicationManagerInterface::GetApplicationRecordUpdateSystemEvent>, "GetApplicationRecordUpdateSystemEvent"},
|
||||
{3, nullptr, "GetApplicationViewDeprecated"},
|
||||
{4, nullptr, "DeleteApplicationEntity"},
|
||||
{5, nullptr, "DeleteApplicationCompletely"},
|
||||
{6, nullptr, "IsAnyApplicationEntityRedundant"},
|
||||
{7, nullptr, "DeleteRedundantApplicationEntity"},
|
||||
{8, nullptr, "IsApplicationEntityMovable"},
|
||||
{9, nullptr, "MoveApplicationEntity"},
|
||||
{11, nullptr, "CalculateApplicationOccupiedSize"},
|
||||
{16, nullptr, "PushApplicationRecord"},
|
||||
{17, nullptr, "ListApplicationRecordContentMeta"},
|
||||
{19, nullptr, "LaunchApplicationOld"},
|
||||
{21, nullptr, "GetApplicationContentPath"},
|
||||
{22, nullptr, "TerminateApplication"},
|
||||
{23, nullptr, "ResolveApplicationContentPath"},
|
||||
{26, nullptr, "BeginInstallApplication"},
|
||||
{27, nullptr, "DeleteApplicationRecord"},
|
||||
{30, nullptr, "RequestApplicationUpdateInfo"},
|
||||
{31, nullptr, "Unknown31"},
|
||||
{32, nullptr, "CancelApplicationDownload"},
|
||||
{33, nullptr, "ResumeApplicationDownload"},
|
||||
{35, nullptr, "UpdateVersionList"},
|
||||
{36, nullptr, "PushLaunchVersion"},
|
||||
{37, nullptr, "ListRequiredVersion"},
|
||||
{38, D<&IApplicationManagerInterface::CheckApplicationLaunchVersion>, "CheckApplicationLaunchVersion"},
|
||||
{39, nullptr, "CheckApplicationLaunchRights"},
|
||||
{40, nullptr, "GetApplicationLogoData"},
|
||||
{41, nullptr, "CalculateApplicationDownloadRequiredSize"},
|
||||
{42, nullptr, "CleanupSdCard"},
|
||||
{43, D<&IApplicationManagerInterface::CheckSdCardMountStatus>, "CheckSdCardMountStatus"},
|
||||
{44, D<&IApplicationManagerInterface::GetSdCardMountStatusChangedEvent>, "GetSdCardMountStatusChangedEvent"},
|
||||
{45, nullptr, "GetGameCardAttachmentEvent"},
|
||||
{46, nullptr, "GetGameCardAttachmentInfo"},
|
||||
{47, nullptr, "GetTotalSpaceSize"},
|
||||
{48, D<&IApplicationManagerInterface::GetFreeSpaceSize>, "GetFreeSpaceSize"},
|
||||
{49, nullptr, "GetSdCardRemovedEvent"},
|
||||
{52, D<&IApplicationManagerInterface::GetGameCardUpdateDetectionEvent>, "GetGameCardUpdateDetectionEvent"},
|
||||
{53, nullptr, "DisableApplicationAutoDelete"},
|
||||
{54, nullptr, "EnableApplicationAutoDelete"},
|
||||
{55, D<&IApplicationManagerInterface::GetApplicationDesiredLanguage>, "GetApplicationDesiredLanguage"},
|
||||
{56, nullptr, "SetApplicationTerminateResult"},
|
||||
{57, nullptr, "ClearApplicationTerminateResult"},
|
||||
{58, nullptr, "GetLastSdCardMountUnexpectedResult"},
|
||||
{59, D<&IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode>, "ConvertApplicationLanguageToLanguageCode"},
|
||||
{60, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
|
||||
{61, nullptr, "GetBackgroundDownloadStressTaskInfo"},
|
||||
{62, nullptr, "GetGameCardStopper"},
|
||||
{63, nullptr, "IsSystemProgramInstalled"},
|
||||
{64, nullptr, "StartApplyDeltaTask"},
|
||||
{65, nullptr, "GetRequestServerStopper"},
|
||||
{66, nullptr, "GetBackgroundApplyDeltaStressTaskInfo"},
|
||||
{67, nullptr, "CancelApplicationApplyDelta"},
|
||||
{68, nullptr, "ResumeApplicationApplyDelta"},
|
||||
{69, nullptr, "CalculateApplicationApplyDeltaRequiredSize"},
|
||||
{70, D<&IApplicationManagerInterface::ResumeAll>, "ResumeAll"},
|
||||
{71, D<&IApplicationManagerInterface::GetStorageSize>, "GetStorageSize"},
|
||||
{80, nullptr, "RequestDownloadApplication"},
|
||||
{81, nullptr, "RequestDownloadAddOnContent"},
|
||||
{82, nullptr, "DownloadApplication"},
|
||||
{83, nullptr, "CheckApplicationResumeRights"},
|
||||
{84, nullptr, "GetDynamicCommitEvent"},
|
||||
{85, nullptr, "RequestUpdateApplication2"},
|
||||
{86, nullptr, "EnableApplicationCrashReport"},
|
||||
{87, nullptr, "IsApplicationCrashReportEnabled"},
|
||||
{90, nullptr, "BoostSystemMemoryResourceLimit"},
|
||||
{91, nullptr, "DeprecatedLaunchApplication"},
|
||||
{92, nullptr, "GetRunningApplicationProgramId"},
|
||||
{93, nullptr, "GetMainApplicationProgramIndex"},
|
||||
{94, nullptr, "LaunchApplication"},
|
||||
{95, nullptr, "GetApplicationLaunchInfo"},
|
||||
{96, nullptr, "AcquireApplicationLaunchInfo"},
|
||||
{97, nullptr, "GetMainApplicationProgramIndexByApplicationLaunchInfo"},
|
||||
{98, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
|
||||
{99, nullptr, "LaunchDevMenu"},
|
||||
{100, nullptr, "ResetToFactorySettings"},
|
||||
{101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"},
|
||||
{102, nullptr, "ResetToFactorySettingsForRefurbishment"},
|
||||
{103, nullptr, "ResetToFactorySettingsWithPlatformRegion"},
|
||||
{104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"},
|
||||
{105, nullptr, "RequestResetToFactorySettingsSecurely"},
|
||||
{106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"},
|
||||
{200, nullptr, "CalculateUserSaveDataStatistics"},
|
||||
{201, nullptr, "DeleteUserSaveDataAll"},
|
||||
{210, nullptr, "DeleteUserSystemSaveData"},
|
||||
{211, nullptr, "DeleteSaveData"},
|
||||
{220, nullptr, "UnregisterNetworkServiceAccount"},
|
||||
{221, nullptr, "UnregisterNetworkServiceAccountWithUserSaveDataDeletion"},
|
||||
{300, nullptr, "GetApplicationShellEvent"},
|
||||
{301, nullptr, "PopApplicationShellEventInfo"},
|
||||
{302, nullptr, "LaunchLibraryApplet"},
|
||||
{303, nullptr, "TerminateLibraryApplet"},
|
||||
{304, nullptr, "LaunchSystemApplet"},
|
||||
{305, nullptr, "TerminateSystemApplet"},
|
||||
{306, nullptr, "LaunchOverlayApplet"},
|
||||
{307, nullptr, "TerminateOverlayApplet"},
|
||||
{400, D<&IApplicationManagerInterface::GetApplicationControlData>, "GetApplicationControlData"},
|
||||
{401, nullptr, "InvalidateAllApplicationControlCache"},
|
||||
{402, nullptr, "RequestDownloadApplicationControlData"},
|
||||
{403, nullptr, "GetMaxApplicationControlCacheCount"},
|
||||
{404, nullptr, "InvalidateApplicationControlCache"},
|
||||
{405, nullptr, "ListApplicationControlCacheEntryInfo"},
|
||||
{406, nullptr, "GetApplicationControlProperty"},
|
||||
{407, nullptr, "ListApplicationTitle"},
|
||||
{408, nullptr, "ListApplicationIcon"},
|
||||
{502, nullptr, "RequestCheckGameCardRegistration"},
|
||||
{503, nullptr, "RequestGameCardRegistrationGoldPoint"},
|
||||
{504, nullptr, "RequestRegisterGameCard"},
|
||||
{505, D<&IApplicationManagerInterface::GetGameCardMountFailureEvent>, "GetGameCardMountFailureEvent"},
|
||||
{506, nullptr, "IsGameCardInserted"},
|
||||
{507, nullptr, "EnsureGameCardAccess"},
|
||||
{508, nullptr, "GetLastGameCardMountFailureResult"},
|
||||
{509, nullptr, "ListApplicationIdOnGameCard"},
|
||||
{510, nullptr, "GetGameCardPlatformRegion"},
|
||||
{600, nullptr, "CountApplicationContentMeta"},
|
||||
{601, nullptr, "ListApplicationContentMetaStatus"},
|
||||
{602, nullptr, "ListAvailableAddOnContent"},
|
||||
{603, nullptr, "GetOwnedApplicationContentMetaStatus"},
|
||||
{604, nullptr, "RegisterContentsExternalKey"},
|
||||
{605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
|
||||
{606, nullptr, "GetContentMetaStorage"},
|
||||
{607, nullptr, "ListAvailableAddOnContent"},
|
||||
{609, nullptr, "ListAvailabilityAssuredAddOnContent"},
|
||||
{610, nullptr, "GetInstalledContentMetaStorage"},
|
||||
{611, nullptr, "PrepareAddOnContent"},
|
||||
{700, nullptr, "PushDownloadTaskList"},
|
||||
{701, nullptr, "ClearTaskStatusList"},
|
||||
{702, nullptr, "RequestDownloadTaskList"},
|
||||
{703, nullptr, "RequestEnsureDownloadTask"},
|
||||
{704, nullptr, "ListDownloadTaskStatus"},
|
||||
{705, nullptr, "RequestDownloadTaskListData"},
|
||||
{800, nullptr, "RequestVersionList"},
|
||||
{801, nullptr, "ListVersionList"},
|
||||
{802, nullptr, "RequestVersionListData"},
|
||||
{900, nullptr, "GetApplicationRecord"},
|
||||
{901, nullptr, "GetApplicationRecordProperty"},
|
||||
{902, nullptr, "EnableApplicationAutoUpdate"},
|
||||
{903, nullptr, "DisableApplicationAutoUpdate"},
|
||||
{904, nullptr, "TouchApplication"},
|
||||
{905, nullptr, "RequestApplicationUpdate"},
|
||||
{906, D<&IApplicationManagerInterface::IsApplicationUpdateRequested>, "IsApplicationUpdateRequested"},
|
||||
{907, nullptr, "WithdrawApplicationUpdateRequest"},
|
||||
{908, nullptr, "ListApplicationRecordInstalledContentMeta"},
|
||||
{909, nullptr, "WithdrawCleanupAddOnContentsWithNoRightsRecommendation"},
|
||||
{910, nullptr, "HasApplicationRecord"},
|
||||
{911, nullptr, "SetPreInstalledApplication"},
|
||||
{912, nullptr, "ClearPreInstalledApplicationFlag"},
|
||||
{913, nullptr, "ListAllApplicationRecord"},
|
||||
{914, nullptr, "HideApplicationRecord"},
|
||||
{915, nullptr, "ShowApplicationRecord"},
|
||||
{916, nullptr, "IsApplicationAutoDeleteDisabled"},
|
||||
{1000, nullptr, "RequestVerifyApplicationDeprecated"},
|
||||
{1001, nullptr, "CorruptApplicationForDebug"},
|
||||
{1002, nullptr, "RequestVerifyAddOnContentsRights"},
|
||||
{1003, nullptr, "RequestVerifyApplication"},
|
||||
{1004, nullptr, "CorruptContentForDebug"},
|
||||
{1200, nullptr, "NeedsUpdateVulnerability"},
|
||||
{1300, D<&IApplicationManagerInterface::IsAnyApplicationEntityInstalled>, "IsAnyApplicationEntityInstalled"},
|
||||
{1301, nullptr, "DeleteApplicationContentEntities"},
|
||||
{1302, nullptr, "CleanupUnrecordedApplicationEntity"},
|
||||
{1303, nullptr, "CleanupAddOnContentsWithNoRights"},
|
||||
{1304, nullptr, "DeleteApplicationContentEntity"},
|
||||
{1305, nullptr, "TryDeleteRunningApplicationEntity"},
|
||||
{1306, nullptr, "TryDeleteRunningApplicationCompletely"},
|
||||
{1307, nullptr, "TryDeleteRunningApplicationContentEntities"},
|
||||
{1308, nullptr, "DeleteApplicationCompletelyForDebug"},
|
||||
{1309, nullptr, "CleanupUnavailableAddOnContents"},
|
||||
{1310, nullptr, "RequestMoveApplicationEntity"},
|
||||
{1311, nullptr, "EstimateSizeToMove"},
|
||||
{1312, nullptr, "HasMovableEntity"},
|
||||
{1313, nullptr, "CleanupOrphanContents"},
|
||||
{1314, nullptr, "CheckPreconditionSatisfiedToMove"},
|
||||
{1400, nullptr, "PrepareShutdown"},
|
||||
{1500, nullptr, "FormatSdCard"},
|
||||
{1501, nullptr, "NeedsSystemUpdateToFormatSdCard"},
|
||||
{1502, nullptr, "GetLastSdCardFormatUnexpectedResult"},
|
||||
{1504, nullptr, "InsertSdCard"},
|
||||
{1505, nullptr, "RemoveSdCard"},
|
||||
{1506, nullptr, "GetSdCardStartupStatus"},
|
||||
{1600, nullptr, "GetSystemSeedForPseudoDeviceId"},
|
||||
{1601, nullptr, "ResetSystemSeedForPseudoDeviceId"},
|
||||
{1700, nullptr, "ListApplicationDownloadingContentMeta"},
|
||||
{1701, D<&IApplicationManagerInterface::GetApplicationView>, "GetApplicationView"},
|
||||
{1702, nullptr, "GetApplicationDownloadTaskStatus"},
|
||||
{1703, nullptr, "GetApplicationViewDownloadErrorContext"},
|
||||
{1704, D<&IApplicationManagerInterface::GetApplicationViewWithPromotionInfo>, "GetApplicationViewWithPromotionInfo"},
|
||||
{1705, nullptr, "IsPatchAutoDeletableApplication"},
|
||||
{1800, nullptr, "IsNotificationSetupCompleted"},
|
||||
{1801, nullptr, "GetLastNotificationInfoCount"},
|
||||
{1802, nullptr, "ListLastNotificationInfo"},
|
||||
{1803, nullptr, "ListNotificationTask"},
|
||||
{1900, nullptr, "IsActiveAccount"},
|
||||
{1901, nullptr, "RequestDownloadApplicationPrepurchasedRights"},
|
||||
{1902, nullptr, "GetApplicationTicketInfo"},
|
||||
{1903, nullptr, "RequestDownloadApplicationPrepurchasedRightsForAccount"},
|
||||
{2000, nullptr, "GetSystemDeliveryInfo"},
|
||||
{2001, nullptr, "SelectLatestSystemDeliveryInfo"},
|
||||
{2002, nullptr, "VerifyDeliveryProtocolVersion"},
|
||||
{2003, nullptr, "GetApplicationDeliveryInfo"},
|
||||
{2004, nullptr, "HasAllContentsToDeliver"},
|
||||
{2005, nullptr, "CompareApplicationDeliveryInfo"},
|
||||
{2006, nullptr, "CanDeliverApplication"},
|
||||
{2007, nullptr, "ListContentMetaKeyToDeliverApplication"},
|
||||
{2008, nullptr, "NeedsSystemUpdateToDeliverApplication"},
|
||||
{2009, nullptr, "EstimateRequiredSize"},
|
||||
{2010, nullptr, "RequestReceiveApplication"},
|
||||
{2011, nullptr, "CommitReceiveApplication"},
|
||||
{2012, nullptr, "GetReceiveApplicationProgress"},
|
||||
{2013, nullptr, "RequestSendApplication"},
|
||||
{2014, nullptr, "GetSendApplicationProgress"},
|
||||
{2015, nullptr, "CompareSystemDeliveryInfo"},
|
||||
{2016, nullptr, "ListNotCommittedContentMeta"},
|
||||
{2017, nullptr, "CreateDownloadTask"},
|
||||
{2018, nullptr, "GetApplicationDeliveryInfoHash"},
|
||||
{2050, D<&IApplicationManagerInterface::GetApplicationRightsOnClient>, "GetApplicationRightsOnClient"},
|
||||
{2051, nullptr, "InvalidateRightsIdCache"},
|
||||
{2100, D<&IApplicationManagerInterface::GetApplicationTerminateResult>, "GetApplicationTerminateResult"},
|
||||
{2101, nullptr, "GetRawApplicationTerminateResult"},
|
||||
{2150, nullptr, "CreateRightsEnvironment"},
|
||||
{2151, nullptr, "DestroyRightsEnvironment"},
|
||||
{2152, nullptr, "ActivateRightsEnvironment"},
|
||||
{2153, nullptr, "DeactivateRightsEnvironment"},
|
||||
{2154, nullptr, "ForceActivateRightsContextForExit"},
|
||||
{2155, nullptr, "UpdateRightsEnvironmentStatus"},
|
||||
{2156, nullptr, "CreateRightsEnvironmentForMicroApplication"},
|
||||
{2160, nullptr, "AddTargetApplicationToRightsEnvironment"},
|
||||
{2161, nullptr, "SetUsersToRightsEnvironment"},
|
||||
{2170, nullptr, "GetRightsEnvironmentStatus"},
|
||||
{2171, nullptr, "GetRightsEnvironmentStatusChangedEvent"},
|
||||
{2180, nullptr, "RequestExtendRightsInRightsEnvironment"},
|
||||
{2181, nullptr, "GetResultOfExtendRightsInRightsEnvironment"},
|
||||
{2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"},
|
||||
{2190, nullptr, "GetRightsEnvironmentHandleForApplication"},
|
||||
{2199, nullptr, "GetRightsEnvironmentCountForDebug"},
|
||||
{2200, nullptr, "GetGameCardApplicationCopyIdentifier"},
|
||||
{2201, nullptr, "GetInstalledApplicationCopyIdentifier"},
|
||||
{2250, nullptr, "RequestReportActiveELicence"},
|
||||
{2300, nullptr, "ListEventLog"},
|
||||
{2350, nullptr, "PerformAutoUpdateByApplicationId"},
|
||||
{2351, nullptr, "RequestNoDownloadRightsErrorResolution"},
|
||||
{2352, nullptr, "RequestResolveNoDownloadRightsError"},
|
||||
{2353, nullptr, "GetApplicationDownloadTaskInfo"},
|
||||
{2354, nullptr, "PrioritizeApplicationBackgroundTask"},
|
||||
{2355, nullptr, "PreferStorageEfficientUpdate"},
|
||||
{2356, nullptr, "RequestStorageEfficientUpdatePreferable"},
|
||||
{2357, nullptr, "EnableMultiCoreDownload"},
|
||||
{2358, nullptr, "DisableMultiCoreDownload"},
|
||||
{2359, nullptr, "IsMultiCoreDownloadEnabled"},
|
||||
{2400, nullptr, "GetPromotionInfo"},
|
||||
{2401, nullptr, "CountPromotionInfo"},
|
||||
{2402, nullptr, "ListPromotionInfo"},
|
||||
{2403, nullptr, "ImportPromotionJsonForDebug"},
|
||||
{2404, nullptr, "ClearPromotionInfoForDebug"},
|
||||
{2500, nullptr, "ConfirmAvailableTime"},
|
||||
{2510, nullptr, "CreateApplicationResource"},
|
||||
{2511, nullptr, "GetApplicationResource"},
|
||||
{2513, nullptr, "LaunchMicroApplication"},
|
||||
{2514, nullptr, "ClearTaskOfAsyncTaskManager"},
|
||||
{2515, nullptr, "CleanupAllPlaceHolderAndFragmentsIfNoTask"},
|
||||
{2516, nullptr, "EnsureApplicationCertificate"},
|
||||
{2517, nullptr, "CreateApplicationInstance"},
|
||||
{2518, nullptr, "UpdateQualificationForDebug"},
|
||||
{2519, nullptr, "IsQualificationTransitionSupported"},
|
||||
{2520, nullptr, "IsQualificationTransitionSupportedByProcessId"},
|
||||
{2521, nullptr, "GetRightsUserChangedEvent"},
|
||||
{2522, nullptr, "IsRomRedirectionAvailable"},
|
||||
{2800, nullptr, "GetApplicationIdOfPreomia"},
|
||||
{3000, nullptr, "RegisterDeviceLockKey"},
|
||||
{3001, nullptr, "UnregisterDeviceLockKey"},
|
||||
{3002, nullptr, "VerifyDeviceLockKey"},
|
||||
{3003, nullptr, "HideApplicationIcon"},
|
||||
{3004, nullptr, "ShowApplicationIcon"},
|
||||
{3005, nullptr, "HideApplicationTitle"},
|
||||
{3006, nullptr, "ShowApplicationTitle"},
|
||||
{3007, nullptr, "EnableGameCard"},
|
||||
{3008, nullptr, "DisableGameCard"},
|
||||
{3009, nullptr, "EnableLocalContentShare"},
|
||||
{3010, nullptr, "DisableLocalContentShare"},
|
||||
{3011, nullptr, "IsApplicationIconHidden"},
|
||||
{3012, nullptr, "IsApplicationTitleHidden"},
|
||||
{3013, nullptr, "IsGameCardEnabled"},
|
||||
{3014, nullptr, "IsLocalContentShareEnabled"},
|
||||
{3050, nullptr, "ListAssignELicenseTaskResult"},
|
||||
{9999, nullptr, "GetApplicationCertificate"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IApplicationManagerInterface::~IApplicationManagerInterface() = default;
|
||||
|
||||
Result IApplicationManagerInterface::GetApplicationControlData(
|
||||
OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size,
|
||||
ApplicationControlSource application_control_source, u64 application_id) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
R_RETURN(IReadOnlyApplicationControlDataInterface(system).GetApplicationControlData(
|
||||
out_buffer, out_actual_size, application_control_source, application_id));
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::GetApplicationDesiredLanguage(
|
||||
Out<ApplicationLanguage> out_desired_language, u32 supported_languages) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
R_RETURN(IReadOnlyApplicationControlDataInterface(system).GetApplicationDesiredLanguage(
|
||||
out_desired_language, supported_languages));
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
|
||||
Out<u64> out_language_code, ApplicationLanguage application_language) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
R_RETURN(
|
||||
IReadOnlyApplicationControlDataInterface(system).ConvertApplicationLanguageToLanguageCode(
|
||||
out_language_code, application_language));
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::ListApplicationRecord(
|
||||
OutArray<ApplicationRecord, BufferAttr_HipcMapAlias> out_records, Out<s32> out_count,
|
||||
s32 offset) {
|
||||
const auto limit = out_records.size();
|
||||
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called");
|
||||
const auto& cache = system.GetContentProviderUnion();
|
||||
const auto installed_games = cache.ListEntriesFilterOrigin(
|
||||
std::nullopt, FileSys::TitleType::Application, FileSys::ContentRecordType::Program);
|
||||
|
||||
size_t i = 0;
|
||||
u8 ii = 24;
|
||||
|
||||
for (const auto& [slot, game] : installed_games) {
|
||||
if (i >= limit) {
|
||||
break;
|
||||
}
|
||||
if (game.title_id == 0 || game.title_id < 0x0100000000001FFFull) {
|
||||
continue;
|
||||
}
|
||||
if (offset > 0) {
|
||||
offset--;
|
||||
continue;
|
||||
}
|
||||
|
||||
ApplicationRecord record{};
|
||||
record.application_id = game.title_id;
|
||||
record.type = ApplicationRecordType::Installed;
|
||||
record.unknown = 0; // 2 = needs update
|
||||
record.unknown2 = ii++;
|
||||
|
||||
out_records[i++] = record;
|
||||
}
|
||||
|
||||
*out_count = static_cast<s32>(i);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::GetApplicationRecordUpdateSystemEvent(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called");
|
||||
|
||||
record_update_system_event.Signal();
|
||||
*out_event = record_update_system_event.GetHandle();
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::GetGameCardMountFailureEvent(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called");
|
||||
*out_event = gamecard_mount_failure_event.GetHandle();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::IsAnyApplicationEntityInstalled(
|
||||
Out<bool> out_is_any_application_entity_installed) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called");
|
||||
*out_is_any_application_entity_installed = true;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::GetApplicationView(
|
||||
OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views,
|
||||
InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
|
||||
const auto size = std::min(out_application_views.size(), application_ids.size());
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called, size={}", application_ids.size());
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
ApplicationView view{};
|
||||
view.application_id = application_ids[i];
|
||||
view.unk = 0x70000;
|
||||
view.flags = 0x401f17;
|
||||
|
||||
out_application_views[i] = view;
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::GetApplicationViewWithPromotionInfo(
|
||||
OutArray<ApplicationViewWithPromotionInfo, BufferAttr_HipcMapAlias> out_application_views,
|
||||
InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
|
||||
const auto size = std::min(out_application_views.size(), application_ids.size());
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called, size={}", application_ids.size());
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
ApplicationViewWithPromotionInfo view{};
|
||||
view.view.application_id = application_ids[i];
|
||||
view.view.unk = 0x70000;
|
||||
view.view.flags = 0x401f17;
|
||||
view.promotion = {};
|
||||
|
||||
out_application_views[i] = view;
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::GetApplicationRightsOnClient(
|
||||
OutArray<ApplicationRightsOnClient, BufferAttr_HipcMapAlias> out_rights, Out<u32> out_count,
|
||||
Common::UUID account_id, u32 flags, u64 application_id) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called, flags={}, application_id={:016X}, account_id={}",
|
||||
flags, application_id, account_id.FormattedString());
|
||||
|
||||
if (!out_rights.empty()) {
|
||||
out_rights[0] = {
|
||||
.application_id = application_id,
|
||||
.uid = account_id,
|
||||
.flags = 0,
|
||||
.flags2 = 0,
|
||||
};
|
||||
*out_count = 1;
|
||||
} else {
|
||||
*out_count = 0;
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::CheckSdCardMountStatus() {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
R_RETURN(IContentManagementInterface(system).CheckSdCardMountStatus());
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::GetSdCardMountStatusChangedEvent(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called");
|
||||
*out_event = sd_card_mount_status_event.GetHandle();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::GetFreeSpaceSize(Out<s64> out_free_space_size,
|
||||
FileSys::StorageId storage_id) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
R_RETURN(IContentManagementInterface(system).GetFreeSpaceSize(out_free_space_size, storage_id));
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::GetGameCardUpdateDetectionEvent(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called");
|
||||
*out_event = gamecard_update_detection_event.GetHandle();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::ResumeAll() {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called");
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::GetStorageSize(Out<s64> out_total_space_size,
|
||||
Out<s64> out_free_space_size,
|
||||
FileSys::StorageId storage_id) {
|
||||
LOG_INFO(Service_NS, "called, storage_id={}", storage_id);
|
||||
*out_total_space_size = system.GetFileSystemController().GetTotalSpaceSize(storage_id);
|
||||
*out_free_space_size = system.GetFileSystemController().GetFreeSpaceSize(storage_id);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::IsApplicationUpdateRequested(Out<bool> out_update_required,
|
||||
Out<u32> out_update_version,
|
||||
u64 application_id) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called. application_id={:016X}", application_id);
|
||||
*out_update_required = false;
|
||||
*out_update_version = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::CheckApplicationLaunchVersion(u64 application_id) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called. application_id={:016X}", application_id);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::GetApplicationTerminateResult(Out<Result> out_result,
|
||||
u64 application_id) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called. application_id={:016X}", application_id);
|
||||
*out_result = ResultSuccess;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::NS
|
62
src/core/hle/service/ns/application_manager_interface.h
Executable file
62
src/core/hle/service/ns/application_manager_interface.h
Executable file
@ -0,0 +1,62 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ns/language.h"
|
||||
#include "core/hle/service/ns/ns_types.h"
|
||||
#include "core/hle/service/os/event.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> {
|
||||
public:
|
||||
explicit IApplicationManagerInterface(Core::System& system_);
|
||||
~IApplicationManagerInterface() override;
|
||||
|
||||
Result GetApplicationControlData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
|
||||
Out<u32> out_actual_size,
|
||||
ApplicationControlSource application_control_source,
|
||||
u64 application_id);
|
||||
Result GetApplicationDesiredLanguage(Out<ApplicationLanguage> out_desired_language,
|
||||
u32 supported_languages);
|
||||
Result ConvertApplicationLanguageToLanguageCode(Out<u64> out_language_code,
|
||||
ApplicationLanguage application_language);
|
||||
Result ListApplicationRecord(OutArray<ApplicationRecord, BufferAttr_HipcMapAlias> out_records,
|
||||
Out<s32> out_count, s32 offset);
|
||||
Result GetApplicationRecordUpdateSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result GetGameCardMountFailureEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result IsAnyApplicationEntityInstalled(Out<bool> out_is_any_application_entity_installed);
|
||||
Result GetApplicationView(
|
||||
OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views,
|
||||
InArray<u64, BufferAttr_HipcMapAlias> application_ids);
|
||||
Result GetApplicationViewWithPromotionInfo(
|
||||
OutArray<ApplicationViewWithPromotionInfo, BufferAttr_HipcMapAlias> out_application_views,
|
||||
InArray<u64, BufferAttr_HipcMapAlias> application_ids);
|
||||
Result GetApplicationRightsOnClient(
|
||||
OutArray<ApplicationRightsOnClient, BufferAttr_HipcMapAlias> out_rights, Out<u32> out_count,
|
||||
Common::UUID account_id, u32 flags, u64 application_id);
|
||||
Result CheckSdCardMountStatus();
|
||||
Result GetSdCardMountStatusChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result GetFreeSpaceSize(Out<s64> out_free_space_size, FileSys::StorageId storage_id);
|
||||
Result GetGameCardUpdateDetectionEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result ResumeAll();
|
||||
Result GetStorageSize(Out<s64> out_total_space_size, Out<s64> out_free_space_size,
|
||||
FileSys::StorageId storage_id);
|
||||
Result IsApplicationUpdateRequested(Out<bool> out_update_required, Out<u32> out_update_version,
|
||||
u64 application_id);
|
||||
Result CheckApplicationLaunchVersion(u64 application_id);
|
||||
Result GetApplicationTerminateResult(Out<Result> out_result, u64 application_id);
|
||||
|
||||
private:
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
Event record_update_system_event;
|
||||
Event sd_card_mount_status_event;
|
||||
Event gamecard_update_detection_event;
|
||||
Event gamecard_mount_status_event;
|
||||
Event gamecard_mount_failure_event;
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
33
src/core/hle/service/ns/application_version_interface.cpp
Executable file
33
src/core/hle/service/ns/application_version_interface.cpp
Executable file
@ -0,0 +1,33 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/ns/application_version_interface.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "IApplicationVersionInterface"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetLaunchRequiredVersion"},
|
||||
{1, nullptr, "UpgradeLaunchRequiredVersion"},
|
||||
{35, nullptr, "UpdateVersionList"},
|
||||
{36, nullptr, "PushLaunchVersion"},
|
||||
{37, nullptr, "ListRequiredVersion"},
|
||||
{800, nullptr, "RequestVersionList"},
|
||||
{801, nullptr, "ListVersionList"},
|
||||
{802, nullptr, "RequestVersionListData"},
|
||||
{900, nullptr, "ImportAutoUpdatePolicyJsonForDebug"},
|
||||
{901, nullptr, "ListDefaultAutoUpdatePolicy"},
|
||||
{902, nullptr, "ListAutoUpdatePolicyForSpecificApplication"},
|
||||
{1000, nullptr, "PerformAutoUpdate"},
|
||||
{1001, nullptr, "ListAutoUpdateSchedule"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IApplicationVersionInterface::~IApplicationVersionInterface() = default;
|
||||
|
||||
} // namespace Service::NS
|
16
src/core/hle/service/ns/application_version_interface.h
Executable file
16
src/core/hle/service/ns/application_version_interface.h
Executable file
@ -0,0 +1,16 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> {
|
||||
public:
|
||||
explicit IApplicationVersionInterface(Core::System& system_);
|
||||
~IApplicationVersionInterface() override;
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
72
src/core/hle/service/ns/content_management_interface.cpp
Executable file
72
src/core/hle/service/ns/content_management_interface.cpp
Executable file
@ -0,0 +1,72 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/common_funcs.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/hle/service/ns/content_management_interface.h"
|
||||
#include "core/hle/service/ns/ns_types.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
IContentManagementInterface::IContentManagementInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "IContentManagementInterface"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{11, D<&IContentManagementInterface::CalculateApplicationOccupiedSize>, "CalculateApplicationOccupiedSize"},
|
||||
{43, D<&IContentManagementInterface::CheckSdCardMountStatus>, "CheckSdCardMountStatus"},
|
||||
{47, D<&IContentManagementInterface::GetTotalSpaceSize>, "GetTotalSpaceSize"},
|
||||
{48, D<&IContentManagementInterface::GetFreeSpaceSize>, "GetFreeSpaceSize"},
|
||||
{600, nullptr, "CountApplicationContentMeta"},
|
||||
{601, nullptr, "ListApplicationContentMetaStatus"},
|
||||
{605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
|
||||
{607, nullptr, "IsAnyApplicationRunning"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IContentManagementInterface::~IContentManagementInterface() = default;
|
||||
|
||||
Result IContentManagementInterface::CalculateApplicationOccupiedSize(
|
||||
Out<ApplicationOccupiedSize> out_size, u64 application_id) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called, application_id={:016X}", application_id);
|
||||
|
||||
using namespace Common::Literals;
|
||||
|
||||
constexpr ApplicationOccupiedSizeEntity stub_entity{
|
||||
.storage_id = FileSys::StorageId::SdCard,
|
||||
.app_size = 8_GiB,
|
||||
.patch_size = 2_GiB,
|
||||
.aoc_size = 12_MiB,
|
||||
};
|
||||
|
||||
for (auto& entity : out_size->entities) {
|
||||
entity = stub_entity;
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IContentManagementInterface::CheckSdCardMountStatus() {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called");
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IContentManagementInterface::GetTotalSpaceSize(Out<s64> out_total_space_size,
|
||||
FileSys::StorageId storage_id) {
|
||||
LOG_INFO(Service_NS, "(STUBBED) called, storage_id={}", storage_id);
|
||||
*out_total_space_size = system.GetFileSystemController().GetTotalSpaceSize(storage_id);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IContentManagementInterface::GetFreeSpaceSize(Out<s64> out_free_space_size,
|
||||
FileSys::StorageId storage_id) {
|
||||
LOG_INFO(Service_NS, "(STUBBED) called, storage_id={}", storage_id);
|
||||
*out_free_space_size = system.GetFileSystemController().GetFreeSpaceSize(storage_id);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::NS
|
25
src/core/hle/service/ns/content_management_interface.h
Executable file
25
src/core/hle/service/ns/content_management_interface.h
Executable file
@ -0,0 +1,25 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ns/ns_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
class IContentManagementInterface final : public ServiceFramework<IContentManagementInterface> {
|
||||
public:
|
||||
explicit IContentManagementInterface(Core::System& system_);
|
||||
~IContentManagementInterface() override;
|
||||
|
||||
public:
|
||||
Result CalculateApplicationOccupiedSize(Out<ApplicationOccupiedSize> out_size,
|
||||
u64 application_id);
|
||||
Result CheckSdCardMountStatus();
|
||||
Result GetTotalSpaceSize(Out<s64> out_total_space_size, FileSys::StorageId storage_id);
|
||||
Result GetFreeSpaceSize(Out<s64> out_free_space_size, FileSys::StorageId storage_id);
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
40
src/core/hle/service/ns/develop_interface.cpp
Executable file
40
src/core/hle/service/ns/develop_interface.cpp
Executable file
@ -0,0 +1,40 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/ns/develop_interface.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
IDevelopInterface::IDevelopInterface(Core::System& system_) : ServiceFramework{system_, "ns:dev"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "LaunchProgram"},
|
||||
{1, nullptr, "TerminateProcess"},
|
||||
{2, nullptr, "TerminateProgram"},
|
||||
{4, nullptr, "GetShellEvent"},
|
||||
{5, nullptr, "GetShellEventInfo"},
|
||||
{6, nullptr, "TerminateApplication"},
|
||||
{7, nullptr, "PrepareLaunchProgramFromHost"},
|
||||
{8, nullptr, "LaunchApplicationFromHost"},
|
||||
{9, nullptr, "LaunchApplicationWithStorageIdForDevelop"},
|
||||
{10, nullptr, "IsSystemMemoryResourceLimitBoosted"},
|
||||
{11, nullptr, "GetRunningApplicationProcessIdForDevelop"},
|
||||
{12, nullptr, "SetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop"},
|
||||
{13, nullptr, "CreateApplicationResourceForDevelop"},
|
||||
{14, nullptr, "IsPreomiaForDevelop"},
|
||||
{15, nullptr, "GetApplicationProgramIdFromHost"},
|
||||
{16, nullptr, "RefreshCachedDebugValues"},
|
||||
{17, nullptr, "PrepareLaunchApplicationFromHost"},
|
||||
{18, nullptr, "GetLaunchEvent"},
|
||||
{19, nullptr, "GetLaunchResult"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IDevelopInterface::~IDevelopInterface() = default;
|
||||
|
||||
} // namespace Service::NS
|
16
src/core/hle/service/ns/develop_interface.h
Executable file
16
src/core/hle/service/ns/develop_interface.h
Executable file
@ -0,0 +1,16 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
class IDevelopInterface final : public ServiceFramework<IDevelopInterface> {
|
||||
public:
|
||||
explicit IDevelopInterface(Core::System& system_);
|
||||
~IDevelopInterface() override;
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
38
src/core/hle/service/ns/document_interface.cpp
Executable file
38
src/core/hle/service/ns/document_interface.cpp
Executable file
@ -0,0 +1,38 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ns/document_interface.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
IDocumentInterface::IDocumentInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "IDocumentInterface"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{21, nullptr, "GetApplicationContentPath"},
|
||||
{23, D<&IDocumentInterface::ResolveApplicationContentPath>, "ResolveApplicationContentPath"},
|
||||
{92, D<&IDocumentInterface::GetRunningApplicationProgramId>, "GetRunningApplicationProgramId"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IDocumentInterface::~IDocumentInterface() = default;
|
||||
|
||||
Result IDocumentInterface::ResolveApplicationContentPath(ContentPath content_path) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called, file_system_proxy_type={}, program_id={:016X}",
|
||||
content_path.file_system_proxy_type, content_path.program_id);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IDocumentInterface::GetRunningApplicationProgramId(Out<u64> out_program_id,
|
||||
u64 caller_program_id) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called, caller_program_id={:016X}", caller_program_id);
|
||||
*out_program_id = system.GetApplicationProcessProgramID();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::NS
|
22
src/core/hle/service/ns/document_interface.h
Executable file
22
src/core/hle/service/ns/document_interface.h
Executable file
@ -0,0 +1,22 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ns/ns_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
class IDocumentInterface final : public ServiceFramework<IDocumentInterface> {
|
||||
public:
|
||||
explicit IDocumentInterface(Core::System& system_);
|
||||
~IDocumentInterface() override;
|
||||
|
||||
private:
|
||||
Result ResolveApplicationContentPath(ContentPath content_path);
|
||||
Result GetRunningApplicationProgramId(Out<u64> out_program_id, u64 caller_program_id);
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
39
src/core/hle/service/ns/download_task_interface.cpp
Executable file
39
src/core/hle/service/ns/download_task_interface.cpp
Executable file
@ -0,0 +1,39 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ns/download_task_interface.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
IDownloadTaskInterface::IDownloadTaskInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "IDownloadTaskInterface"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{701, nullptr, "ClearTaskStatusList"},
|
||||
{702, nullptr, "RequestDownloadTaskList"},
|
||||
{703, nullptr, "RequestEnsureDownloadTask"},
|
||||
{704, nullptr, "ListDownloadTaskStatus"},
|
||||
{705, nullptr, "RequestDownloadTaskListData"},
|
||||
{706, nullptr, "TryCommitCurrentApplicationDownloadTask"},
|
||||
{707, D<&IDownloadTaskInterface::EnableAutoCommit>, "EnableAutoCommit"},
|
||||
{708, D<&IDownloadTaskInterface::DisableAutoCommit>, "DisableAutoCommit"},
|
||||
{709, nullptr, "TriggerDynamicCommitEvent"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IDownloadTaskInterface::~IDownloadTaskInterface() = default;
|
||||
|
||||
Result IDownloadTaskInterface::EnableAutoCommit() {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called");
|
||||
R_SUCCEED();
|
||||
}
|
||||
Result IDownloadTaskInterface::DisableAutoCommit() {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called");
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::NS
|
20
src/core/hle/service/ns/download_task_interface.h
Executable file
20
src/core/hle/service/ns/download_task_interface.h
Executable file
@ -0,0 +1,20 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterface> {
|
||||
public:
|
||||
explicit IDownloadTaskInterface(Core::System& system_);
|
||||
~IDownloadTaskInterface() override;
|
||||
|
||||
private:
|
||||
Result EnableAutoCommit();
|
||||
Result DisableAutoCommit();
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
62
src/core/hle/service/ns/dynamic_rights_interface.cpp
Executable file
62
src/core/hle/service/ns/dynamic_rights_interface.cpp
Executable file
@ -0,0 +1,62 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ns/dynamic_rights_interface.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
IDynamicRightsInterface::IDynamicRightsInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "DynamicRightsInterface"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "RequestApplicationRightsOnServer"},
|
||||
{1, nullptr, "RequestAssignRights"},
|
||||
{4, nullptr, "DeprecatedRequestAssignRightsToResume"},
|
||||
{5, D<&IDynamicRightsInterface::VerifyActivatedRightsOwners>, "VerifyActivatedRightsOwners"},
|
||||
{6, nullptr, "DeprecatedGetApplicationRightsStatus"},
|
||||
{7, nullptr, "RequestPrefetchForDynamicRights"},
|
||||
{8, nullptr, "GetDynamicRightsState"},
|
||||
{9, nullptr, "RequestApplicationRightsOnServerToResume"},
|
||||
{10, nullptr, "RequestAssignRightsToResume"},
|
||||
{11, nullptr, "GetActivatedRightsUsers"},
|
||||
{12, nullptr, "GetApplicationRightsStatus"},
|
||||
{13, D<&IDynamicRightsInterface::GetRunningApplicationStatus>, "GetRunningApplicationStatus"},
|
||||
{14, nullptr, "SelectApplicationLicense"},
|
||||
{15, nullptr, "RequestContentsAuthorizationToken"},
|
||||
{16, nullptr, "QualifyUser"},
|
||||
{17, nullptr, "QualifyUserWithProcessId"},
|
||||
{18, D<&IDynamicRightsInterface::NotifyApplicationRightsCheckStart>, "NotifyApplicationRightsCheckStart"},
|
||||
{19, nullptr, "UpdateUserList"},
|
||||
{20, nullptr, "IsRightsLostUser"},
|
||||
{21, nullptr, "SetRequiredAddOnContentsOnContentsAvailabilityTransition"},
|
||||
{22, nullptr, "GetLimitedApplicationLicense"},
|
||||
{23, nullptr, "GetLimitedApplicationLicenseUpgradableEvent"},
|
||||
{24, nullptr, "NotifyLimitedApplicationLicenseUpgradableEventForDebug"},
|
||||
{25, nullptr, "RequestProceedDynamicRightsState"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IDynamicRightsInterface::~IDynamicRightsInterface() = default;
|
||||
|
||||
Result IDynamicRightsInterface::NotifyApplicationRightsCheckStart() {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called");
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IDynamicRightsInterface::GetRunningApplicationStatus(Out<u32> out_status,
|
||||
u64 rights_handle) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called, rights_handle={:#x}", rights_handle);
|
||||
*out_status = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IDynamicRightsInterface::VerifyActivatedRightsOwners(u64 rights_handle) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called, rights_handle={:#x}", rights_handle);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::NS
|
22
src/core/hle/service/ns/dynamic_rights_interface.h
Executable file
22
src/core/hle/service/ns/dynamic_rights_interface.h
Executable file
@ -0,0 +1,22 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
class IDynamicRightsInterface final : public ServiceFramework<IDynamicRightsInterface> {
|
||||
public:
|
||||
explicit IDynamicRightsInterface(Core::System& system_);
|
||||
~IDynamicRightsInterface() override;
|
||||
|
||||
private:
|
||||
Result NotifyApplicationRightsCheckStart();
|
||||
Result GetRunningApplicationStatus(Out<u32> out_status, u64 rights_handle);
|
||||
Result VerifyActivatedRightsOwners(u64 rights_handle);
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
27
src/core/hle/service/ns/ecommerce_interface.cpp
Executable file
27
src/core/hle/service/ns/ecommerce_interface.cpp
Executable file
@ -0,0 +1,27 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/ns/ecommerce_interface.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
IECommerceInterface::IECommerceInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "IECommerceInterface"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "RequestLinkDevice"},
|
||||
{1, nullptr, "RequestCleanupAllPreInstalledApplications"},
|
||||
{2, nullptr, "RequestCleanupPreInstalledApplication"},
|
||||
{3, nullptr, "RequestSyncRights"},
|
||||
{4, nullptr, "RequestUnlinkDevice"},
|
||||
{5, nullptr, "RequestRevokeAllELicense"},
|
||||
{6, nullptr, "RequestSyncRightsBasedOnAssignedELicenses"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IECommerceInterface::~IECommerceInterface() = default;
|
||||
|
||||
} // namespace Service::NS
|
16
src/core/hle/service/ns/ecommerce_interface.h
Executable file
16
src/core/hle/service/ns/ecommerce_interface.h
Executable file
@ -0,0 +1,16 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
class IECommerceInterface final : public ServiceFramework<IECommerceInterface> {
|
||||
public:
|
||||
explicit IECommerceInterface(Core::System& system_);
|
||||
~IECommerceInterface() override;
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
27
src/core/hle/service/ns/factory_reset_interface.cpp
Executable file
27
src/core/hle/service/ns/factory_reset_interface.cpp
Executable file
@ -0,0 +1,27 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/ns/factory_reset_interface.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
IFactoryResetInterface::IFactoryResetInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "IFactoryResetInterface"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{100, nullptr, "ResetToFactorySettings"},
|
||||
{101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"},
|
||||
{102, nullptr, "ResetToFactorySettingsForRefurbishment"},
|
||||
{103, nullptr, "ResetToFactorySettingsWithPlatformRegion"},
|
||||
{104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"},
|
||||
{105, nullptr, "RequestResetToFactorySettingsSecurely"},
|
||||
{106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IFactoryResetInterface::~IFactoryResetInterface() = default;
|
||||
|
||||
} // namespace Service::NS
|
16
src/core/hle/service/ns/factory_reset_interface.h
Executable file
16
src/core/hle/service/ns/factory_reset_interface.h
Executable file
@ -0,0 +1,16 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
class IFactoryResetInterface final : public ServiceFramework<IFactoryResetInterface> {
|
||||
public:
|
||||
explicit IFactoryResetInterface(Core::System& system_);
|
||||
~IFactoryResetInterface() override;
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
@ -1,893 +1,38 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "common/settings.h"
|
||||
#include "core/arm/debug.h"
|
||||
#include "core/core.h"
|
||||
#include "core/file_sys/control_metadata.h"
|
||||
#include "core/file_sys/patch_manager.h"
|
||||
#include "core/file_sys/vfs/vfs.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/hle/service/glue/glue_manager.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/ns/errors.h"
|
||||
#include "core/hle/service/ns/iplatform_service_manager.h"
|
||||
#include "core/hle/service/ns/language.h"
|
||||
#include "core/hle/service/ns/develop_interface.h"
|
||||
#include "core/hle/service/ns/ns.h"
|
||||
#include "core/hle/service/ns/pdm_qry.h"
|
||||
#include "core/hle/service/ns/platform_service_manager.h"
|
||||
#include "core/hle/service/ns/query_service.h"
|
||||
#include "core/hle/service/ns/service_getter_interface.h"
|
||||
#include "core/hle/service/ns/system_update_interface.h"
|
||||
#include "core/hle/service/ns/vulnerability_manager_interface.h"
|
||||
#include "core/hle/service/server_manager.h"
|
||||
#include "core/hle/service/set/settings_server.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
IAccountProxyInterface::IAccountProxyInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "IAccountProxyInterface"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "CreateUserAccount"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IAccountProxyInterface::~IAccountProxyInterface() = default;
|
||||
|
||||
IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "IApplicationManagerInterface"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "ListApplicationRecord"},
|
||||
{1, nullptr, "GenerateApplicationRecordCount"},
|
||||
{2, nullptr, "GetApplicationRecordUpdateSystemEvent"},
|
||||
{3, nullptr, "GetApplicationViewDeprecated"},
|
||||
{4, nullptr, "DeleteApplicationEntity"},
|
||||
{5, nullptr, "DeleteApplicationCompletely"},
|
||||
{6, nullptr, "IsAnyApplicationEntityRedundant"},
|
||||
{7, nullptr, "DeleteRedundantApplicationEntity"},
|
||||
{8, nullptr, "IsApplicationEntityMovable"},
|
||||
{9, nullptr, "MoveApplicationEntity"},
|
||||
{11, nullptr, "CalculateApplicationOccupiedSize"},
|
||||
{16, nullptr, "PushApplicationRecord"},
|
||||
{17, nullptr, "ListApplicationRecordContentMeta"},
|
||||
{19, nullptr, "LaunchApplicationOld"},
|
||||
{21, nullptr, "GetApplicationContentPath"},
|
||||
{22, nullptr, "TerminateApplication"},
|
||||
{23, nullptr, "ResolveApplicationContentPath"},
|
||||
{26, nullptr, "BeginInstallApplication"},
|
||||
{27, nullptr, "DeleteApplicationRecord"},
|
||||
{30, nullptr, "RequestApplicationUpdateInfo"},
|
||||
{31, nullptr, "Unknown31"},
|
||||
{32, nullptr, "CancelApplicationDownload"},
|
||||
{33, nullptr, "ResumeApplicationDownload"},
|
||||
{35, nullptr, "UpdateVersionList"},
|
||||
{36, nullptr, "PushLaunchVersion"},
|
||||
{37, nullptr, "ListRequiredVersion"},
|
||||
{38, nullptr, "CheckApplicationLaunchVersion"},
|
||||
{39, nullptr, "CheckApplicationLaunchRights"},
|
||||
{40, nullptr, "GetApplicationLogoData"},
|
||||
{41, nullptr, "CalculateApplicationDownloadRequiredSize"},
|
||||
{42, nullptr, "CleanupSdCard"},
|
||||
{43, nullptr, "CheckSdCardMountStatus"},
|
||||
{44, nullptr, "GetSdCardMountStatusChangedEvent"},
|
||||
{45, nullptr, "GetGameCardAttachmentEvent"},
|
||||
{46, nullptr, "GetGameCardAttachmentInfo"},
|
||||
{47, nullptr, "GetTotalSpaceSize"},
|
||||
{48, nullptr, "GetFreeSpaceSize"},
|
||||
{49, nullptr, "GetSdCardRemovedEvent"},
|
||||
{52, nullptr, "GetGameCardUpdateDetectionEvent"},
|
||||
{53, nullptr, "DisableApplicationAutoDelete"},
|
||||
{54, nullptr, "EnableApplicationAutoDelete"},
|
||||
{55, &IApplicationManagerInterface::GetApplicationDesiredLanguage, "GetApplicationDesiredLanguage"},
|
||||
{56, nullptr, "SetApplicationTerminateResult"},
|
||||
{57, nullptr, "ClearApplicationTerminateResult"},
|
||||
{58, nullptr, "GetLastSdCardMountUnexpectedResult"},
|
||||
{59, &IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode, "ConvertApplicationLanguageToLanguageCode"},
|
||||
{60, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
|
||||
{61, nullptr, "GetBackgroundDownloadStressTaskInfo"},
|
||||
{62, nullptr, "GetGameCardStopper"},
|
||||
{63, nullptr, "IsSystemProgramInstalled"},
|
||||
{64, nullptr, "StartApplyDeltaTask"},
|
||||
{65, nullptr, "GetRequestServerStopper"},
|
||||
{66, nullptr, "GetBackgroundApplyDeltaStressTaskInfo"},
|
||||
{67, nullptr, "CancelApplicationApplyDelta"},
|
||||
{68, nullptr, "ResumeApplicationApplyDelta"},
|
||||
{69, nullptr, "CalculateApplicationApplyDeltaRequiredSize"},
|
||||
{70, nullptr, "ResumeAll"},
|
||||
{71, nullptr, "GetStorageSize"},
|
||||
{80, nullptr, "RequestDownloadApplication"},
|
||||
{81, nullptr, "RequestDownloadAddOnContent"},
|
||||
{82, nullptr, "DownloadApplication"},
|
||||
{83, nullptr, "CheckApplicationResumeRights"},
|
||||
{84, nullptr, "GetDynamicCommitEvent"},
|
||||
{85, nullptr, "RequestUpdateApplication2"},
|
||||
{86, nullptr, "EnableApplicationCrashReport"},
|
||||
{87, nullptr, "IsApplicationCrashReportEnabled"},
|
||||
{90, nullptr, "BoostSystemMemoryResourceLimit"},
|
||||
{91, nullptr, "DeprecatedLaunchApplication"},
|
||||
{92, nullptr, "GetRunningApplicationProgramId"},
|
||||
{93, nullptr, "GetMainApplicationProgramIndex"},
|
||||
{94, nullptr, "LaunchApplication"},
|
||||
{95, nullptr, "GetApplicationLaunchInfo"},
|
||||
{96, nullptr, "AcquireApplicationLaunchInfo"},
|
||||
{97, nullptr, "GetMainApplicationProgramIndexByApplicationLaunchInfo"},
|
||||
{98, nullptr, "EnableApplicationAllThreadDumpOnCrash"},
|
||||
{99, nullptr, "LaunchDevMenu"},
|
||||
{100, nullptr, "ResetToFactorySettings"},
|
||||
{101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"},
|
||||
{102, nullptr, "ResetToFactorySettingsForRefurbishment"},
|
||||
{103, nullptr, "ResetToFactorySettingsWithPlatformRegion"},
|
||||
{104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"},
|
||||
{105, nullptr, "RequestResetToFactorySettingsSecurely"},
|
||||
{106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"},
|
||||
{200, nullptr, "CalculateUserSaveDataStatistics"},
|
||||
{201, nullptr, "DeleteUserSaveDataAll"},
|
||||
{210, nullptr, "DeleteUserSystemSaveData"},
|
||||
{211, nullptr, "DeleteSaveData"},
|
||||
{220, nullptr, "UnregisterNetworkServiceAccount"},
|
||||
{221, nullptr, "UnregisterNetworkServiceAccountWithUserSaveDataDeletion"},
|
||||
{300, nullptr, "GetApplicationShellEvent"},
|
||||
{301, nullptr, "PopApplicationShellEventInfo"},
|
||||
{302, nullptr, "LaunchLibraryApplet"},
|
||||
{303, nullptr, "TerminateLibraryApplet"},
|
||||
{304, nullptr, "LaunchSystemApplet"},
|
||||
{305, nullptr, "TerminateSystemApplet"},
|
||||
{306, nullptr, "LaunchOverlayApplet"},
|
||||
{307, nullptr, "TerminateOverlayApplet"},
|
||||
{400, &IApplicationManagerInterface::GetApplicationControlData, "GetApplicationControlData"},
|
||||
{401, nullptr, "InvalidateAllApplicationControlCache"},
|
||||
{402, nullptr, "RequestDownloadApplicationControlData"},
|
||||
{403, nullptr, "GetMaxApplicationControlCacheCount"},
|
||||
{404, nullptr, "InvalidateApplicationControlCache"},
|
||||
{405, nullptr, "ListApplicationControlCacheEntryInfo"},
|
||||
{406, nullptr, "GetApplicationControlProperty"},
|
||||
{407, nullptr, "ListApplicationTitle"},
|
||||
{408, nullptr, "ListApplicationIcon"},
|
||||
{502, nullptr, "RequestCheckGameCardRegistration"},
|
||||
{503, nullptr, "RequestGameCardRegistrationGoldPoint"},
|
||||
{504, nullptr, "RequestRegisterGameCard"},
|
||||
{505, nullptr, "GetGameCardMountFailureEvent"},
|
||||
{506, nullptr, "IsGameCardInserted"},
|
||||
{507, nullptr, "EnsureGameCardAccess"},
|
||||
{508, nullptr, "GetLastGameCardMountFailureResult"},
|
||||
{509, nullptr, "ListApplicationIdOnGameCard"},
|
||||
{510, nullptr, "GetGameCardPlatformRegion"},
|
||||
{600, nullptr, "CountApplicationContentMeta"},
|
||||
{601, nullptr, "ListApplicationContentMetaStatus"},
|
||||
{602, nullptr, "ListAvailableAddOnContent"},
|
||||
{603, nullptr, "GetOwnedApplicationContentMetaStatus"},
|
||||
{604, nullptr, "RegisterContentsExternalKey"},
|
||||
{605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
|
||||
{606, nullptr, "GetContentMetaStorage"},
|
||||
{607, nullptr, "ListAvailableAddOnContent"},
|
||||
{609, nullptr, "ListAvailabilityAssuredAddOnContent"},
|
||||
{610, nullptr, "GetInstalledContentMetaStorage"},
|
||||
{611, nullptr, "PrepareAddOnContent"},
|
||||
{700, nullptr, "PushDownloadTaskList"},
|
||||
{701, nullptr, "ClearTaskStatusList"},
|
||||
{702, nullptr, "RequestDownloadTaskList"},
|
||||
{703, nullptr, "RequestEnsureDownloadTask"},
|
||||
{704, nullptr, "ListDownloadTaskStatus"},
|
||||
{705, nullptr, "RequestDownloadTaskListData"},
|
||||
{800, nullptr, "RequestVersionList"},
|
||||
{801, nullptr, "ListVersionList"},
|
||||
{802, nullptr, "RequestVersionListData"},
|
||||
{900, nullptr, "GetApplicationRecord"},
|
||||
{901, nullptr, "GetApplicationRecordProperty"},
|
||||
{902, nullptr, "EnableApplicationAutoUpdate"},
|
||||
{903, nullptr, "DisableApplicationAutoUpdate"},
|
||||
{904, nullptr, "TouchApplication"},
|
||||
{905, nullptr, "RequestApplicationUpdate"},
|
||||
{906, nullptr, "IsApplicationUpdateRequested"},
|
||||
{907, nullptr, "WithdrawApplicationUpdateRequest"},
|
||||
{908, nullptr, "ListApplicationRecordInstalledContentMeta"},
|
||||
{909, nullptr, "WithdrawCleanupAddOnContentsWithNoRightsRecommendation"},
|
||||
{910, nullptr, "HasApplicationRecord"},
|
||||
{911, nullptr, "SetPreInstalledApplication"},
|
||||
{912, nullptr, "ClearPreInstalledApplicationFlag"},
|
||||
{913, nullptr, "ListAllApplicationRecord"},
|
||||
{914, nullptr, "HideApplicationRecord"},
|
||||
{915, nullptr, "ShowApplicationRecord"},
|
||||
{916, nullptr, "IsApplicationAutoDeleteDisabled"},
|
||||
{1000, nullptr, "RequestVerifyApplicationDeprecated"},
|
||||
{1001, nullptr, "CorruptApplicationForDebug"},
|
||||
{1002, nullptr, "RequestVerifyAddOnContentsRights"},
|
||||
{1003, nullptr, "RequestVerifyApplication"},
|
||||
{1004, nullptr, "CorruptContentForDebug"},
|
||||
{1200, nullptr, "NeedsUpdateVulnerability"},
|
||||
{1300, nullptr, "IsAnyApplicationEntityInstalled"},
|
||||
{1301, nullptr, "DeleteApplicationContentEntities"},
|
||||
{1302, nullptr, "CleanupUnrecordedApplicationEntity"},
|
||||
{1303, nullptr, "CleanupAddOnContentsWithNoRights"},
|
||||
{1304, nullptr, "DeleteApplicationContentEntity"},
|
||||
{1305, nullptr, "TryDeleteRunningApplicationEntity"},
|
||||
{1306, nullptr, "TryDeleteRunningApplicationCompletely"},
|
||||
{1307, nullptr, "TryDeleteRunningApplicationContentEntities"},
|
||||
{1308, nullptr, "DeleteApplicationCompletelyForDebug"},
|
||||
{1309, nullptr, "CleanupUnavailableAddOnContents"},
|
||||
{1310, nullptr, "RequestMoveApplicationEntity"},
|
||||
{1311, nullptr, "EstimateSizeToMove"},
|
||||
{1312, nullptr, "HasMovableEntity"},
|
||||
{1313, nullptr, "CleanupOrphanContents"},
|
||||
{1314, nullptr, "CheckPreconditionSatisfiedToMove"},
|
||||
{1400, nullptr, "PrepareShutdown"},
|
||||
{1500, nullptr, "FormatSdCard"},
|
||||
{1501, nullptr, "NeedsSystemUpdateToFormatSdCard"},
|
||||
{1502, nullptr, "GetLastSdCardFormatUnexpectedResult"},
|
||||
{1504, nullptr, "InsertSdCard"},
|
||||
{1505, nullptr, "RemoveSdCard"},
|
||||
{1506, nullptr, "GetSdCardStartupStatus"},
|
||||
{1600, nullptr, "GetSystemSeedForPseudoDeviceId"},
|
||||
{1601, nullptr, "ResetSystemSeedForPseudoDeviceId"},
|
||||
{1700, nullptr, "ListApplicationDownloadingContentMeta"},
|
||||
{1701, nullptr, "GetApplicationView"},
|
||||
{1702, nullptr, "GetApplicationDownloadTaskStatus"},
|
||||
{1703, nullptr, "GetApplicationViewDownloadErrorContext"},
|
||||
{1704, nullptr, "GetApplicationViewWithPromotionInfo"},
|
||||
{1705, nullptr, "IsPatchAutoDeletableApplication"},
|
||||
{1800, nullptr, "IsNotificationSetupCompleted"},
|
||||
{1801, nullptr, "GetLastNotificationInfoCount"},
|
||||
{1802, nullptr, "ListLastNotificationInfo"},
|
||||
{1803, nullptr, "ListNotificationTask"},
|
||||
{1900, nullptr, "IsActiveAccount"},
|
||||
{1901, nullptr, "RequestDownloadApplicationPrepurchasedRights"},
|
||||
{1902, nullptr, "GetApplicationTicketInfo"},
|
||||
{1903, nullptr, "RequestDownloadApplicationPrepurchasedRightsForAccount"},
|
||||
{2000, nullptr, "GetSystemDeliveryInfo"},
|
||||
{2001, nullptr, "SelectLatestSystemDeliveryInfo"},
|
||||
{2002, nullptr, "VerifyDeliveryProtocolVersion"},
|
||||
{2003, nullptr, "GetApplicationDeliveryInfo"},
|
||||
{2004, nullptr, "HasAllContentsToDeliver"},
|
||||
{2005, nullptr, "CompareApplicationDeliveryInfo"},
|
||||
{2006, nullptr, "CanDeliverApplication"},
|
||||
{2007, nullptr, "ListContentMetaKeyToDeliverApplication"},
|
||||
{2008, nullptr, "NeedsSystemUpdateToDeliverApplication"},
|
||||
{2009, nullptr, "EstimateRequiredSize"},
|
||||
{2010, nullptr, "RequestReceiveApplication"},
|
||||
{2011, nullptr, "CommitReceiveApplication"},
|
||||
{2012, nullptr, "GetReceiveApplicationProgress"},
|
||||
{2013, nullptr, "RequestSendApplication"},
|
||||
{2014, nullptr, "GetSendApplicationProgress"},
|
||||
{2015, nullptr, "CompareSystemDeliveryInfo"},
|
||||
{2016, nullptr, "ListNotCommittedContentMeta"},
|
||||
{2017, nullptr, "CreateDownloadTask"},
|
||||
{2018, nullptr, "GetApplicationDeliveryInfoHash"},
|
||||
{2050, nullptr, "GetApplicationRightsOnClient"},
|
||||
{2051, nullptr, "InvalidateRightsIdCache"},
|
||||
{2100, nullptr, "GetApplicationTerminateResult"},
|
||||
{2101, nullptr, "GetRawApplicationTerminateResult"},
|
||||
{2150, nullptr, "CreateRightsEnvironment"},
|
||||
{2151, nullptr, "DestroyRightsEnvironment"},
|
||||
{2152, nullptr, "ActivateRightsEnvironment"},
|
||||
{2153, nullptr, "DeactivateRightsEnvironment"},
|
||||
{2154, nullptr, "ForceActivateRightsContextForExit"},
|
||||
{2155, nullptr, "UpdateRightsEnvironmentStatus"},
|
||||
{2156, nullptr, "CreateRightsEnvironmentForMicroApplication"},
|
||||
{2160, nullptr, "AddTargetApplicationToRightsEnvironment"},
|
||||
{2161, nullptr, "SetUsersToRightsEnvironment"},
|
||||
{2170, nullptr, "GetRightsEnvironmentStatus"},
|
||||
{2171, nullptr, "GetRightsEnvironmentStatusChangedEvent"},
|
||||
{2180, nullptr, "RequestExtendRightsInRightsEnvironment"},
|
||||
{2181, nullptr, "GetResultOfExtendRightsInRightsEnvironment"},
|
||||
{2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"},
|
||||
{2190, nullptr, "GetRightsEnvironmentHandleForApplication"},
|
||||
{2199, nullptr, "GetRightsEnvironmentCountForDebug"},
|
||||
{2200, nullptr, "GetGameCardApplicationCopyIdentifier"},
|
||||
{2201, nullptr, "GetInstalledApplicationCopyIdentifier"},
|
||||
{2250, nullptr, "RequestReportActiveELicence"},
|
||||
{2300, nullptr, "ListEventLog"},
|
||||
{2350, nullptr, "PerformAutoUpdateByApplicationId"},
|
||||
{2351, nullptr, "RequestNoDownloadRightsErrorResolution"},
|
||||
{2352, nullptr, "RequestResolveNoDownloadRightsError"},
|
||||
{2353, nullptr, "GetApplicationDownloadTaskInfo"},
|
||||
{2354, nullptr, "PrioritizeApplicationBackgroundTask"},
|
||||
{2355, nullptr, "PreferStorageEfficientUpdate"},
|
||||
{2356, nullptr, "RequestStorageEfficientUpdatePreferable"},
|
||||
{2357, nullptr, "EnableMultiCoreDownload"},
|
||||
{2358, nullptr, "DisableMultiCoreDownload"},
|
||||
{2359, nullptr, "IsMultiCoreDownloadEnabled"},
|
||||
{2400, nullptr, "GetPromotionInfo"},
|
||||
{2401, nullptr, "CountPromotionInfo"},
|
||||
{2402, nullptr, "ListPromotionInfo"},
|
||||
{2403, nullptr, "ImportPromotionJsonForDebug"},
|
||||
{2404, nullptr, "ClearPromotionInfoForDebug"},
|
||||
{2500, nullptr, "ConfirmAvailableTime"},
|
||||
{2510, nullptr, "CreateApplicationResource"},
|
||||
{2511, nullptr, "GetApplicationResource"},
|
||||
{2513, nullptr, "LaunchMicroApplication"},
|
||||
{2514, nullptr, "ClearTaskOfAsyncTaskManager"},
|
||||
{2515, nullptr, "CleanupAllPlaceHolderAndFragmentsIfNoTask"},
|
||||
{2516, nullptr, "EnsureApplicationCertificate"},
|
||||
{2517, nullptr, "CreateApplicationInstance"},
|
||||
{2518, nullptr, "UpdateQualificationForDebug"},
|
||||
{2519, nullptr, "IsQualificationTransitionSupported"},
|
||||
{2520, nullptr, "IsQualificationTransitionSupportedByProcessId"},
|
||||
{2521, nullptr, "GetRightsUserChangedEvent"},
|
||||
{2522, nullptr, "IsRomRedirectionAvailable"},
|
||||
{2800, nullptr, "GetApplicationIdOfPreomia"},
|
||||
{3000, nullptr, "RegisterDeviceLockKey"},
|
||||
{3001, nullptr, "UnregisterDeviceLockKey"},
|
||||
{3002, nullptr, "VerifyDeviceLockKey"},
|
||||
{3003, nullptr, "HideApplicationIcon"},
|
||||
{3004, nullptr, "ShowApplicationIcon"},
|
||||
{3005, nullptr, "HideApplicationTitle"},
|
||||
{3006, nullptr, "ShowApplicationTitle"},
|
||||
{3007, nullptr, "EnableGameCard"},
|
||||
{3008, nullptr, "DisableGameCard"},
|
||||
{3009, nullptr, "EnableLocalContentShare"},
|
||||
{3010, nullptr, "DisableLocalContentShare"},
|
||||
{3011, nullptr, "IsApplicationIconHidden"},
|
||||
{3012, nullptr, "IsApplicationTitleHidden"},
|
||||
{3013, nullptr, "IsGameCardEnabled"},
|
||||
{3014, nullptr, "IsLocalContentShareEnabled"},
|
||||
{3050, nullptr, "ListAssignELicenseTaskResult"},
|
||||
{9999, nullptr, "GetApplicationCertificate"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IApplicationManagerInterface::~IApplicationManagerInterface() = default;
|
||||
|
||||
void IApplicationManagerInterface::GetApplicationControlData(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto flag = rp.PopRaw<u64>();
|
||||
LOG_DEBUG(Service_NS, "called with flag={:016X}", flag);
|
||||
|
||||
const auto title_id = rp.PopRaw<u64>();
|
||||
|
||||
const auto size = ctx.GetWriteBufferSize();
|
||||
|
||||
const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
|
||||
system.GetContentProvider()};
|
||||
const auto control = pm.GetControlMetadata();
|
||||
|
||||
std::vector<u8> out;
|
||||
|
||||
if (control.first != nullptr) {
|
||||
if (size < 0x4000) {
|
||||
LOG_ERROR(Service_NS,
|
||||
"output buffer is too small! (actual={:016X}, expected_min=0x4000)", size);
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
// TODO(DarkLordZach): Find a better error code for this.
|
||||
rb.Push(ResultUnknown);
|
||||
return;
|
||||
}
|
||||
|
||||
out.resize(0x4000);
|
||||
const auto bytes = control.first->GetRawBytes();
|
||||
std::memcpy(out.data(), bytes.data(), bytes.size());
|
||||
} else {
|
||||
LOG_WARNING(Service_NS, "missing NACP data for title_id={:016X}, defaulting to zeros.",
|
||||
title_id);
|
||||
out.resize(std::min<u64>(0x4000, size));
|
||||
}
|
||||
|
||||
if (control.second != nullptr) {
|
||||
if (size < 0x4000 + control.second->GetSize()) {
|
||||
LOG_ERROR(Service_NS,
|
||||
"output buffer is too small! (actual={:016X}, expected_min={:016X})", size,
|
||||
0x4000 + control.second->GetSize());
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
// TODO(DarkLordZach): Find a better error code for this.
|
||||
rb.Push(ResultUnknown);
|
||||
return;
|
||||
}
|
||||
|
||||
out.resize(0x4000 + control.second->GetSize());
|
||||
control.second->Read(out.data() + 0x4000, control.second->GetSize());
|
||||
} else {
|
||||
LOG_WARNING(Service_NS, "missing icon data for title_id={:016X}, defaulting to zeros.",
|
||||
title_id);
|
||||
}
|
||||
|
||||
ctx.WriteBuffer(out);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u32>(static_cast<u32>(out.size()));
|
||||
}
|
||||
|
||||
void IApplicationManagerInterface::GetApplicationDesiredLanguage(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto supported_languages = rp.Pop<u32>();
|
||||
|
||||
u8 desired_language{};
|
||||
const auto res = GetApplicationDesiredLanguage(&desired_language, supported_languages);
|
||||
if (res == ResultSuccess) {
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u32>(desired_language);
|
||||
} else {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::GetApplicationDesiredLanguage(u8* out_desired_language,
|
||||
const u32 supported_languages) {
|
||||
LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages);
|
||||
|
||||
// Get language code from settings
|
||||
const auto language_code =
|
||||
Set::GetLanguageCodeFromIndex(static_cast<s32>(Settings::values.language_index.GetValue()));
|
||||
|
||||
// Convert to application language, get priority list
|
||||
const auto application_language = ConvertToApplicationLanguage(language_code);
|
||||
if (application_language == std::nullopt) {
|
||||
LOG_ERROR(Service_NS, "Could not convert application language! language_code={}",
|
||||
language_code);
|
||||
return Service::NS::ResultApplicationLanguageNotFound;
|
||||
}
|
||||
const auto priority_list = GetApplicationLanguagePriorityList(*application_language);
|
||||
if (!priority_list) {
|
||||
LOG_ERROR(Service_NS,
|
||||
"Could not find application language priorities! application_language={}",
|
||||
*application_language);
|
||||
return Service::NS::ResultApplicationLanguageNotFound;
|
||||
}
|
||||
|
||||
// Try to find a valid language.
|
||||
for (const auto lang : *priority_list) {
|
||||
const auto supported_flag = GetSupportedLanguageFlag(lang);
|
||||
if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) {
|
||||
*out_desired_language = static_cast<u8>(lang);
|
||||
return ResultSuccess;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_NS, "Could not find a valid language! supported_languages={:08X}",
|
||||
supported_languages);
|
||||
return Service::NS::ResultApplicationLanguageNotFound;
|
||||
}
|
||||
|
||||
void IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
|
||||
HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto application_language = rp.Pop<u8>();
|
||||
|
||||
u64 language_code{};
|
||||
const auto res = ConvertApplicationLanguageToLanguageCode(&language_code, application_language);
|
||||
if (res == ResultSuccess) {
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(language_code);
|
||||
} else {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(res);
|
||||
}
|
||||
}
|
||||
|
||||
Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
|
||||
u64* out_language_code, u8 application_language) {
|
||||
const auto language_code =
|
||||
ConvertToLanguageCode(static_cast<ApplicationLanguage>(application_language));
|
||||
if (language_code == std::nullopt) {
|
||||
LOG_ERROR(Service_NS, "Language not found! application_language={}", application_language);
|
||||
return Service::NS::ResultApplicationLanguageNotFound;
|
||||
}
|
||||
|
||||
*out_language_code = static_cast<u64>(*language_code);
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "IApplicationVersionInterface"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetLaunchRequiredVersion"},
|
||||
{1, nullptr, "UpgradeLaunchRequiredVersion"},
|
||||
{35, nullptr, "UpdateVersionList"},
|
||||
{36, nullptr, "PushLaunchVersion"},
|
||||
{37, nullptr, "ListRequiredVersion"},
|
||||
{800, nullptr, "RequestVersionList"},
|
||||
{801, nullptr, "ListVersionList"},
|
||||
{802, nullptr, "RequestVersionListData"},
|
||||
{900, nullptr, "ImportAutoUpdatePolicyJsonForDebug"},
|
||||
{901, nullptr, "ListDefaultAutoUpdatePolicy"},
|
||||
{902, nullptr, "ListAutoUpdatePolicyForSpecificApplication"},
|
||||
{1000, nullptr, "PerformAutoUpdate"},
|
||||
{1001, nullptr, "ListAutoUpdateSchedule"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IApplicationVersionInterface::~IApplicationVersionInterface() = default;
|
||||
|
||||
IContentManagementInterface::IContentManagementInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "IContentManagementInterface"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{11, nullptr, "CalculateApplicationOccupiedSize"},
|
||||
{43, nullptr, "CheckSdCardMountStatus"},
|
||||
{47, &IContentManagementInterface::GetTotalSpaceSize, "GetTotalSpaceSize"},
|
||||
{48, &IContentManagementInterface::GetFreeSpaceSize, "GetFreeSpaceSize"},
|
||||
{600, nullptr, "CountApplicationContentMeta"},
|
||||
{601, nullptr, "ListApplicationContentMetaStatus"},
|
||||
{605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
|
||||
{607, nullptr, "IsAnyApplicationRunning"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IContentManagementInterface::~IContentManagementInterface() = default;
|
||||
|
||||
void IContentManagementInterface::GetTotalSpaceSize(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto storage{rp.PopEnum<FileSys::StorageId>()};
|
||||
|
||||
LOG_INFO(Service_Capture, "called, storage={}", storage);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u64>(system.GetFileSystemController().GetTotalSpaceSize(storage));
|
||||
}
|
||||
|
||||
void IContentManagementInterface::GetFreeSpaceSize(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto storage{rp.PopEnum<FileSys::StorageId>()};
|
||||
|
||||
LOG_INFO(Service_Capture, "called, storage={}", storage);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u64>(system.GetFileSystemController().GetFreeSpaceSize(storage));
|
||||
}
|
||||
|
||||
IDocumentInterface::IDocumentInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "IDocumentInterface"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{21, nullptr, "GetApplicationContentPath"},
|
||||
{23, &IDocumentInterface::ResolveApplicationContentPath, "ResolveApplicationContentPath"},
|
||||
{92, &IDocumentInterface::GetRunningApplicationProgramId, "GetRunningApplicationProgramId"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IDocumentInterface::~IDocumentInterface() = default;
|
||||
|
||||
void IDocumentInterface::ResolveApplicationContentPath(HLERequestContext& ctx) {
|
||||
struct ContentPath {
|
||||
u8 file_system_proxy_type;
|
||||
u64 program_id;
|
||||
};
|
||||
static_assert(sizeof(ContentPath) == 0x10, "ContentPath has wrong size");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto content_path = rp.PopRaw<ContentPath>();
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called, file_system_proxy_type={}, program_id={:016X}",
|
||||
content_path.file_system_proxy_type, content_path.program_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void IDocumentInterface::GetRunningApplicationProgramId(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto caller_program_id = rp.PopRaw<u64>();
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called, caller_program_id={:016X}", caller_program_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u64>(system.GetApplicationProcessProgramID());
|
||||
}
|
||||
|
||||
IDownloadTaskInterface::IDownloadTaskInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "IDownloadTaskInterface"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{701, nullptr, "ClearTaskStatusList"},
|
||||
{702, nullptr, "RequestDownloadTaskList"},
|
||||
{703, nullptr, "RequestEnsureDownloadTask"},
|
||||
{704, nullptr, "ListDownloadTaskStatus"},
|
||||
{705, nullptr, "RequestDownloadTaskListData"},
|
||||
{706, nullptr, "TryCommitCurrentApplicationDownloadTask"},
|
||||
{707, nullptr, "EnableAutoCommit"},
|
||||
{708, nullptr, "DisableAutoCommit"},
|
||||
{709, nullptr, "TriggerDynamicCommitEvent"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IDownloadTaskInterface::~IDownloadTaskInterface() = default;
|
||||
|
||||
IECommerceInterface::IECommerceInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "IECommerceInterface"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "RequestLinkDevice"},
|
||||
{1, nullptr, "RequestCleanupAllPreInstalledApplications"},
|
||||
{2, nullptr, "RequestCleanupPreInstalledApplication"},
|
||||
{3, nullptr, "RequestSyncRights"},
|
||||
{4, nullptr, "RequestUnlinkDevice"},
|
||||
{5, nullptr, "RequestRevokeAllELicense"},
|
||||
{6, nullptr, "RequestSyncRightsBasedOnAssignedELicenses"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IECommerceInterface::~IECommerceInterface() = default;
|
||||
|
||||
IFactoryResetInterface::IFactoryResetInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "IFactoryResetInterface"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{100, nullptr, "ResetToFactorySettings"},
|
||||
{101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"},
|
||||
{102, nullptr, "ResetToFactorySettingsForRefurbishment"},
|
||||
{103, nullptr, "ResetToFactorySettingsWithPlatformRegion"},
|
||||
{104, nullptr, "ResetToFactorySettingsWithPlatformRegionAuthentication"},
|
||||
{105, nullptr, "RequestResetToFactorySettingsSecurely"},
|
||||
{106, nullptr, "RequestResetToFactorySettingsWithPlatformRegionAuthenticationSecurely"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IFactoryResetInterface::~IFactoryResetInterface() = default;
|
||||
|
||||
IReadOnlyApplicationRecordInterface::IReadOnlyApplicationRecordInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "IReadOnlyApplicationRecordInterface"} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IReadOnlyApplicationRecordInterface::HasApplicationRecord, "HasApplicationRecord"},
|
||||
{1, nullptr, "NotifyApplicationFailure"},
|
||||
{2, &IReadOnlyApplicationRecordInterface::IsDataCorruptedResult, "IsDataCorruptedResult"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IReadOnlyApplicationRecordInterface::~IReadOnlyApplicationRecordInterface() = default;
|
||||
|
||||
void IReadOnlyApplicationRecordInterface::HasApplicationRecord(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const u64 program_id = rp.PopRaw<u64>();
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called, program_id={:X}", program_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u8>(1);
|
||||
}
|
||||
|
||||
void IReadOnlyApplicationRecordInterface::IsDataCorruptedResult(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto result = rp.PopRaw<Result>();
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called, result={:#x}", result.GetInnerValue());
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u8>(0);
|
||||
}
|
||||
|
||||
IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterface(
|
||||
Core::System& system_)
|
||||
: ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IReadOnlyApplicationControlDataInterface::GetApplicationControlData, "GetApplicationControlData"},
|
||||
{1, nullptr, "GetApplicationDesiredLanguage"},
|
||||
{2, nullptr, "ConvertApplicationLanguageToLanguageCode"},
|
||||
{3, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
|
||||
{4, nullptr, "SelectApplicationDesiredLanguage"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default;
|
||||
|
||||
void IReadOnlyApplicationControlDataInterface::GetApplicationControlData(HLERequestContext& ctx) {
|
||||
enum class ApplicationControlSource : u8 {
|
||||
CacheOnly,
|
||||
Storage,
|
||||
StorageOnly,
|
||||
};
|
||||
|
||||
struct RequestParameters {
|
||||
ApplicationControlSource source;
|
||||
u64 application_id;
|
||||
};
|
||||
static_assert(sizeof(RequestParameters) == 0x10, "RequestParameters has incorrect size.");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
std::vector<u8> nacp_data{};
|
||||
const auto parameters{rp.PopRaw<RequestParameters>()};
|
||||
const auto result =
|
||||
system.GetARPManager().GetControlProperty(&nacp_data, parameters.application_id);
|
||||
|
||||
if (result == ResultSuccess) {
|
||||
ctx.WriteBuffer(nacp_data.data(), nacp_data.size());
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
}
|
||||
|
||||
NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{7988, nullptr, "GetDynamicRightsInterface"},
|
||||
{7989, &NS::PushInterface<IReadOnlyApplicationControlDataInterface>, "GetReadOnlyApplicationControlDataInterface"},
|
||||
{7991, &NS::PushInterface<IReadOnlyApplicationRecordInterface>, "GetReadOnlyApplicationRecordInterface"},
|
||||
{7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"},
|
||||
{7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"},
|
||||
{7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"},
|
||||
{7995, &NS::PushInterface<IAccountProxyInterface>, "GetAccountProxyInterface"},
|
||||
{7996, &NS::PushIApplicationManagerInterface, "GetApplicationManagerInterface"},
|
||||
{7997, &NS::PushInterface<IDownloadTaskInterface>, "GetDownloadTaskInterface"},
|
||||
{7998, &NS::PushInterface<IContentManagementInterface>, "GetContentManagementInterface"},
|
||||
{7999, &NS::PushInterface<IDocumentInterface>, "GetDocumentInterface"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
NS::~NS() = default;
|
||||
|
||||
std::shared_ptr<IApplicationManagerInterface> NS::GetApplicationManagerInterface() const {
|
||||
return GetInterface<IApplicationManagerInterface>(system);
|
||||
}
|
||||
|
||||
class NS_DEV final : public ServiceFramework<NS_DEV> {
|
||||
public:
|
||||
explicit NS_DEV(Core::System& system_) : ServiceFramework{system_, "ns:dev"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "LaunchProgram"},
|
||||
{1, nullptr, "TerminateProcess"},
|
||||
{2, nullptr, "TerminateProgram"},
|
||||
{4, nullptr, "GetShellEvent"},
|
||||
{5, nullptr, "GetShellEventInfo"},
|
||||
{6, nullptr, "TerminateApplication"},
|
||||
{7, nullptr, "PrepareLaunchProgramFromHost"},
|
||||
{8, nullptr, "LaunchApplicationFromHost"},
|
||||
{9, nullptr, "LaunchApplicationWithStorageIdForDevelop"},
|
||||
{10, nullptr, "IsSystemMemoryResourceLimitBoosted"},
|
||||
{11, nullptr, "GetRunningApplicationProcessIdForDevelop"},
|
||||
{12, nullptr, "SetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop"},
|
||||
{13, nullptr, "CreateApplicationResourceForDevelop"},
|
||||
{14, nullptr, "IsPreomiaForDevelop"},
|
||||
{15, nullptr, "GetApplicationProgramIdFromHost"},
|
||||
{16, nullptr, "RefreshCachedDebugValues"},
|
||||
{17, nullptr, "PrepareLaunchApplicationFromHost"},
|
||||
{18, nullptr, "GetLaunchEvent"},
|
||||
{19, nullptr, "GetLaunchResult"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class ISystemUpdateControl final : public ServiceFramework<ISystemUpdateControl> {
|
||||
public:
|
||||
explicit ISystemUpdateControl(Core::System& system_)
|
||||
: ServiceFramework{system_, "ISystemUpdateControl"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "HasDownloaded"},
|
||||
{1, nullptr, "RequestCheckLatestUpdate"},
|
||||
{2, nullptr, "RequestDownloadLatestUpdate"},
|
||||
{3, nullptr, "GetDownloadProgress"},
|
||||
{4, nullptr, "ApplyDownloadedUpdate"},
|
||||
{5, nullptr, "RequestPrepareCardUpdate"},
|
||||
{6, nullptr, "GetPrepareCardUpdateProgress"},
|
||||
{7, nullptr, "HasPreparedCardUpdate"},
|
||||
{8, nullptr, "ApplyCardUpdate"},
|
||||
{9, nullptr, "GetDownloadedEulaDataSize"},
|
||||
{10, nullptr, "GetDownloadedEulaData"},
|
||||
{11, nullptr, "SetupCardUpdate"},
|
||||
{12, nullptr, "GetPreparedCardUpdateEulaDataSize"},
|
||||
{13, nullptr, "GetPreparedCardUpdateEulaData"},
|
||||
{14, nullptr, "SetupCardUpdateViaSystemUpdater"},
|
||||
{15, nullptr, "HasReceived"},
|
||||
{16, nullptr, "RequestReceiveSystemUpdate"},
|
||||
{17, nullptr, "GetReceiveProgress"},
|
||||
{18, nullptr, "ApplyReceivedUpdate"},
|
||||
{19, nullptr, "GetReceivedEulaDataSize"},
|
||||
{20, nullptr, "GetReceivedEulaData"},
|
||||
{21, nullptr, "SetupToReceiveSystemUpdate"},
|
||||
{22, nullptr, "RequestCheckLatestUpdateIncludesRebootlessUpdate"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class NS_SU final : public ServiceFramework<NS_SU> {
|
||||
public:
|
||||
explicit NS_SU(Core::System& system_) : ServiceFramework{system_, "ns:su"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetBackgroundNetworkUpdateState"},
|
||||
{1, &NS_SU::OpenSystemUpdateControl, "OpenSystemUpdateControl"},
|
||||
{2, nullptr, "NotifyExFatDriverRequired"},
|
||||
{3, nullptr, "ClearExFatDriverStatusForDebug"},
|
||||
{4, nullptr, "RequestBackgroundNetworkUpdate"},
|
||||
{5, nullptr, "NotifyBackgroundNetworkUpdate"},
|
||||
{6, nullptr, "NotifyExFatDriverDownloadedForDebug"},
|
||||
{9, nullptr, "GetSystemUpdateNotificationEventForContentDelivery"},
|
||||
{10, nullptr, "NotifySystemUpdateForContentDelivery"},
|
||||
{11, nullptr, "PrepareShutdown"},
|
||||
{12, nullptr, "Unknown12"},
|
||||
{13, nullptr, "Unknown13"},
|
||||
{14, nullptr, "Unknown14"},
|
||||
{15, nullptr, "Unknown15"},
|
||||
{16, nullptr, "DestroySystemUpdateTask"},
|
||||
{17, nullptr, "RequestSendSystemUpdate"},
|
||||
{18, nullptr, "GetSendSystemUpdateProgress"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
private:
|
||||
void OpenSystemUpdateControl(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<ISystemUpdateControl>(system);
|
||||
}
|
||||
};
|
||||
|
||||
class NS_VM final : public ServiceFramework<NS_VM> {
|
||||
public:
|
||||
explicit NS_VM(Core::System& system_) : ServiceFramework{system_, "ns:vm"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{1200, &NS_VM::NeedsUpdateVulnerability, "NeedsUpdateVulnerability"},
|
||||
{1201, nullptr, "UpdateSafeSystemVersionForDebug"},
|
||||
{1202, nullptr, "GetSafeSystemVersion"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
private:
|
||||
void NeedsUpdateVulnerability(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(false);
|
||||
}
|
||||
};
|
||||
|
||||
void LoopProcess(Core::System& system) {
|
||||
auto server_manager = std::make_unique<ServerManager>(system);
|
||||
|
||||
server_manager->RegisterNamedService("ns:am2", std::make_shared<NS>("ns:am2", system));
|
||||
server_manager->RegisterNamedService("ns:ec", std::make_shared<NS>("ns:ec", system));
|
||||
server_manager->RegisterNamedService("ns:rid", std::make_shared<NS>("ns:rid", system));
|
||||
server_manager->RegisterNamedService("ns:rt", std::make_shared<NS>("ns:rt", system));
|
||||
server_manager->RegisterNamedService("ns:web", std::make_shared<NS>("ns:web", system));
|
||||
server_manager->RegisterNamedService("ns:ro", std::make_shared<NS>("ns:ro", system));
|
||||
server_manager->RegisterNamedService(
|
||||
"ns:am2", std::make_shared<IServiceGetterInterface>(system, "ns:am2"));
|
||||
server_manager->RegisterNamedService(
|
||||
"ns:ec", std::make_shared<IServiceGetterInterface>(system, "ns:ec"));
|
||||
server_manager->RegisterNamedService(
|
||||
"ns:rid", std::make_shared<IServiceGetterInterface>(system, "ns:rid"));
|
||||
server_manager->RegisterNamedService(
|
||||
"ns:rt", std::make_shared<IServiceGetterInterface>(system, "ns:rt"));
|
||||
server_manager->RegisterNamedService(
|
||||
"ns:web", std::make_shared<IServiceGetterInterface>(system, "ns:web"));
|
||||
server_manager->RegisterNamedService(
|
||||
"ns:ro", std::make_shared<IServiceGetterInterface>(system, "ns:ro"));
|
||||
|
||||
server_manager->RegisterNamedService("ns:dev", std::make_shared<NS_DEV>(system));
|
||||
server_manager->RegisterNamedService("ns:su", std::make_shared<NS_SU>(system));
|
||||
server_manager->RegisterNamedService("ns:vm", std::make_shared<NS_VM>(system));
|
||||
server_manager->RegisterNamedService("pdm:qry", std::make_shared<PDM_QRY>(system));
|
||||
server_manager->RegisterNamedService("ns:dev", std::make_shared<IDevelopInterface>(system));
|
||||
server_manager->RegisterNamedService("ns:su", std::make_shared<ISystemUpdateInterface>(system));
|
||||
server_manager->RegisterNamedService("ns:vm",
|
||||
std::make_shared<IVulnerabilityManagerInterface>(system));
|
||||
server_manager->RegisterNamedService("pdm:qry", std::make_shared<IQueryService>(system));
|
||||
|
||||
server_manager->RegisterNamedService("pl:s",
|
||||
std::make_shared<IPlatformServiceManager>(system, "pl:s"));
|
||||
|
@ -3,141 +3,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Service {
|
||||
|
||||
namespace FileSystem {
|
||||
class FileSystemController;
|
||||
} // namespace FileSystem
|
||||
|
||||
namespace NS {
|
||||
|
||||
class IAccountProxyInterface final : public ServiceFramework<IAccountProxyInterface> {
|
||||
public:
|
||||
explicit IAccountProxyInterface(Core::System& system_);
|
||||
~IAccountProxyInterface() override;
|
||||
};
|
||||
|
||||
class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> {
|
||||
public:
|
||||
explicit IApplicationManagerInterface(Core::System& system_);
|
||||
~IApplicationManagerInterface() override;
|
||||
|
||||
Result GetApplicationDesiredLanguage(u8* out_desired_language, u32 supported_languages);
|
||||
Result ConvertApplicationLanguageToLanguageCode(u64* out_language_code,
|
||||
u8 application_language);
|
||||
|
||||
private:
|
||||
void GetApplicationControlData(HLERequestContext& ctx);
|
||||
void GetApplicationDesiredLanguage(HLERequestContext& ctx);
|
||||
void ConvertApplicationLanguageToLanguageCode(HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> {
|
||||
public:
|
||||
explicit IApplicationVersionInterface(Core::System& system_);
|
||||
~IApplicationVersionInterface() override;
|
||||
};
|
||||
|
||||
class IContentManagementInterface final : public ServiceFramework<IContentManagementInterface> {
|
||||
public:
|
||||
explicit IContentManagementInterface(Core::System& system_);
|
||||
~IContentManagementInterface() override;
|
||||
|
||||
private:
|
||||
void GetTotalSpaceSize(HLERequestContext& ctx);
|
||||
void GetFreeSpaceSize(HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
class IDocumentInterface final : public ServiceFramework<IDocumentInterface> {
|
||||
public:
|
||||
explicit IDocumentInterface(Core::System& system_);
|
||||
~IDocumentInterface() override;
|
||||
|
||||
private:
|
||||
void ResolveApplicationContentPath(HLERequestContext& ctx);
|
||||
void GetRunningApplicationProgramId(HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterface> {
|
||||
public:
|
||||
explicit IDownloadTaskInterface(Core::System& system_);
|
||||
~IDownloadTaskInterface() override;
|
||||
};
|
||||
|
||||
class IECommerceInterface final : public ServiceFramework<IECommerceInterface> {
|
||||
public:
|
||||
explicit IECommerceInterface(Core::System& system_);
|
||||
~IECommerceInterface() override;
|
||||
};
|
||||
|
||||
class IFactoryResetInterface final : public ServiceFramework<IFactoryResetInterface> {
|
||||
public:
|
||||
explicit IFactoryResetInterface(Core::System& system_);
|
||||
~IFactoryResetInterface() override;
|
||||
};
|
||||
|
||||
class IReadOnlyApplicationRecordInterface final
|
||||
: public ServiceFramework<IReadOnlyApplicationRecordInterface> {
|
||||
public:
|
||||
explicit IReadOnlyApplicationRecordInterface(Core::System& system_);
|
||||
~IReadOnlyApplicationRecordInterface() override;
|
||||
|
||||
private:
|
||||
void HasApplicationRecord(HLERequestContext& ctx);
|
||||
void IsDataCorruptedResult(HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
class IReadOnlyApplicationControlDataInterface final
|
||||
: public ServiceFramework<IReadOnlyApplicationControlDataInterface> {
|
||||
public:
|
||||
explicit IReadOnlyApplicationControlDataInterface(Core::System& system_);
|
||||
~IReadOnlyApplicationControlDataInterface() override;
|
||||
|
||||
private:
|
||||
void GetApplicationControlData(HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
class NS final : public ServiceFramework<NS> {
|
||||
public:
|
||||
explicit NS(const char* name, Core::System& system_);
|
||||
~NS() override;
|
||||
|
||||
std::shared_ptr<IApplicationManagerInterface> GetApplicationManagerInterface() const;
|
||||
|
||||
private:
|
||||
template <typename T, typename... Args>
|
||||
void PushInterface(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<T>(system);
|
||||
}
|
||||
|
||||
void PushIApplicationManagerInterface(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushIpcInterface<IApplicationManagerInterface>(system);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
std::shared_ptr<T> GetInterface(Args&&... args) const {
|
||||
static_assert(std::is_base_of_v<SessionRequestHandler, T>,
|
||||
"Not a base of ServiceFrameworkBase");
|
||||
|
||||
return std::make_shared<T>(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
namespace Service::NS {
|
||||
|
||||
void LoopProcess(Core::System& system);
|
||||
|
||||
} // namespace NS
|
||||
} // namespace Service
|
||||
} // namespace Service::NS
|
||||
|
12
src/core/hle/service/ns/ns_results.h
Executable file
12
src/core/hle/service/ns/ns_results.h
Executable file
@ -0,0 +1,12 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/result.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
constexpr Result ResultApplicationLanguageNotFound{ErrorModule::NS, 300};
|
||||
|
||||
}
|
102
src/core/hle/service/ns/ns_types.h
Executable file
102
src/core/hle/service/ns/ns_types.h
Executable file
@ -0,0 +1,102 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/uuid.h"
|
||||
#include "core/file_sys/romfs_factory.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
enum class ApplicationRecordType : u8 {
|
||||
Installing = 2,
|
||||
Installed = 3,
|
||||
GameCardNotInserted = 5,
|
||||
Archived = 0xB,
|
||||
GameCard = 0x10,
|
||||
};
|
||||
|
||||
enum class ApplicationControlSource : u8 {
|
||||
CacheOnly = 0,
|
||||
Storage = 1,
|
||||
StorageOnly = 2,
|
||||
};
|
||||
|
||||
enum class BackgroundNetworkUpdateState : u8 {
|
||||
None,
|
||||
InProgress,
|
||||
Ready,
|
||||
};
|
||||
|
||||
struct ApplicationRecord {
|
||||
u64 application_id;
|
||||
ApplicationRecordType type;
|
||||
u8 unknown;
|
||||
INSERT_PADDING_BYTES_NOINIT(0x6);
|
||||
u8 unknown2;
|
||||
INSERT_PADDING_BYTES_NOINIT(0x7);
|
||||
};
|
||||
static_assert(sizeof(ApplicationRecord) == 0x18, "ApplicationRecord is an invalid size");
|
||||
|
||||
/// ApplicationView
|
||||
struct ApplicationView {
|
||||
u64 application_id; ///< ApplicationId.
|
||||
u32 unk; ///< Unknown.
|
||||
u32 flags; ///< Flags.
|
||||
u8 unk_x10[0x10]; ///< Unknown.
|
||||
u32 unk_x20; ///< Unknown.
|
||||
u16 unk_x24; ///< Unknown.
|
||||
u8 unk_x26[0x2]; ///< Unknown.
|
||||
u8 unk_x28[0x8]; ///< Unknown.
|
||||
u8 unk_x30[0x10]; ///< Unknown.
|
||||
u32 unk_x40; ///< Unknown.
|
||||
u8 unk_x44; ///< Unknown.
|
||||
u8 unk_x45[0xb]; ///< Unknown.
|
||||
};
|
||||
|
||||
struct ApplicationRightsOnClient {
|
||||
u64 application_id;
|
||||
Common::UUID uid;
|
||||
u8 flags;
|
||||
u8 flags2;
|
||||
INSERT_PADDING_BYTES(0x6);
|
||||
};
|
||||
|
||||
/// NsPromotionInfo
|
||||
struct PromotionInfo {
|
||||
u64 start_timestamp; ///< POSIX timestamp for the promotion start.
|
||||
u64 end_timestamp; ///< POSIX timestamp for the promotion end.
|
||||
s64 remaining_time; ///< Remaining time until the promotion ends, in nanoseconds
|
||||
///< ({end_timestamp - current_time} converted to nanoseconds).
|
||||
INSERT_PADDING_BYTES_NOINIT(0x4);
|
||||
u8 flags; ///< Flags. Bit0: whether the PromotionInfo is valid (including bit1). Bit1 clear:
|
||||
///< remaining_time is set.
|
||||
INSERT_PADDING_BYTES_NOINIT(0x3);
|
||||
};
|
||||
|
||||
/// NsApplicationViewWithPromotionInfo
|
||||
struct ApplicationViewWithPromotionInfo {
|
||||
ApplicationView view; ///< \ref NsApplicationView
|
||||
PromotionInfo promotion; ///< \ref NsPromotionInfo
|
||||
};
|
||||
|
||||
struct ApplicationOccupiedSizeEntity {
|
||||
FileSys::StorageId storage_id;
|
||||
u64 app_size;
|
||||
u64 patch_size;
|
||||
u64 aoc_size;
|
||||
};
|
||||
static_assert(sizeof(ApplicationOccupiedSizeEntity) == 0x20,
|
||||
"ApplicationOccupiedSizeEntity has incorrect size.");
|
||||
|
||||
struct ApplicationOccupiedSize {
|
||||
std::array<ApplicationOccupiedSizeEntity, 4> entities;
|
||||
};
|
||||
|
||||
struct ContentPath {
|
||||
u8 file_system_proxy_type;
|
||||
u64 program_id;
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
273
src/core/hle/service/ns/platform_service_manager.cpp
Executable file
273
src/core/hle/service/ns/platform_service_manager.cpp
Executable file
@ -0,0 +1,273 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/core.h"
|
||||
#include "core/file_sys/content_archive.h"
|
||||
#include "core/file_sys/nca_metadata.h"
|
||||
#include "core/file_sys/registered_cache.h"
|
||||
#include "core/file_sys/romfs.h"
|
||||
#include "core/file_sys/system_archive/system_archive.h"
|
||||
#include "core/hle/kernel/k_shared_memory.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/physical_memory.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/hle/service/ns/platform_service_manager.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
struct FontRegion {
|
||||
u32 offset;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
// The below data is specific to shared font data dumped from Switch on f/w 2.2
|
||||
// Virtual address and offsets/sizes likely will vary by dump
|
||||
[[maybe_unused]] constexpr VAddr SHARED_FONT_MEM_VADDR{0x00000009d3016000ULL};
|
||||
constexpr u32 EXPECTED_RESULT{0x7f9a0218}; // What we expect the decrypted bfttf first 4 bytes to be
|
||||
constexpr u32 EXPECTED_MAGIC{0x36f81a1e}; // What we expect the encrypted bfttf first 4 bytes to be
|
||||
constexpr u64 SHARED_FONT_MEM_SIZE{0x1100000};
|
||||
constexpr FontRegion EMPTY_REGION{0, 0};
|
||||
|
||||
static void DecryptSharedFont(const std::vector<u32>& input, Kernel::PhysicalMemory& output,
|
||||
std::size_t& offset) {
|
||||
ASSERT_MSG(offset + (input.size() * sizeof(u32)) < SHARED_FONT_MEM_SIZE,
|
||||
"Shared fonts exceeds 17mb!");
|
||||
ASSERT_MSG(input[0] == EXPECTED_MAGIC, "Failed to derive key, unexpected magic number");
|
||||
|
||||
const u32 KEY = input[0] ^ EXPECTED_RESULT; // Derive key using an inverse xor
|
||||
std::vector<u32> transformed_font(input.size());
|
||||
// TODO(ogniK): Figure out a better way to do this
|
||||
std::transform(input.begin(), input.end(), transformed_font.begin(),
|
||||
[&KEY](u32 font_data) { return Common::swap32(font_data ^ KEY); });
|
||||
transformed_font[1] = Common::swap32(transformed_font[1]) ^ KEY; // "re-encrypt" the size
|
||||
std::memcpy(output.data() + offset, transformed_font.data(),
|
||||
transformed_font.size() * sizeof(u32));
|
||||
offset += transformed_font.size() * sizeof(u32);
|
||||
}
|
||||
|
||||
void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output) {
|
||||
ASSERT_MSG(input[0] == EXPECTED_MAGIC, "Failed to derive key, unexpected magic number");
|
||||
|
||||
if (input.size() < 2) {
|
||||
LOG_ERROR(Service_NS, "Input font is empty");
|
||||
return;
|
||||
}
|
||||
|
||||
const u32 KEY = input[0] ^ EXPECTED_RESULT; // Derive key using an inverse xor
|
||||
std::vector<u32> transformed_font(input.size());
|
||||
// TODO(ogniK): Figure out a better way to do this
|
||||
std::transform(input.begin(), input.end(), transformed_font.begin(),
|
||||
[&KEY](u32 font_data) { return Common::swap32(font_data ^ KEY); });
|
||||
std::memcpy(output.data(), transformed_font.data() + 2,
|
||||
(transformed_font.size() - 2) * sizeof(u32));
|
||||
}
|
||||
|
||||
void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output,
|
||||
std::size_t& offset) {
|
||||
ASSERT_MSG(offset + (input.size() * sizeof(u32)) < SHARED_FONT_MEM_SIZE,
|
||||
"Shared fonts exceeds 17mb!");
|
||||
|
||||
const auto key = Common::swap32(EXPECTED_RESULT ^ EXPECTED_MAGIC);
|
||||
std::vector<u32> transformed_font(input.size() + 2);
|
||||
transformed_font[0] = Common::swap32(EXPECTED_MAGIC);
|
||||
transformed_font[1] = Common::swap32(static_cast<u32>(input.size() * sizeof(u32))) ^ key;
|
||||
std::transform(input.begin(), input.end(), transformed_font.begin() + 2,
|
||||
[key](u32 in) { return in ^ key; });
|
||||
std::memcpy(output.data() + offset, transformed_font.data(),
|
||||
transformed_font.size() * sizeof(u32));
|
||||
offset += transformed_font.size() * sizeof(u32);
|
||||
}
|
||||
|
||||
// Helper function to make BuildSharedFontsRawRegions a bit nicer
|
||||
static u32 GetU32Swapped(const u8* data) {
|
||||
u32 value;
|
||||
std::memcpy(&value, data, sizeof(value));
|
||||
return Common::swap32(value);
|
||||
}
|
||||
|
||||
struct IPlatformServiceManager::Impl {
|
||||
const FontRegion& GetSharedFontRegion(std::size_t index) const {
|
||||
if (index >= shared_font_regions.size() || shared_font_regions.empty()) {
|
||||
// No font fallback
|
||||
return EMPTY_REGION;
|
||||
}
|
||||
return shared_font_regions.at(index);
|
||||
}
|
||||
|
||||
void BuildSharedFontsRawRegions(const Kernel::PhysicalMemory& input) {
|
||||
// As we can derive the xor key we can just populate the offsets
|
||||
// based on the shared memory dump
|
||||
unsigned cur_offset = 0;
|
||||
|
||||
for (std::size_t i = 0; i < SHARED_FONTS.size(); i++) {
|
||||
// Out of shared fonts/invalid font
|
||||
if (GetU32Swapped(input.data() + cur_offset) != EXPECTED_RESULT) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Derive key within inverse xor
|
||||
const u32 KEY = GetU32Swapped(input.data() + cur_offset) ^ EXPECTED_MAGIC;
|
||||
const u32 SIZE = GetU32Swapped(input.data() + cur_offset + 4) ^ KEY;
|
||||
shared_font_regions.push_back(FontRegion{cur_offset + 8, SIZE});
|
||||
cur_offset += SIZE + 8;
|
||||
}
|
||||
}
|
||||
|
||||
/// Backing memory for the shared font data
|
||||
std::shared_ptr<Kernel::PhysicalMemory> shared_font;
|
||||
|
||||
// Automatically populated based on shared_fonts dump or system archives.
|
||||
std::vector<FontRegion> shared_font_regions;
|
||||
};
|
||||
|
||||
IPlatformServiceManager::IPlatformServiceManager(Core::System& system_, const char* service_name_)
|
||||
: ServiceFramework{system_, service_name_}, impl{std::make_unique<Impl>()} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IPlatformServiceManager::RequestLoad>, "RequestLoad"},
|
||||
{1, D<&IPlatformServiceManager::GetLoadState>, "GetLoadState"},
|
||||
{2, D<&IPlatformServiceManager::GetSize>, "GetSize"},
|
||||
{3, D<&IPlatformServiceManager::GetSharedMemoryAddressOffset>, "GetSharedMemoryAddressOffset"},
|
||||
{4, D<&IPlatformServiceManager::GetSharedMemoryNativeHandle>, "GetSharedMemoryNativeHandle"},
|
||||
{5, D<&IPlatformServiceManager::GetSharedFontInOrderOfPriority>, "GetSharedFontInOrderOfPriority"},
|
||||
{6, D<&IPlatformServiceManager::GetSharedFontInOrderOfPriority>, "GetSharedFontInOrderOfPriorityForSystem"},
|
||||
{100, nullptr, "RequestApplicationFunctionAuthorization"},
|
||||
{101, nullptr, "RequestApplicationFunctionAuthorizationByProcessId"},
|
||||
{102, nullptr, "RequestApplicationFunctionAuthorizationByApplicationId"},
|
||||
{103, nullptr, "RefreshApplicationFunctionBlackListDebugRecord"},
|
||||
{104, nullptr, "RequestApplicationFunctionAuthorizationByProgramId"},
|
||||
{105, nullptr, "GetFunctionBlackListSystemVersionToAuthorize"},
|
||||
{106, nullptr, "GetFunctionBlackListVersion"},
|
||||
{1000, nullptr, "LoadNgWordDataForPlatformRegionChina"},
|
||||
{1001, nullptr, "GetNgWordDataSizeForPlatformRegionChina"},
|
||||
};
|
||||
// clang-format on
|
||||
RegisterHandlers(functions);
|
||||
|
||||
auto& fsc = system.GetFileSystemController();
|
||||
|
||||
// Attempt to load shared font data from disk
|
||||
const auto* nand = fsc.GetSystemNANDContents();
|
||||
std::size_t offset = 0;
|
||||
// Rebuild shared fonts from data ncas or synthesize
|
||||
|
||||
impl->shared_font = std::make_shared<Kernel::PhysicalMemory>(SHARED_FONT_MEM_SIZE);
|
||||
for (auto font : SHARED_FONTS) {
|
||||
FileSys::VirtualFile romfs;
|
||||
const auto nca =
|
||||
nand->GetEntry(static_cast<u64>(font.first), FileSys::ContentRecordType::Data);
|
||||
if (nca) {
|
||||
romfs = nca->GetRomFS();
|
||||
}
|
||||
|
||||
if (!romfs) {
|
||||
romfs = FileSys::SystemArchive::SynthesizeSystemArchive(static_cast<u64>(font.first));
|
||||
}
|
||||
|
||||
if (!romfs) {
|
||||
LOG_ERROR(Service_NS, "Failed to find or synthesize {:016X}! Skipping", font.first);
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto extracted_romfs = FileSys::ExtractRomFS(romfs);
|
||||
if (!extracted_romfs) {
|
||||
LOG_ERROR(Service_NS, "Failed to extract RomFS for {:016X}! Skipping", font.first);
|
||||
continue;
|
||||
}
|
||||
const auto font_fp = extracted_romfs->GetFile(font.second);
|
||||
if (!font_fp) {
|
||||
LOG_ERROR(Service_NS, "{:016X} has no file \"{}\"! Skipping", font.first, font.second);
|
||||
continue;
|
||||
}
|
||||
std::vector<u32> font_data_u32(font_fp->GetSize() / sizeof(u32));
|
||||
font_fp->ReadBytes<u32>(font_data_u32.data(), font_fp->GetSize());
|
||||
// We need to be BigEndian as u32s for the xor encryption
|
||||
std::transform(font_data_u32.begin(), font_data_u32.end(), font_data_u32.begin(),
|
||||
Common::swap32);
|
||||
// Font offset and size do not account for the header
|
||||
const FontRegion region{static_cast<u32>(offset + 8),
|
||||
static_cast<u32>((font_data_u32.size() * sizeof(u32)) - 8)};
|
||||
DecryptSharedFont(font_data_u32, *impl->shared_font, offset);
|
||||
impl->shared_font_regions.push_back(region);
|
||||
}
|
||||
}
|
||||
|
||||
IPlatformServiceManager::~IPlatformServiceManager() = default;
|
||||
|
||||
Result IPlatformServiceManager::RequestLoad(SharedFontType type) {
|
||||
// Games don't call this so all fonts should be loaded
|
||||
LOG_DEBUG(Service_NS, "called, shared_font_type={}", type);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IPlatformServiceManager::GetLoadState(Out<LoadState> out_load_state, SharedFontType type) {
|
||||
LOG_DEBUG(Service_NS, "called, shared_font_type={}", type);
|
||||
*out_load_state = LoadState::Loaded;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IPlatformServiceManager::GetSize(Out<u32> out_size, SharedFontType type) {
|
||||
LOG_DEBUG(Service_NS, "called, shared_font_type={}", type);
|
||||
*out_size = impl->GetSharedFontRegion(static_cast<size_t>(type)).size;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IPlatformServiceManager::GetSharedMemoryAddressOffset(Out<u32> out_shared_memory_offset,
|
||||
SharedFontType type) {
|
||||
LOG_DEBUG(Service_NS, "called, shared_font_type={}", type);
|
||||
*out_shared_memory_offset = impl->GetSharedFontRegion(static_cast<size_t>(type)).offset;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IPlatformServiceManager::GetSharedMemoryNativeHandle(
|
||||
OutCopyHandle<Kernel::KSharedMemory> out_shared_memory_native_handle) {
|
||||
// Map backing memory for the font data
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
|
||||
// Create shared font memory object
|
||||
std::memcpy(kernel.GetFontSharedMem().GetPointer(), impl->shared_font->data(),
|
||||
impl->shared_font->size());
|
||||
|
||||
// FIXME: this shouldn't belong to the kernel
|
||||
*out_shared_memory_native_handle = &kernel.GetFontSharedMem();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IPlatformServiceManager::GetSharedFontInOrderOfPriority(
|
||||
OutArray<u32, BufferAttr_HipcMapAlias> out_font_codes,
|
||||
OutArray<u32, BufferAttr_HipcMapAlias> out_font_offsets,
|
||||
OutArray<u32, BufferAttr_HipcMapAlias> out_font_sizes, Out<bool> out_fonts_are_loaded,
|
||||
Out<u32> out_font_count, Set::LanguageCode language_code) {
|
||||
LOG_DEBUG(Service_NS, "called, language_code={:#x}", language_code);
|
||||
|
||||
// The maximum number of elements that can be returned is 6. Regardless of the available fonts
|
||||
// or buffer size.
|
||||
constexpr size_t MaxElementCount = 6;
|
||||
|
||||
// TODO(ogniK): Have actual priority order
|
||||
const auto max_size = std::min({MaxElementCount, out_font_codes.size(), out_font_offsets.size(),
|
||||
out_font_sizes.size(), impl->shared_font_regions.size()});
|
||||
|
||||
for (size_t i = 0; i < max_size; i++) {
|
||||
auto region = impl->GetSharedFontRegion(i);
|
||||
|
||||
out_font_codes[i] = static_cast<u32>(i);
|
||||
out_font_offsets[i] = region.offset;
|
||||
out_font_sizes[i] = region.size;
|
||||
}
|
||||
|
||||
*out_fonts_are_loaded = true;
|
||||
*out_font_count = static_cast<u32>(max_size);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::NS
|
79
src/core/hle/service/ns/platform_service_manager.h
Executable file
79
src/core/hle/service/ns/platform_service_manager.h
Executable file
@ -0,0 +1,79 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/set/settings_types.h"
|
||||
|
||||
namespace Service {
|
||||
|
||||
namespace FileSystem {
|
||||
class FileSystemController;
|
||||
} // namespace FileSystem
|
||||
|
||||
namespace NS {
|
||||
|
||||
enum class FontArchives : u64 {
|
||||
Extension = 0x0100000000000810,
|
||||
Standard = 0x0100000000000811,
|
||||
Korean = 0x0100000000000812,
|
||||
ChineseTraditional = 0x0100000000000813,
|
||||
ChineseSimple = 0x0100000000000814,
|
||||
};
|
||||
|
||||
enum class SharedFontType : u32 {
|
||||
JapanUSEuropeStandard = 0,
|
||||
ChineseSimplified = 1,
|
||||
ExtendedChineseSimplified = 2,
|
||||
ChineseTraditional = 3,
|
||||
KoreanHangul = 4,
|
||||
NintendoExtended = 5,
|
||||
};
|
||||
|
||||
enum class LoadState : u32 {
|
||||
Loading = 0,
|
||||
Loaded = 1,
|
||||
};
|
||||
|
||||
constexpr std::array<std::pair<FontArchives, const char*>, 7> SHARED_FONTS{
|
||||
std::make_pair(FontArchives::Standard, "nintendo_udsg-r_std_003.bfttf"),
|
||||
std::make_pair(FontArchives::ChineseSimple, "nintendo_udsg-r_org_zh-cn_003.bfttf"),
|
||||
std::make_pair(FontArchives::ChineseSimple, "nintendo_udsg-r_ext_zh-cn_003.bfttf"),
|
||||
std::make_pair(FontArchives::ChineseTraditional, "nintendo_udjxh-db_zh-tw_003.bfttf"),
|
||||
std::make_pair(FontArchives::Korean, "nintendo_udsg-r_ko_003.bfttf"),
|
||||
std::make_pair(FontArchives::Extension, "nintendo_ext_003.bfttf"),
|
||||
std::make_pair(FontArchives::Extension, "nintendo_ext2_003.bfttf"),
|
||||
};
|
||||
|
||||
void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output);
|
||||
void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, std::size_t& offset);
|
||||
|
||||
class IPlatformServiceManager final : public ServiceFramework<IPlatformServiceManager> {
|
||||
public:
|
||||
explicit IPlatformServiceManager(Core::System& system_, const char* service_name_);
|
||||
~IPlatformServiceManager() override;
|
||||
|
||||
private:
|
||||
Result RequestLoad(SharedFontType type);
|
||||
Result GetLoadState(Out<LoadState> out_load_state, SharedFontType type);
|
||||
Result GetSize(Out<u32> out_size, SharedFontType type);
|
||||
Result GetSharedMemoryAddressOffset(Out<u32> out_shared_memory_offset, SharedFontType type);
|
||||
Result GetSharedMemoryNativeHandle(
|
||||
OutCopyHandle<Kernel::KSharedMemory> out_shared_memory_native_handle);
|
||||
Result GetSharedFontInOrderOfPriority(OutArray<u32, BufferAttr_HipcMapAlias> out_font_codes,
|
||||
OutArray<u32, BufferAttr_HipcMapAlias> out_font_offsets,
|
||||
OutArray<u32, BufferAttr_HipcMapAlias> out_font_sizes,
|
||||
Out<bool> out_fonts_are_loaded, Out<u32> out_font_count,
|
||||
Set::LanguageCode language_code);
|
||||
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
};
|
||||
|
||||
} // namespace NS
|
||||
|
||||
} // namespace Service
|
57
src/core/hle/service/ns/query_service.cpp
Executable file
57
src/core/hle/service/ns/query_service.cpp
Executable file
@ -0,0 +1,57 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "common/uuid.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ns/query_service.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
IQueryService::IQueryService(Core::System& system_) : ServiceFramework{system_, "pdm:qry"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "QueryAppletEvent"},
|
||||
{1, nullptr, "QueryPlayStatistics"},
|
||||
{2, nullptr, "QueryPlayStatisticsByUserAccountId"},
|
||||
{3, nullptr, "QueryPlayStatisticsByNetworkServiceAccountId"},
|
||||
{4, nullptr, "QueryPlayStatisticsByApplicationId"},
|
||||
{5, D<&IQueryService::QueryPlayStatisticsByApplicationIdAndUserAccountId>, "QueryPlayStatisticsByApplicationIdAndUserAccountId"},
|
||||
{6, nullptr, "QueryPlayStatisticsByApplicationIdAndNetworkServiceAccountId"},
|
||||
{7, nullptr, "QueryLastPlayTimeV0"},
|
||||
{8, nullptr, "QueryPlayEvent"},
|
||||
{9, nullptr, "GetAvailablePlayEventRange"},
|
||||
{10, nullptr, "QueryAccountEvent"},
|
||||
{11, nullptr, "QueryAccountPlayEvent"},
|
||||
{12, nullptr, "GetAvailableAccountPlayEventRange"},
|
||||
{13, nullptr, "QueryApplicationPlayStatisticsForSystemV0"},
|
||||
{14, nullptr, "QueryRecentlyPlayedApplication"},
|
||||
{15, nullptr, "GetRecentlyPlayedApplicationUpdateEvent"},
|
||||
{16, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystemV0"},
|
||||
{17, nullptr, "QueryLastPlayTime"},
|
||||
{18, nullptr, "QueryApplicationPlayStatisticsForSystem"},
|
||||
{19, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystem"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IQueryService::~IQueryService() = default;
|
||||
|
||||
Result IQueryService::QueryPlayStatisticsByApplicationIdAndUserAccountId(
|
||||
Out<PlayStatistics> out_play_statistics, bool unknown, Common::UUID account_id,
|
||||
u64 application_id) {
|
||||
// TODO(German77): Read statistics of the game
|
||||
*out_play_statistics = {
|
||||
.application_id = application_id,
|
||||
.total_launches = 1,
|
||||
};
|
||||
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called. unknown={}. application_id={:016X}, account_id={}",
|
||||
unknown, application_id, account_id.FormattedString());
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::NS
|
36
src/core/hle/service/ns/query_service.h
Executable file
36
src/core/hle/service/ns/query_service.h
Executable file
@ -0,0 +1,36 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/uuid.h"
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
struct PlayStatistics {
|
||||
u64 application_id{};
|
||||
u32 first_entry_index{};
|
||||
u32 first_timestamp_user{};
|
||||
u32 first_timestamp_network{};
|
||||
u32 last_entry_index{};
|
||||
u32 last_timestamp_user{};
|
||||
u32 last_timestamp_network{};
|
||||
u32 play_time_in_minutes{};
|
||||
u32 total_launches{};
|
||||
};
|
||||
static_assert(sizeof(PlayStatistics) == 0x28, "PlayStatistics is an invalid size");
|
||||
|
||||
class IQueryService final : public ServiceFramework<IQueryService> {
|
||||
public:
|
||||
explicit IQueryService(Core::System& system_);
|
||||
~IQueryService() override;
|
||||
|
||||
private:
|
||||
Result QueryPlayStatisticsByApplicationIdAndUserAccountId(
|
||||
Out<PlayStatistics> out_play_statistics, bool unknown, Common::UUID account_id,
|
||||
u64 application_id);
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
122
src/core/hle/service/ns/read_only_application_control_data_interface.cpp
Executable file
122
src/core/hle/service/ns/read_only_application_control_data_interface.cpp
Executable file
@ -0,0 +1,122 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/settings.h"
|
||||
#include "core/file_sys/control_metadata.h"
|
||||
#include "core/file_sys/patch_manager.h"
|
||||
#include "core/file_sys/vfs/vfs.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ns/language.h"
|
||||
#include "core/hle/service/ns/ns_results.h"
|
||||
#include "core/hle/service/ns/read_only_application_control_data_interface.h"
|
||||
#include "core/hle/service/set/settings_server.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterface(
|
||||
Core::System& system_)
|
||||
: ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlData>, "GetApplicationControlData"},
|
||||
{1, D<&IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage>, "GetApplicationDesiredLanguage"},
|
||||
{2, D<&IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLanguageCode>, "ConvertApplicationLanguageToLanguageCode"},
|
||||
{3, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
|
||||
{4, nullptr, "SelectApplicationDesiredLanguage"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default;
|
||||
|
||||
Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData(
|
||||
OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size,
|
||||
ApplicationControlSource application_control_source, u64 application_id) {
|
||||
LOG_INFO(Service_NS, "called with control_source={}, application_id={:016X}",
|
||||
application_control_source, application_id);
|
||||
|
||||
const FileSys::PatchManager pm{application_id, system.GetFileSystemController(),
|
||||
system.GetContentProvider()};
|
||||
const auto control = pm.GetControlMetadata();
|
||||
const auto size = out_buffer.size();
|
||||
|
||||
const auto icon_size = control.second ? control.second->GetSize() : 0;
|
||||
const auto total_size = 0x4000 + icon_size;
|
||||
|
||||
if (size < total_size) {
|
||||
LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, expected_min=0x4000)",
|
||||
size);
|
||||
R_THROW(ResultUnknown);
|
||||
}
|
||||
|
||||
if (control.first != nullptr) {
|
||||
const auto bytes = control.first->GetRawBytes();
|
||||
std::memcpy(out_buffer.data(), bytes.data(), bytes.size());
|
||||
} else {
|
||||
LOG_WARNING(Service_NS, "missing NACP data for application_id={:016X}, defaulting to zero",
|
||||
application_id);
|
||||
std::memset(out_buffer.data(), 0, 0x4000);
|
||||
}
|
||||
|
||||
if (control.second != nullptr) {
|
||||
control.second->Read(out_buffer.data() + 0x4000, icon_size);
|
||||
} else {
|
||||
LOG_WARNING(Service_NS, "missing icon data for application_id={:016X}", application_id);
|
||||
}
|
||||
|
||||
*out_actual_size = static_cast<u32>(total_size);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage(
|
||||
Out<ApplicationLanguage> out_desired_language, u32 supported_languages) {
|
||||
LOG_INFO(Service_NS, "called with supported_languages={:08X}", supported_languages);
|
||||
|
||||
// Get language code from settings
|
||||
const auto language_code =
|
||||
Set::GetLanguageCodeFromIndex(static_cast<s32>(Settings::values.language_index.GetValue()));
|
||||
|
||||
// Convert to application language, get priority list
|
||||
const auto application_language = ConvertToApplicationLanguage(language_code);
|
||||
if (application_language == std::nullopt) {
|
||||
LOG_ERROR(Service_NS, "Could not convert application language! language_code={}",
|
||||
language_code);
|
||||
R_THROW(Service::NS::ResultApplicationLanguageNotFound);
|
||||
}
|
||||
const auto priority_list = GetApplicationLanguagePriorityList(*application_language);
|
||||
if (!priority_list) {
|
||||
LOG_ERROR(Service_NS,
|
||||
"Could not find application language priorities! application_language={}",
|
||||
*application_language);
|
||||
R_THROW(Service::NS::ResultApplicationLanguageNotFound);
|
||||
}
|
||||
|
||||
// Try to find a valid language.
|
||||
for (const auto lang : *priority_list) {
|
||||
const auto supported_flag = GetSupportedLanguageFlag(lang);
|
||||
if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) {
|
||||
*out_desired_language = lang;
|
||||
R_SUCCEED();
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERROR(Service_NS, "Could not find a valid language! supported_languages={:08X}",
|
||||
supported_languages);
|
||||
R_THROW(Service::NS::ResultApplicationLanguageNotFound);
|
||||
}
|
||||
|
||||
Result IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLanguageCode(
|
||||
Out<u64> out_language_code, ApplicationLanguage application_language) {
|
||||
const auto language_code = ConvertToLanguageCode(application_language);
|
||||
if (language_code == std::nullopt) {
|
||||
LOG_ERROR(Service_NS, "Language not found! application_language={}", application_language);
|
||||
R_THROW(Service::NS::ResultApplicationLanguageNotFound);
|
||||
}
|
||||
|
||||
*out_language_code = static_cast<u64>(*language_code);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::NS
|
30
src/core/hle/service/ns/read_only_application_control_data_interface.h
Executable file
30
src/core/hle/service/ns/read_only_application_control_data_interface.h
Executable file
@ -0,0 +1,30 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ns/language.h"
|
||||
#include "core/hle/service/ns/ns_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
class IReadOnlyApplicationControlDataInterface final
|
||||
: public ServiceFramework<IReadOnlyApplicationControlDataInterface> {
|
||||
public:
|
||||
explicit IReadOnlyApplicationControlDataInterface(Core::System& system_);
|
||||
~IReadOnlyApplicationControlDataInterface() override;
|
||||
|
||||
public:
|
||||
Result GetApplicationControlData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
|
||||
Out<u32> out_actual_size,
|
||||
ApplicationControlSource application_control_source,
|
||||
u64 application_id);
|
||||
Result GetApplicationDesiredLanguage(Out<ApplicationLanguage> out_desired_language,
|
||||
u32 supported_languages);
|
||||
Result ConvertApplicationLanguageToLanguageCode(Out<u64> out_language_code,
|
||||
ApplicationLanguage application_language);
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
38
src/core/hle/service/ns/read_only_application_record_interface.cpp
Executable file
38
src/core/hle/service/ns/read_only_application_record_interface.cpp
Executable file
@ -0,0 +1,38 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ns/read_only_application_record_interface.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
IReadOnlyApplicationRecordInterface::IReadOnlyApplicationRecordInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "IReadOnlyApplicationRecordInterface"} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IReadOnlyApplicationRecordInterface::HasApplicationRecord>, "HasApplicationRecord"},
|
||||
{1, nullptr, "NotifyApplicationFailure"},
|
||||
{2, D<&IReadOnlyApplicationRecordInterface::IsDataCorruptedResult>,
|
||||
"IsDataCorruptedResult"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IReadOnlyApplicationRecordInterface::~IReadOnlyApplicationRecordInterface() = default;
|
||||
|
||||
Result IReadOnlyApplicationRecordInterface::HasApplicationRecord(
|
||||
Out<bool> out_has_application_record, u64 program_id) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called, program_id={:016X}", program_id);
|
||||
*out_has_application_record = true;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IReadOnlyApplicationRecordInterface::IsDataCorruptedResult(
|
||||
Out<bool> out_is_data_corrupted_result, Result result) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called, result={:#x}", result.GetInnerValue());
|
||||
*out_is_data_corrupted_result = false;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::NS
|
22
src/core/hle/service/ns/read_only_application_record_interface.h
Executable file
22
src/core/hle/service/ns/read_only_application_record_interface.h
Executable file
@ -0,0 +1,22 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
class IReadOnlyApplicationRecordInterface final
|
||||
: public ServiceFramework<IReadOnlyApplicationRecordInterface> {
|
||||
public:
|
||||
explicit IReadOnlyApplicationRecordInterface(Core::System& system_);
|
||||
~IReadOnlyApplicationRecordInterface() override;
|
||||
|
||||
private:
|
||||
Result HasApplicationRecord(Out<bool> out_has_application_record, u64 program_id);
|
||||
Result IsDataCorruptedResult(Out<bool> out_is_data_corrupted_result, Result result);
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
120
src/core/hle/service/ns/service_getter_interface.cpp
Executable file
120
src/core/hle/service/ns/service_getter_interface.cpp
Executable file
@ -0,0 +1,120 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ns/account_proxy_interface.h"
|
||||
#include "core/hle/service/ns/application_manager_interface.h"
|
||||
#include "core/hle/service/ns/application_version_interface.h"
|
||||
#include "core/hle/service/ns/content_management_interface.h"
|
||||
#include "core/hle/service/ns/document_interface.h"
|
||||
#include "core/hle/service/ns/download_task_interface.h"
|
||||
#include "core/hle/service/ns/dynamic_rights_interface.h"
|
||||
#include "core/hle/service/ns/ecommerce_interface.h"
|
||||
#include "core/hle/service/ns/factory_reset_interface.h"
|
||||
#include "core/hle/service/ns/read_only_application_control_data_interface.h"
|
||||
#include "core/hle/service/ns/read_only_application_record_interface.h"
|
||||
#include "core/hle/service/ns/service_getter_interface.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
IServiceGetterInterface::IServiceGetterInterface(Core::System& system_, const char* name)
|
||||
: ServiceFramework{system_, name} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{7988, D<&IServiceGetterInterface::GetDynamicRightsInterface>, "GetDynamicRightsInterface"},
|
||||
{7989, D<&IServiceGetterInterface::GetReadOnlyApplicationControlDataInterface>, "GetReadOnlyApplicationControlDataInterface"},
|
||||
{7991, D<&IServiceGetterInterface::GetReadOnlyApplicationRecordInterface>, "GetReadOnlyApplicationRecordInterface"},
|
||||
{7992, D<&IServiceGetterInterface::GetECommerceInterface>, "GetECommerceInterface"},
|
||||
{7993, D<&IServiceGetterInterface::GetApplicationVersionInterface>, "GetApplicationVersionInterface"},
|
||||
{7994, D<&IServiceGetterInterface::GetFactoryResetInterface>, "GetFactoryResetInterface"},
|
||||
{7995, D<&IServiceGetterInterface::GetAccountProxyInterface>, "GetAccountProxyInterface"},
|
||||
{7996, D<&IServiceGetterInterface::GetApplicationManagerInterface>, "GetApplicationManagerInterface"},
|
||||
{7997, D<&IServiceGetterInterface::GetDownloadTaskInterface>, "GetDownloadTaskInterface"},
|
||||
{7998, D<&IServiceGetterInterface::GetContentManagementInterface>, "GetContentManagementInterface"},
|
||||
{7999, D<&IServiceGetterInterface::GetDocumentInterface>, "GetDocumentInterface"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IServiceGetterInterface::~IServiceGetterInterface() = default;
|
||||
|
||||
Result IServiceGetterInterface::GetDynamicRightsInterface(
|
||||
Out<SharedPointer<IDynamicRightsInterface>> out_interface) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
*out_interface = std::make_shared<IDynamicRightsInterface>(system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IServiceGetterInterface::GetReadOnlyApplicationControlDataInterface(
|
||||
Out<SharedPointer<IReadOnlyApplicationControlDataInterface>> out_interface) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
*out_interface = std::make_shared<IReadOnlyApplicationControlDataInterface>(system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IServiceGetterInterface::GetReadOnlyApplicationRecordInterface(
|
||||
Out<SharedPointer<IReadOnlyApplicationRecordInterface>> out_interface) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
*out_interface = std::make_shared<IReadOnlyApplicationRecordInterface>(system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IServiceGetterInterface::GetECommerceInterface(
|
||||
Out<SharedPointer<IECommerceInterface>> out_interface) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
*out_interface = std::make_shared<IECommerceInterface>(system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IServiceGetterInterface::GetApplicationVersionInterface(
|
||||
Out<SharedPointer<IApplicationVersionInterface>> out_interface) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
*out_interface = std::make_shared<IApplicationVersionInterface>(system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IServiceGetterInterface::GetFactoryResetInterface(
|
||||
Out<SharedPointer<IFactoryResetInterface>> out_interface) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
*out_interface = std::make_shared<IFactoryResetInterface>(system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IServiceGetterInterface::GetAccountProxyInterface(
|
||||
Out<SharedPointer<IAccountProxyInterface>> out_interface) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
*out_interface = std::make_shared<IAccountProxyInterface>(system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IServiceGetterInterface::GetApplicationManagerInterface(
|
||||
Out<SharedPointer<IApplicationManagerInterface>> out_interface) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
*out_interface = std::make_shared<IApplicationManagerInterface>(system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IServiceGetterInterface::GetDownloadTaskInterface(
|
||||
Out<SharedPointer<IDownloadTaskInterface>> out_interface) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
*out_interface = std::make_shared<IDownloadTaskInterface>(system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IServiceGetterInterface::GetContentManagementInterface(
|
||||
Out<SharedPointer<IContentManagementInterface>> out_interface) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
*out_interface = std::make_shared<IContentManagementInterface>(system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IServiceGetterInterface::GetDocumentInterface(
|
||||
Out<SharedPointer<IDocumentInterface>> out_interface) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
*out_interface = std::make_shared<IDocumentInterface>(system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::NS
|
47
src/core/hle/service/ns/service_getter_interface.h
Executable file
47
src/core/hle/service/ns/service_getter_interface.h
Executable file
@ -0,0 +1,47 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
class IDynamicRightsInterface;
|
||||
class IReadOnlyApplicationControlDataInterface;
|
||||
class IReadOnlyApplicationRecordInterface;
|
||||
class IECommerceInterface;
|
||||
class IApplicationVersionInterface;
|
||||
class IFactoryResetInterface;
|
||||
class IAccountProxyInterface;
|
||||
class IApplicationManagerInterface;
|
||||
class IDownloadTaskInterface;
|
||||
class IContentManagementInterface;
|
||||
class IDocumentInterface;
|
||||
|
||||
class IServiceGetterInterface : public ServiceFramework<IServiceGetterInterface> {
|
||||
public:
|
||||
explicit IServiceGetterInterface(Core::System& system_, const char* name);
|
||||
~IServiceGetterInterface() override;
|
||||
|
||||
public:
|
||||
Result GetDynamicRightsInterface(Out<SharedPointer<IDynamicRightsInterface>> out_interface);
|
||||
Result GetReadOnlyApplicationControlDataInterface(
|
||||
Out<SharedPointer<IReadOnlyApplicationControlDataInterface>> out_interface);
|
||||
Result GetReadOnlyApplicationRecordInterface(
|
||||
Out<SharedPointer<IReadOnlyApplicationRecordInterface>> out_interface);
|
||||
Result GetECommerceInterface(Out<SharedPointer<IECommerceInterface>> out_interface);
|
||||
Result GetApplicationVersionInterface(
|
||||
Out<SharedPointer<IApplicationVersionInterface>> out_interface);
|
||||
Result GetFactoryResetInterface(Out<SharedPointer<IFactoryResetInterface>> out_interface);
|
||||
Result GetAccountProxyInterface(Out<SharedPointer<IAccountProxyInterface>> out_interface);
|
||||
Result GetApplicationManagerInterface(
|
||||
Out<SharedPointer<IApplicationManagerInterface>> out_interface);
|
||||
Result GetDownloadTaskInterface(Out<SharedPointer<IDownloadTaskInterface>> out_interface);
|
||||
Result GetContentManagementInterface(
|
||||
Out<SharedPointer<IContentManagementInterface>> out_interface);
|
||||
Result GetDocumentInterface(Out<SharedPointer<IDocumentInterface>> out_interface);
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
44
src/core/hle/service/ns/system_update_control.cpp
Executable file
44
src/core/hle/service/ns/system_update_control.cpp
Executable file
@ -0,0 +1,44 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ns/system_update_control.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
ISystemUpdateControl::ISystemUpdateControl(Core::System& system_)
|
||||
: ServiceFramework{system_, "ISystemUpdateControl"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "HasDownloaded"},
|
||||
{1, nullptr, "RequestCheckLatestUpdate"},
|
||||
{2, nullptr, "RequestDownloadLatestUpdate"},
|
||||
{3, nullptr, "GetDownloadProgress"},
|
||||
{4, nullptr, "ApplyDownloadedUpdate"},
|
||||
{5, nullptr, "RequestPrepareCardUpdate"},
|
||||
{6, nullptr, "GetPrepareCardUpdateProgress"},
|
||||
{7, nullptr, "HasPreparedCardUpdate"},
|
||||
{8, nullptr, "ApplyCardUpdate"},
|
||||
{9, nullptr, "GetDownloadedEulaDataSize"},
|
||||
{10, nullptr, "GetDownloadedEulaData"},
|
||||
{11, nullptr, "SetupCardUpdate"},
|
||||
{12, nullptr, "GetPreparedCardUpdateEulaDataSize"},
|
||||
{13, nullptr, "GetPreparedCardUpdateEulaData"},
|
||||
{14, nullptr, "SetupCardUpdateViaSystemUpdater"},
|
||||
{15, nullptr, "HasReceived"},
|
||||
{16, nullptr, "RequestReceiveSystemUpdate"},
|
||||
{17, nullptr, "GetReceiveProgress"},
|
||||
{18, nullptr, "ApplyReceivedUpdate"},
|
||||
{19, nullptr, "GetReceivedEulaDataSize"},
|
||||
{20, nullptr, "GetReceivedEulaData"},
|
||||
{21, nullptr, "SetupToReceiveSystemUpdate"},
|
||||
{22, nullptr, "RequestCheckLatestUpdateIncludesRebootlessUpdate"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
ISystemUpdateControl::~ISystemUpdateControl() = default;
|
||||
|
||||
} // namespace Service::NS
|
16
src/core/hle/service/ns/system_update_control.h
Executable file
16
src/core/hle/service/ns/system_update_control.h
Executable file
@ -0,0 +1,16 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
class ISystemUpdateControl final : public ServiceFramework<ISystemUpdateControl> {
|
||||
public:
|
||||
explicit ISystemUpdateControl(Core::System& system_);
|
||||
~ISystemUpdateControl() override;
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
61
src/core/hle/service/ns/system_update_interface.cpp
Executable file
61
src/core/hle/service/ns/system_update_interface.cpp
Executable file
@ -0,0 +1,61 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ns/system_update_control.h"
|
||||
#include "core/hle/service/ns/system_update_interface.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
ISystemUpdateInterface::ISystemUpdateInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "ns:su"}, service_context{system_, "ns:su"},
|
||||
update_notification_event{service_context} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&ISystemUpdateInterface::GetBackgroundNetworkUpdateState>, "GetBackgroundNetworkUpdateState"},
|
||||
{1, D<&ISystemUpdateInterface::OpenSystemUpdateControl>, "OpenSystemUpdateControl"},
|
||||
{2, nullptr, "NotifyExFatDriverRequired"},
|
||||
{3, nullptr, "ClearExFatDriverStatusForDebug"},
|
||||
{4, nullptr, "RequestBackgroundNetworkUpdate"},
|
||||
{5, nullptr, "NotifyBackgroundNetworkUpdate"},
|
||||
{6, nullptr, "NotifyExFatDriverDownloadedForDebug"},
|
||||
{9, D<&ISystemUpdateInterface::GetSystemUpdateNotificationEventForContentDelivery>, "GetSystemUpdateNotificationEventForContentDelivery"},
|
||||
{10, nullptr, "NotifySystemUpdateForContentDelivery"},
|
||||
{11, nullptr, "PrepareShutdown"},
|
||||
{12, nullptr, "Unknown12"},
|
||||
{13, nullptr, "Unknown13"},
|
||||
{14, nullptr, "Unknown14"},
|
||||
{15, nullptr, "Unknown15"},
|
||||
{16, nullptr, "DestroySystemUpdateTask"},
|
||||
{17, nullptr, "RequestSendSystemUpdate"},
|
||||
{18, nullptr, "GetSendSystemUpdateProgress"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
ISystemUpdateInterface::~ISystemUpdateInterface() = default;
|
||||
|
||||
Result ISystemUpdateInterface::GetBackgroundNetworkUpdateState(
|
||||
Out<BackgroundNetworkUpdateState> out_background_network_update_state) {
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||
*out_background_network_update_state = BackgroundNetworkUpdateState::None;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISystemUpdateInterface::OpenSystemUpdateControl(
|
||||
Out<SharedPointer<ISystemUpdateControl>> out_system_update_control) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called");
|
||||
*out_system_update_control = std::make_shared<ISystemUpdateControl>(system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISystemUpdateInterface::GetSystemUpdateNotificationEventForContentDelivery(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called");
|
||||
*out_event = update_notification_event.GetHandle();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::NS
|
38
src/core/hle/service/ns/system_update_interface.h
Executable file
38
src/core/hle/service/ns/system_update_interface.h
Executable file
@ -0,0 +1,38 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/hle/service/ns/ns_types.h"
|
||||
#include "core/hle/service/os/event.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Kernel {
|
||||
class KReadableEvent;
|
||||
}
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
class ISystemUpdateControl;
|
||||
|
||||
class ISystemUpdateInterface final : public ServiceFramework<ISystemUpdateInterface> {
|
||||
public:
|
||||
explicit ISystemUpdateInterface(Core::System& system_);
|
||||
~ISystemUpdateInterface() override;
|
||||
|
||||
private:
|
||||
Result GetBackgroundNetworkUpdateState(
|
||||
Out<BackgroundNetworkUpdateState> out_background_network_update_state);
|
||||
Result OpenSystemUpdateControl(
|
||||
Out<SharedPointer<ISystemUpdateControl>> out_system_update_control);
|
||||
Result GetSystemUpdateNotificationEventForContentDelivery(
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
|
||||
private:
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
Event update_notification_event;
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
31
src/core/hle/service/ns/vulnerability_manager_interface.cpp
Executable file
31
src/core/hle/service/ns/vulnerability_manager_interface.cpp
Executable file
@ -0,0 +1,31 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ns/vulnerability_manager_interface.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
IVulnerabilityManagerInterface::IVulnerabilityManagerInterface(Core::System& system_)
|
||||
: ServiceFramework{system_, "ns:vm"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{1200, D<&IVulnerabilityManagerInterface::NeedsUpdateVulnerability>, "NeedsUpdateVulnerability"},
|
||||
{1201, nullptr, "UpdateSafeSystemVersionForDebug"},
|
||||
{1202, nullptr, "GetSafeSystemVersion"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IVulnerabilityManagerInterface::~IVulnerabilityManagerInterface() = default;
|
||||
|
||||
Result IVulnerabilityManagerInterface::NeedsUpdateVulnerability(
|
||||
Out<bool> out_needs_update_vulnerability) {
|
||||
LOG_WARNING(Service_NS, "(STUBBED) called");
|
||||
*out_needs_update_vulnerability = false;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::NS
|
21
src/core/hle/service/ns/vulnerability_manager_interface.h
Executable file
21
src/core/hle/service/ns/vulnerability_manager_interface.h
Executable file
@ -0,0 +1,21 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
class IVulnerabilityManagerInterface final
|
||||
: public ServiceFramework<IVulnerabilityManagerInterface> {
|
||||
public:
|
||||
explicit IVulnerabilityManagerInterface(Core::System& system_);
|
||||
~IVulnerabilityManagerInterface() override;
|
||||
|
||||
private:
|
||||
Result NeedsUpdateVulnerability(Out<bool> out_needs_update_vulnerability);
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
@ -42,7 +42,7 @@ void EventInterface::FreeEvent(Kernel::KEvent* event) {
|
||||
module.service_context.CloseEvent(event);
|
||||
}
|
||||
|
||||
void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
|
||||
void LoopProcess(Core::System& system) {
|
||||
auto server_manager = std::make_unique<ServerManager>(system);
|
||||
auto module = std::make_shared<Module>(system);
|
||||
const auto NvdrvInterfaceFactoryForApplication = [&, module] {
|
||||
@ -62,7 +62,6 @@ void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
|
||||
server_manager->RegisterNamedService("nvdrv:s", NvdrvInterfaceFactoryForSysmodules);
|
||||
server_manager->RegisterNamedService("nvdrv:t", NvdrvInterfaceFactoryForTesting);
|
||||
server_manager->RegisterNamedService("nvmemp", std::make_shared<NVMEMP>(system));
|
||||
nvnflinger.SetNVDrvInstance(module);
|
||||
ServerManager::RunServer(std::move(server_manager));
|
||||
}
|
||||
|
||||
|
@ -10,13 +10,11 @@
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/hle/service/nvdrv/core/container.h"
|
||||
#include "core/hle/service/nvdrv/nvdata.h"
|
||||
#include "core/hle/service/nvnflinger/ui/fence.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Core {
|
||||
@ -27,10 +25,6 @@ namespace Kernel {
|
||||
class KEvent;
|
||||
}
|
||||
|
||||
namespace Service::Nvnflinger {
|
||||
class Nvnflinger;
|
||||
}
|
||||
|
||||
namespace Service::Nvidia {
|
||||
|
||||
namespace NvCore {
|
||||
@ -99,7 +93,6 @@ public:
|
||||
|
||||
private:
|
||||
friend class EventInterface;
|
||||
friend class Service::Nvnflinger::Nvnflinger;
|
||||
|
||||
/// Manages syncpoints on the host
|
||||
NvCore::Container container;
|
||||
@ -118,6 +111,6 @@ private:
|
||||
std::unordered_map<std::string, std::function<FilesContainerType::iterator(DeviceFD)>> builders;
|
||||
};
|
||||
|
||||
void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system);
|
||||
void LoopProcess(Core::System& system);
|
||||
|
||||
} // namespace Service::Nvidia
|
||||
|
@ -263,8 +263,10 @@ NVDRV::NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char*
|
||||
}
|
||||
|
||||
NVDRV::~NVDRV() {
|
||||
if (is_initialized) {
|
||||
auto& container = nvdrv->GetContainer();
|
||||
container.CloseSession(session_id);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Service::Nvidia
|
||||
|
@ -16,6 +16,10 @@ public:
|
||||
explicit NVDRV(Core::System& system_, std::shared_ptr<Module> nvdrv_, const char* name);
|
||||
~NVDRV() override;
|
||||
|
||||
std::shared_ptr<Module> GetModule() const {
|
||||
return nvdrv;
|
||||
}
|
||||
|
||||
private:
|
||||
void Open(HLERequestContext& ctx);
|
||||
void Ioctl1(HLERequestContext& ctx);
|
||||
|
@ -20,29 +20,12 @@ class HLERequestContext;
|
||||
|
||||
namespace Service::android {
|
||||
|
||||
enum class TransactionId {
|
||||
RequestBuffer = 1,
|
||||
SetBufferCount = 2,
|
||||
DequeueBuffer = 3,
|
||||
DetachBuffer = 4,
|
||||
DetachNextBuffer = 5,
|
||||
AttachBuffer = 6,
|
||||
QueueBuffer = 7,
|
||||
CancelBuffer = 8,
|
||||
Query = 9,
|
||||
Connect = 10,
|
||||
Disconnect = 11,
|
||||
AllocateBuffers = 13,
|
||||
SetPreallocatedBuffer = 14,
|
||||
GetBufferHistory = 17,
|
||||
};
|
||||
|
||||
class IBinder {
|
||||
public:
|
||||
virtual ~IBinder() = default;
|
||||
virtual void Transact(android::TransactionId code, u32 flags, std::span<const u8> parcel_data,
|
||||
std::span<u8> parcel_reply) = 0;
|
||||
virtual Kernel::KReadableEvent& GetNativeHandle() = 0;
|
||||
virtual void Transact(u32 code, std::span<const u8> parcel_data, std::span<u8> parcel_reply,
|
||||
u32 flags) = 0;
|
||||
virtual Kernel::KReadableEvent* GetNativeHandle(u32 type_id) = 0;
|
||||
};
|
||||
|
||||
} // namespace Service::android
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
namespace Service::android {
|
||||
|
||||
BufferItemConsumer::BufferItemConsumer(std::unique_ptr<BufferQueueConsumer> consumer_)
|
||||
BufferItemConsumer::BufferItemConsumer(std::shared_ptr<BufferQueueConsumer> consumer_)
|
||||
: ConsumerBase{std::move(consumer_)} {}
|
||||
|
||||
Status BufferItemConsumer::AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when,
|
||||
|
@ -19,7 +19,7 @@ class BufferItem;
|
||||
|
||||
class BufferItemConsumer final : public ConsumerBase {
|
||||
public:
|
||||
explicit BufferItemConsumer(std::unique_ptr<BufferQueueConsumer> consumer);
|
||||
explicit BufferItemConsumer(std::shared_ptr<BufferQueueConsumer> consumer);
|
||||
Status AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when,
|
||||
bool wait_for_fence = true);
|
||||
Status ReleaseBuffer(const BufferItem& item, const Fence& release_fence);
|
||||
|
@ -4,12 +4,13 @@
|
||||
// Parts of this implementation were based on:
|
||||
// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/service/nvnflinger/buffer_item.h"
|
||||
#include "core/hle/service/nvnflinger/buffer_queue_consumer.h"
|
||||
#include "core/hle/service/nvnflinger/buffer_queue_core.h"
|
||||
#include "core/hle/service/nvnflinger/parcel.h"
|
||||
#include "core/hle/service/nvnflinger/producer_listener.h"
|
||||
#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
|
||||
|
||||
namespace Service::android {
|
||||
|
||||
@ -254,4 +255,77 @@ Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) {
|
||||
return Status::NoError;
|
||||
}
|
||||
|
||||
void BufferQueueConsumer::Transact(u32 code, std::span<const u8> parcel_data,
|
||||
std::span<u8> parcel_reply, u32 flags) {
|
||||
// Values used by BnGraphicBufferConsumer onTransact
|
||||
enum class TransactionId {
|
||||
AcquireBuffer = 1,
|
||||
DetachBuffer = 2,
|
||||
AttachBuffer = 3,
|
||||
ReleaseBuffer = 4,
|
||||
ConsumerConnect = 5,
|
||||
ConsumerDisconnect = 6,
|
||||
GetReleasedBuffers = 7,
|
||||
SetDefaultBufferSize = 8,
|
||||
SetDefaultMaxBufferCount = 9,
|
||||
DisableAsyncBuffer = 10,
|
||||
SetMaxAcquiredBufferCount = 11,
|
||||
SetConsumerName = 12,
|
||||
SetDefaultBufferFormat = 13,
|
||||
SetConsumerUsageBits = 14,
|
||||
SetTransformHint = 15,
|
||||
GetSidebandStream = 16,
|
||||
Unknown18 = 18,
|
||||
Unknown20 = 20,
|
||||
};
|
||||
|
||||
Status status{Status::NoError};
|
||||
InputParcel parcel_in{parcel_data};
|
||||
OutputParcel parcel_out{};
|
||||
|
||||
switch (static_cast<TransactionId>(code)) {
|
||||
case TransactionId::AcquireBuffer: {
|
||||
BufferItem item;
|
||||
const s64 present_when = parcel_in.Read<s64>();
|
||||
|
||||
status = AcquireBuffer(&item, std::chrono::nanoseconds{present_when});
|
||||
|
||||
// TODO: can't write this directly, needs a flattener for the sp<GraphicBuffer>
|
||||
// parcel_out.WriteFlattened(item);
|
||||
UNREACHABLE();
|
||||
}
|
||||
case TransactionId::ReleaseBuffer: {
|
||||
const s32 slot = parcel_in.Read<s32>();
|
||||
const u64 frame_number = parcel_in.Read<u64>();
|
||||
const auto release_fence = parcel_in.ReadFlattened<Fence>();
|
||||
|
||||
status = ReleaseBuffer(slot, frame_number, release_fence);
|
||||
|
||||
break;
|
||||
}
|
||||
case TransactionId::GetReleasedBuffers: {
|
||||
u64 slot_mask = 0;
|
||||
|
||||
status = GetReleasedBuffers(&slot_mask);
|
||||
|
||||
parcel_out.Write(slot_mask);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ASSERT_MSG(false, "called, code={} flags={}", code, flags);
|
||||
break;
|
||||
}
|
||||
|
||||
parcel_out.Write(status);
|
||||
|
||||
const auto serialized = parcel_out.Serialize();
|
||||
std::memcpy(parcel_reply.data(), serialized.data(),
|
||||
std::min(parcel_reply.size(), serialized.size()));
|
||||
}
|
||||
|
||||
Kernel::KReadableEvent* BufferQueueConsumer::GetNativeHandle(u32 type_id) {
|
||||
ASSERT_MSG(false, "called, type_id={}", type_id);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace Service::android
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/service/nvnflinger/binder.h"
|
||||
#include "core/hle/service/nvnflinger/buffer_queue_defs.h"
|
||||
#include "core/hle/service/nvnflinger/status.h"
|
||||
|
||||
@ -19,10 +20,10 @@ class BufferItem;
|
||||
class BufferQueueCore;
|
||||
class IConsumerListener;
|
||||
|
||||
class BufferQueueConsumer final {
|
||||
class BufferQueueConsumer final : public IBinder {
|
||||
public:
|
||||
explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_);
|
||||
~BufferQueueConsumer();
|
||||
~BufferQueueConsumer() override;
|
||||
|
||||
Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present);
|
||||
Status ReleaseBuffer(s32 slot, u64 frame_number, const Fence& release_fence);
|
||||
@ -30,6 +31,11 @@ public:
|
||||
Status Disconnect();
|
||||
Status GetReleasedBuffers(u64* out_slot_mask);
|
||||
|
||||
void Transact(u32 code, std::span<const u8> parcel_data, std::span<u8> parcel_reply,
|
||||
u32 flags) override;
|
||||
|
||||
Kernel::KReadableEvent* GetNativeHandle(u32 type_id) override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<BufferQueueCore> core;
|
||||
BufferQueueDefs::SlotsType& slots;
|
||||
|
@ -6,12 +6,9 @@
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/settings.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/k_event.h"
|
||||
#include "core/hle/kernel/k_readable_event.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/service/hle_ipc.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/hle/service/nvnflinger/buffer_queue_core.h"
|
||||
#include "core/hle/service/nvnflinger/buffer_queue_producer.h"
|
||||
@ -19,7 +16,6 @@
|
||||
#include "core/hle/service/nvnflinger/parcel.h"
|
||||
#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
|
||||
#include "core/hle/service/nvnflinger/window.h"
|
||||
#include "core/hle/service/vi/vi.h"
|
||||
|
||||
namespace Service::android {
|
||||
|
||||
@ -807,13 +803,31 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot,
|
||||
return Status::NoError;
|
||||
}
|
||||
|
||||
void BufferQueueProducer::Transact(TransactionId code, u32 flags, std::span<const u8> parcel_data,
|
||||
std::span<u8> parcel_reply) {
|
||||
void BufferQueueProducer::Transact(u32 code, std::span<const u8> parcel_data,
|
||||
std::span<u8> parcel_reply, u32 flags) {
|
||||
// Values used by BnGraphicBufferProducer onTransact
|
||||
enum class TransactionId {
|
||||
RequestBuffer = 1,
|
||||
SetBufferCount = 2,
|
||||
DequeueBuffer = 3,
|
||||
DetachBuffer = 4,
|
||||
DetachNextBuffer = 5,
|
||||
AttachBuffer = 6,
|
||||
QueueBuffer = 7,
|
||||
CancelBuffer = 8,
|
||||
Query = 9,
|
||||
Connect = 10,
|
||||
Disconnect = 11,
|
||||
AllocateBuffers = 13,
|
||||
SetPreallocatedBuffer = 14,
|
||||
GetBufferHistory = 17,
|
||||
};
|
||||
|
||||
Status status{Status::NoError};
|
||||
InputParcel parcel_in{parcel_data};
|
||||
OutputParcel parcel_out{};
|
||||
|
||||
switch (code) {
|
||||
switch (static_cast<TransactionId>(code)) {
|
||||
case TransactionId::Connect: {
|
||||
const auto enable_listener = parcel_in.Read<bool>();
|
||||
const auto api = parcel_in.Read<NativeWindowApi>();
|
||||
@ -923,8 +937,8 @@ void BufferQueueProducer::Transact(TransactionId code, u32 flags, std::span<cons
|
||||
std::min(parcel_reply.size(), serialized.size()));
|
||||
}
|
||||
|
||||
Kernel::KReadableEvent& BufferQueueProducer::GetNativeHandle() {
|
||||
return buffer_wait_event->GetReadableEvent();
|
||||
Kernel::KReadableEvent* BufferQueueProducer::GetNativeHandle(u32 type_id) {
|
||||
return &buffer_wait_event->GetReadableEvent();
|
||||
}
|
||||
|
||||
} // namespace Service::android
|
||||
|
@ -45,12 +45,12 @@ public:
|
||||
explicit BufferQueueProducer(Service::KernelHelpers::ServiceContext& service_context_,
|
||||
std::shared_ptr<BufferQueueCore> buffer_queue_core_,
|
||||
Service::Nvidia::NvCore::NvMap& nvmap_);
|
||||
~BufferQueueProducer();
|
||||
~BufferQueueProducer() override;
|
||||
|
||||
void Transact(android::TransactionId code, u32 flags, std::span<const u8> parcel_data,
|
||||
std::span<u8> parcel_reply) override;
|
||||
void Transact(u32 code, std::span<const u8> parcel_data, std::span<u8> parcel_reply,
|
||||
u32 flags) override;
|
||||
|
||||
Kernel::KReadableEvent& GetNativeHandle() override;
|
||||
Kernel::KReadableEvent* GetNativeHandle(u32 type_id) override;
|
||||
|
||||
public:
|
||||
Status RequestBuffer(s32 slot, std::shared_ptr<GraphicBuffer>* buf);
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
namespace Service::android {
|
||||
|
||||
ConsumerBase::ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_)
|
||||
ConsumerBase::ConsumerBase(std::shared_ptr<BufferQueueConsumer> consumer_)
|
||||
: consumer{std::move(consumer_)} {}
|
||||
|
||||
ConsumerBase::~ConsumerBase() {
|
||||
|
@ -27,7 +27,7 @@ public:
|
||||
void Abandon();
|
||||
|
||||
protected:
|
||||
explicit ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_);
|
||||
explicit ConsumerBase(std::shared_ptr<BufferQueueConsumer> consumer_);
|
||||
~ConsumerBase() override;
|
||||
|
||||
void OnFrameAvailable(const BufferItem& item) override;
|
||||
@ -54,7 +54,7 @@ protected:
|
||||
|
||||
bool is_abandoned{};
|
||||
|
||||
std::unique_ptr<BufferQueueConsumer> consumer;
|
||||
std::shared_ptr<BufferQueueConsumer> consumer;
|
||||
|
||||
mutable std::mutex mutex;
|
||||
};
|
||||
|
51
src/core/hle/service/nvnflinger/display.h
Executable file
51
src/core/hle/service/nvnflinger/display.h
Executable file
@ -0,0 +1,51 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "core/hle/service/nvnflinger/buffer_item_consumer.h"
|
||||
#include "core/hle/service/nvnflinger/hwc_layer.h"
|
||||
|
||||
namespace Service::Nvnflinger {
|
||||
|
||||
struct Layer {
|
||||
explicit Layer(std::shared_ptr<android::BufferItemConsumer> buffer_item_consumer_,
|
||||
s32 consumer_id_)
|
||||
: buffer_item_consumer(std::move(buffer_item_consumer_)), consumer_id(consumer_id_),
|
||||
blending(LayerBlending::None), visible(true) {}
|
||||
~Layer() {
|
||||
buffer_item_consumer->Abandon();
|
||||
}
|
||||
|
||||
std::shared_ptr<android::BufferItemConsumer> buffer_item_consumer;
|
||||
s32 consumer_id;
|
||||
LayerBlending blending;
|
||||
bool visible;
|
||||
};
|
||||
|
||||
struct LayerStack {
|
||||
std::list<Layer> layers;
|
||||
};
|
||||
|
||||
struct Display {
|
||||
explicit Display(u64 id_) {
|
||||
id = id_;
|
||||
}
|
||||
|
||||
Layer* FindLayer(s32 consumer_id) {
|
||||
for (auto& layer : stack.layers) {
|
||||
if (layer.consumer_id == consumer_id) {
|
||||
return &layer;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
u64 id;
|
||||
LayerStack stack;
|
||||
};
|
||||
|
||||
} // namespace Service::Nvnflinger
|
@ -10,8 +10,6 @@
|
||||
#include "core/hle/service/nvnflinger/hardware_composer.h"
|
||||
#include "core/hle/service/nvnflinger/hwc_layer.h"
|
||||
#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
|
||||
#include "core/hle/service/vi/display/vi_display.h"
|
||||
#include "core/hle/service/vi/layer/vi_layer.h"
|
||||
|
||||
namespace Service::Nvnflinger {
|
||||
|
||||
@ -44,7 +42,7 @@ s32 NormalizeSwapInterval(f32* out_speed_scale, s32 swap_interval) {
|
||||
HardwareComposer::HardwareComposer() = default;
|
||||
HardwareComposer::~HardwareComposer() = default;
|
||||
|
||||
u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,
|
||||
u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display,
|
||||
Nvidia::Devices::nvdisp_disp0& nvdisp) {
|
||||
boost::container::small_vector<HwcLayer, 2> composition_stack;
|
||||
|
||||
@ -56,12 +54,11 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,
|
||||
bool has_acquired_buffer{};
|
||||
|
||||
// Acquire all necessary framebuffers.
|
||||
for (size_t i = 0; i < display.GetNumLayers(); i++) {
|
||||
auto& layer = display.GetLayer(i);
|
||||
auto layer_id = layer.GetLayerId();
|
||||
for (auto& layer : display.stack.layers) {
|
||||
auto consumer_id = layer.consumer_id;
|
||||
|
||||
// Try to fetch the framebuffer (either new or stale).
|
||||
const auto result = this->CacheFramebufferLocked(layer, layer_id);
|
||||
const auto result = this->CacheFramebufferLocked(layer, consumer_id);
|
||||
|
||||
// If we failed, skip this layer.
|
||||
if (result == CacheStatus::NoBufferAvailable) {
|
||||
@ -73,11 +70,12 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,
|
||||
has_acquired_buffer = true;
|
||||
}
|
||||
|
||||
const auto& buffer = m_framebuffers[layer_id];
|
||||
const auto& buffer = m_framebuffers[consumer_id];
|
||||
const auto& item = buffer.item;
|
||||
const auto& igbp_buffer = *item.graphic_buffer;
|
||||
|
||||
// TODO: get proper Z-index from layer
|
||||
if (layer.visible) {
|
||||
composition_stack.emplace_back(HwcLayer{
|
||||
.buffer_handle = igbp_buffer.BufferId(),
|
||||
.offset = igbp_buffer.Offset(),
|
||||
@ -86,11 +84,12 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,
|
||||
.height = igbp_buffer.Height(),
|
||||
.stride = igbp_buffer.Stride(),
|
||||
.z_index = 0,
|
||||
.blending = layer.GetBlending(),
|
||||
.blending = layer.blending,
|
||||
.transform = static_cast<android::BufferTransformFlags>(item.transform),
|
||||
.crop_rect = item.crop,
|
||||
.acquire_fence = item.fence,
|
||||
});
|
||||
}
|
||||
|
||||
// We need to compose again either before this frame is supposed to
|
||||
// be released, or exactly on the vsync period it should be released.
|
||||
@ -138,7 +137,7 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,
|
||||
if (auto* layer = display.FindLayer(layer_id); layer != nullptr) {
|
||||
// TODO: support release fence
|
||||
// This is needed to prevent screen tearing
|
||||
layer->GetConsumer().ReleaseBuffer(framebuffer.item, android::Fence::NoFence());
|
||||
layer->buffer_item_consumer->ReleaseBuffer(framebuffer.item, android::Fence::NoFence());
|
||||
framebuffer.is_acquired = false;
|
||||
}
|
||||
}
|
||||
@ -146,26 +145,26 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display,
|
||||
return frame_advance;
|
||||
}
|
||||
|
||||
void HardwareComposer::RemoveLayerLocked(VI::Display& display, LayerId layer_id) {
|
||||
// Check if we are tracking a slot with this layer_id.
|
||||
const auto it = m_framebuffers.find(layer_id);
|
||||
void HardwareComposer::RemoveLayerLocked(Display& display, ConsumerId consumer_id) {
|
||||
// Check if we are tracking a slot with this consumer_id.
|
||||
const auto it = m_framebuffers.find(consumer_id);
|
||||
if (it == m_framebuffers.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to release the buffer item.
|
||||
auto* const layer = display.FindLayer(layer_id);
|
||||
auto* const layer = display.FindLayer(consumer_id);
|
||||
if (layer && it->second.is_acquired) {
|
||||
layer->GetConsumer().ReleaseBuffer(it->second.item, android::Fence::NoFence());
|
||||
layer->buffer_item_consumer->ReleaseBuffer(it->second.item, android::Fence::NoFence());
|
||||
}
|
||||
|
||||
// Erase the slot.
|
||||
m_framebuffers.erase(it);
|
||||
}
|
||||
|
||||
bool HardwareComposer::TryAcquireFramebufferLocked(VI::Layer& layer, Framebuffer& framebuffer) {
|
||||
bool HardwareComposer::TryAcquireFramebufferLocked(Layer& layer, Framebuffer& framebuffer) {
|
||||
// Attempt the update.
|
||||
const auto status = layer.GetConsumer().AcquireBuffer(&framebuffer.item, {}, false);
|
||||
const auto status = layer.buffer_item_consumer->AcquireBuffer(&framebuffer.item, {}, false);
|
||||
if (status != android::Status::NoError) {
|
||||
return false;
|
||||
}
|
||||
@ -178,10 +177,10 @@ bool HardwareComposer::TryAcquireFramebufferLocked(VI::Layer& layer, Framebuffer
|
||||
return true;
|
||||
}
|
||||
|
||||
HardwareComposer::CacheStatus HardwareComposer::CacheFramebufferLocked(VI::Layer& layer,
|
||||
LayerId layer_id) {
|
||||
HardwareComposer::CacheStatus HardwareComposer::CacheFramebufferLocked(Layer& layer,
|
||||
ConsumerId consumer_id) {
|
||||
// Check if this framebuffer is already present.
|
||||
const auto it = m_framebuffers.find(layer_id);
|
||||
const auto it = m_framebuffers.find(consumer_id);
|
||||
if (it != m_framebuffers.end()) {
|
||||
// If it's currently still acquired, we are done.
|
||||
if (it->second.is_acquired) {
|
||||
@ -203,7 +202,7 @@ HardwareComposer::CacheStatus HardwareComposer::CacheFramebufferLocked(VI::Layer
|
||||
|
||||
if (this->TryAcquireFramebufferLocked(layer, framebuffer)) {
|
||||
// Move the buffer item into a new slot.
|
||||
m_framebuffers.emplace(layer_id, std::move(framebuffer));
|
||||
m_framebuffers.emplace(consumer_id, std::move(framebuffer));
|
||||
|
||||
// We succeeded.
|
||||
return CacheStatus::BufferAcquired;
|
||||
|
@ -3,35 +3,29 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <boost/container/flat_map.hpp>
|
||||
|
||||
#include "core/hle/service/nvnflinger/buffer_item.h"
|
||||
#include "core/hle/service/nvnflinger/display.h"
|
||||
|
||||
namespace Service::Nvidia::Devices {
|
||||
class nvdisp_disp0;
|
||||
}
|
||||
|
||||
namespace Service::VI {
|
||||
class Display;
|
||||
class Layer;
|
||||
} // namespace Service::VI
|
||||
|
||||
namespace Service::Nvnflinger {
|
||||
|
||||
using LayerId = u64;
|
||||
using ConsumerId = s32;
|
||||
|
||||
class HardwareComposer {
|
||||
public:
|
||||
explicit HardwareComposer();
|
||||
~HardwareComposer();
|
||||
|
||||
u32 ComposeLocked(f32* out_speed_scale, VI::Display& display,
|
||||
u32 ComposeLocked(f32* out_speed_scale, Display& display,
|
||||
Nvidia::Devices::nvdisp_disp0& nvdisp);
|
||||
void RemoveLayerLocked(VI::Display& display, LayerId layer_id);
|
||||
void RemoveLayerLocked(Display& display, ConsumerId consumer_id);
|
||||
|
||||
private:
|
||||
// TODO: do we want to track frame number in vi instead?
|
||||
u64 m_frame_number{0};
|
||||
|
||||
private:
|
||||
@ -49,11 +43,11 @@ private:
|
||||
CachedBufferReused,
|
||||
};
|
||||
|
||||
boost::container::flat_map<LayerId, Framebuffer> m_framebuffers{};
|
||||
boost::container::flat_map<ConsumerId, Framebuffer> m_framebuffers{};
|
||||
|
||||
private:
|
||||
bool TryAcquireFramebufferLocked(VI::Layer& layer, Framebuffer& framebuffer);
|
||||
CacheStatus CacheFramebufferLocked(VI::Layer& layer, LayerId layer_id);
|
||||
bool TryAcquireFramebufferLocked(Layer& layer, Framebuffer& framebuffer);
|
||||
CacheStatus CacheFramebufferLocked(Layer& layer, ConsumerId consumer_id);
|
||||
};
|
||||
|
||||
} // namespace Service::Nvnflinger
|
||||
|
66
src/core/hle/service/nvnflinger/hos_binder_driver.cpp
Executable file
66
src/core/hle/service/nvnflinger/hos_binder_driver.cpp
Executable file
@ -0,0 +1,66 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/nvnflinger/binder.h"
|
||||
#include "core/hle/service/nvnflinger/hos_binder_driver.h"
|
||||
#include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
|
||||
|
||||
namespace Service::Nvnflinger {
|
||||
|
||||
IHOSBinderDriver::IHOSBinderDriver(Core::System& system_,
|
||||
std::shared_ptr<HosBinderDriverServer> server,
|
||||
std::shared_ptr<SurfaceFlinger> surface_flinger)
|
||||
: ServiceFramework{system_, "IHOSBinderDriver"}, m_server(server),
|
||||
m_surface_flinger(surface_flinger) {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, C<&IHOSBinderDriver::TransactParcel>, "TransactParcel"},
|
||||
{1, C<&IHOSBinderDriver::AdjustRefcount>, "AdjustRefcount"},
|
||||
{2, C<&IHOSBinderDriver::GetNativeHandle>, "GetNativeHandle"},
|
||||
{3, C<&IHOSBinderDriver::TransactParcelAuto>, "TransactParcelAuto"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IHOSBinderDriver::~IHOSBinderDriver() = default;
|
||||
|
||||
Result IHOSBinderDriver::TransactParcel(s32 binder_id, u32 transaction_id,
|
||||
InBuffer<BufferAttr_HipcMapAlias> parcel_data,
|
||||
OutBuffer<BufferAttr_HipcMapAlias> parcel_reply,
|
||||
u32 flags) {
|
||||
LOG_DEBUG(Service_VI, "called. id={} transaction={}, flags={}", binder_id, transaction_id,
|
||||
flags);
|
||||
|
||||
const auto binder = m_server->TryGetBinder(binder_id);
|
||||
R_SUCCEED_IF(binder == nullptr);
|
||||
|
||||
binder->Transact(transaction_id, parcel_data, parcel_reply, flags);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHOSBinderDriver::AdjustRefcount(s32 binder_id, s32 addval, s32 type) {
|
||||
LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={}, type={}", binder_id, addval, type);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHOSBinderDriver::GetNativeHandle(s32 binder_id, u32 type_id,
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_handle) {
|
||||
LOG_WARNING(Service_VI, "(STUBBED) called id={}, type_id={}", binder_id, type_id);
|
||||
|
||||
const auto binder = m_server->TryGetBinder(binder_id);
|
||||
R_UNLESS(binder != nullptr, ResultUnknown);
|
||||
|
||||
*out_handle = binder->GetNativeHandle(type_id);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHOSBinderDriver::TransactParcelAuto(s32 binder_id, u32 transaction_id,
|
||||
InBuffer<BufferAttr_HipcAutoSelect> parcel_data,
|
||||
OutBuffer<BufferAttr_HipcAutoSelect> parcel_reply,
|
||||
u32 flags) {
|
||||
R_RETURN(this->TransactParcel(binder_id, transaction_id, parcel_data, parcel_reply, flags));
|
||||
}
|
||||
|
||||
} // namespace Service::Nvnflinger
|
46
src/core/hle/service/nvnflinger/hos_binder_driver.h
Executable file
46
src/core/hle/service/nvnflinger/hos_binder_driver.h
Executable file
@ -0,0 +1,46 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Kernel {
|
||||
class KReadableEvent;
|
||||
}
|
||||
|
||||
namespace Service::Nvnflinger {
|
||||
|
||||
class HosBinderDriverServer;
|
||||
class SurfaceFlinger;
|
||||
|
||||
class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> {
|
||||
public:
|
||||
explicit IHOSBinderDriver(Core::System& system_, std::shared_ptr<HosBinderDriverServer> server,
|
||||
std::shared_ptr<SurfaceFlinger> surface_flinger);
|
||||
~IHOSBinderDriver() override;
|
||||
|
||||
std::shared_ptr<SurfaceFlinger> GetSurfaceFlinger() {
|
||||
return m_surface_flinger;
|
||||
}
|
||||
|
||||
std::shared_ptr<HosBinderDriverServer> GetServer() {
|
||||
return m_server;
|
||||
}
|
||||
|
||||
private:
|
||||
Result TransactParcel(s32 binder_id, u32 transaction_id,
|
||||
InBuffer<BufferAttr_HipcMapAlias> parcel_data,
|
||||
OutBuffer<BufferAttr_HipcMapAlias> parcel_reply, u32 flags);
|
||||
Result AdjustRefcount(s32 binder_id, s32 addval, s32 type);
|
||||
Result GetNativeHandle(s32 binder_id, u32 type_id,
|
||||
OutCopyHandle<Kernel::KReadableEvent> out_handle);
|
||||
Result TransactParcelAuto(s32 binder_id, u32 transaction_id,
|
||||
InBuffer<BufferAttr_HipcAutoSelect> parcel_data,
|
||||
OutBuffer<BufferAttr_HipcAutoSelect> parcel_reply, u32 flags);
|
||||
|
||||
private:
|
||||
const std::shared_ptr<HosBinderDriverServer> m_server;
|
||||
const std::shared_ptr<SurfaceFlinger> m_surface_flinger;
|
||||
};
|
||||
|
||||
} // namespace Service::Nvnflinger
|
@ -8,26 +8,30 @@
|
||||
|
||||
namespace Service::Nvnflinger {
|
||||
|
||||
HosBinderDriverServer::HosBinderDriverServer(Core::System& system_)
|
||||
: service_context(system_, "HosBinderDriverServer") {}
|
||||
HosBinderDriverServer::HosBinderDriverServer() = default;
|
||||
HosBinderDriverServer::~HosBinderDriverServer() = default;
|
||||
|
||||
HosBinderDriverServer::~HosBinderDriverServer() {}
|
||||
|
||||
u64 HosBinderDriverServer::RegisterProducer(std::unique_ptr<android::IBinder>&& binder) {
|
||||
s32 HosBinderDriverServer::RegisterBinder(std::shared_ptr<android::IBinder>&& binder) {
|
||||
std::scoped_lock lk{lock};
|
||||
|
||||
last_id++;
|
||||
|
||||
producers[last_id] = std::move(binder);
|
||||
binders[last_id] = std::move(binder);
|
||||
|
||||
return last_id;
|
||||
}
|
||||
|
||||
android::IBinder* HosBinderDriverServer::TryGetProducer(u64 id) {
|
||||
void HosBinderDriverServer::UnregisterBinder(s32 binder_id) {
|
||||
std::scoped_lock lk{lock};
|
||||
|
||||
if (auto search = producers.find(id); search != producers.end()) {
|
||||
return search->second.get();
|
||||
binders.erase(binder_id);
|
||||
}
|
||||
|
||||
std::shared_ptr<android::IBinder> HosBinderDriverServer::TryGetBinder(s32 id) const {
|
||||
std::scoped_lock lk{lock};
|
||||
|
||||
if (auto search = binders.find(id); search != binders.end()) {
|
||||
return search->second;
|
||||
}
|
||||
|
||||
return {};
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/hle/service/nvnflinger/binder.h"
|
||||
|
||||
namespace Core {
|
||||
@ -19,19 +18,18 @@ namespace Service::Nvnflinger {
|
||||
|
||||
class HosBinderDriverServer final {
|
||||
public:
|
||||
explicit HosBinderDriverServer(Core::System& system_);
|
||||
explicit HosBinderDriverServer();
|
||||
~HosBinderDriverServer();
|
||||
|
||||
u64 RegisterProducer(std::unique_ptr<android::IBinder>&& binder);
|
||||
s32 RegisterBinder(std::shared_ptr<android::IBinder>&& binder);
|
||||
void UnregisterBinder(s32 binder_id);
|
||||
|
||||
android::IBinder* TryGetProducer(u64 id);
|
||||
std::shared_ptr<android::IBinder> TryGetBinder(s32 id) const;
|
||||
|
||||
private:
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
|
||||
std::unordered_map<u64, std::unique_ptr<android::IBinder>> producers;
|
||||
std::mutex lock;
|
||||
u64 last_id{};
|
||||
std::unordered_map<s32, std::shared_ptr<android::IBinder>> binders;
|
||||
mutable std::mutex lock;
|
||||
s32 last_id{};
|
||||
};
|
||||
|
||||
} // namespace Service::Nvnflinger
|
||||
|
@ -1,335 +1,24 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/microprofile.h"
|
||||
#include "common/scope_exit.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/thread.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/k_readable_event.h"
|
||||
#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
|
||||
#include "core/hle/service/nvdrv/nvdrv.h"
|
||||
#include "core/hle/service/nvnflinger/buffer_item_consumer.h"
|
||||
#include "core/hle/service/nvnflinger/buffer_queue_core.h"
|
||||
#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
|
||||
#include "core/hle/service/nvnflinger/hardware_composer.h"
|
||||
#include "core/hle/service/nvnflinger/hos_binder_driver.h"
|
||||
#include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
|
||||
#include "core/hle/service/nvnflinger/nvnflinger.h"
|
||||
#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
|
||||
#include "core/hle/service/vi/display/vi_display.h"
|
||||
#include "core/hle/service/vi/layer/vi_layer.h"
|
||||
#include "core/hle/service/vi/vi_results.h"
|
||||
#include "video_core/gpu.h"
|
||||
#include "video_core/host1x/host1x.h"
|
||||
#include "video_core/host1x/syncpoint_manager.h"
|
||||
#include "core/hle/service/nvnflinger/surface_flinger.h"
|
||||
#include "core/hle/service/server_manager.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Service::Nvnflinger {
|
||||
|
||||
constexpr auto frame_ns = std::chrono::nanoseconds{1000000000 / 60};
|
||||
|
||||
void Nvnflinger::SplitVSync(std::stop_token stop_token) {
|
||||
system.RegisterHostThread();
|
||||
std::string name = "VSyncThread";
|
||||
MicroProfileOnThreadCreate(name.c_str());
|
||||
|
||||
// Cleanup
|
||||
SCOPE_EXIT({ MicroProfileOnThreadExit(); });
|
||||
|
||||
Common::SetCurrentThreadName(name.c_str());
|
||||
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
|
||||
|
||||
while (!stop_token.stop_requested()) {
|
||||
vsync_signal.Wait();
|
||||
|
||||
const auto lock_guard = Lock();
|
||||
|
||||
if (!is_abandoned) {
|
||||
Compose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Nvnflinger::Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_)
|
||||
: system(system_), service_context(system_, "nvnflinger"),
|
||||
hos_binder_driver_server(hos_binder_driver_server_) {
|
||||
displays.emplace_back(0, "Default", hos_binder_driver_server, service_context, system);
|
||||
displays.emplace_back(1, "External", hos_binder_driver_server, service_context, system);
|
||||
displays.emplace_back(2, "Edid", hos_binder_driver_server, service_context, system);
|
||||
displays.emplace_back(3, "Internal", hos_binder_driver_server, service_context, system);
|
||||
displays.emplace_back(4, "Null", hos_binder_driver_server, service_context, system);
|
||||
guard = std::make_shared<std::mutex>();
|
||||
|
||||
// Schedule the screen composition events
|
||||
multi_composition_event = Core::Timing::CreateEvent(
|
||||
"ScreenComposition",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
vsync_signal.Set();
|
||||
return std::chrono::nanoseconds(GetNextTicks());
|
||||
});
|
||||
|
||||
single_composition_event = Core::Timing::CreateEvent(
|
||||
"ScreenComposition",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
const auto lock_guard = Lock();
|
||||
Compose();
|
||||
|
||||
return std::chrono::nanoseconds(GetNextTicks());
|
||||
});
|
||||
|
||||
if (system.IsMulticore()) {
|
||||
system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, multi_composition_event);
|
||||
vsync_thread = std::jthread([this](std::stop_token token) { SplitVSync(token); });
|
||||
} else {
|
||||
system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, single_composition_event);
|
||||
}
|
||||
}
|
||||
|
||||
Nvnflinger::~Nvnflinger() {
|
||||
if (system.IsMulticore()) {
|
||||
system.CoreTiming().UnscheduleEvent(multi_composition_event);
|
||||
vsync_thread.request_stop();
|
||||
vsync_signal.Set();
|
||||
} else {
|
||||
system.CoreTiming().UnscheduleEvent(single_composition_event);
|
||||
}
|
||||
|
||||
ShutdownLayers();
|
||||
|
||||
if (nvdrv) {
|
||||
nvdrv->Close(disp_fd);
|
||||
}
|
||||
}
|
||||
|
||||
void Nvnflinger::ShutdownLayers() {
|
||||
// Abandon consumers.
|
||||
{
|
||||
const auto lock_guard = Lock();
|
||||
for (auto& display : displays) {
|
||||
display.Abandon();
|
||||
}
|
||||
|
||||
is_abandoned = true;
|
||||
}
|
||||
|
||||
// Join the vsync thread, if it exists.
|
||||
vsync_thread = {};
|
||||
}
|
||||
|
||||
void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
|
||||
nvdrv = std::move(instance);
|
||||
disp_fd = nvdrv->Open("/dev/nvdisp_disp0", {});
|
||||
}
|
||||
|
||||
std::optional<u64> Nvnflinger::OpenDisplay(std::string_view name) {
|
||||
const auto lock_guard = Lock();
|
||||
|
||||
LOG_DEBUG(Service_Nvnflinger, "Opening \"{}\" display", name);
|
||||
|
||||
const auto itr =
|
||||
std::find_if(displays.begin(), displays.end(),
|
||||
[&](const VI::Display& display) { return display.GetName() == name; });
|
||||
|
||||
if (itr == displays.end()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return itr->GetID();
|
||||
}
|
||||
|
||||
bool Nvnflinger::CloseDisplay(u64 display_id) {
|
||||
const auto lock_guard = Lock();
|
||||
auto* const display = FindDisplay(display_id);
|
||||
|
||||
if (display == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
display->Reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<u64> Nvnflinger::CreateLayer(u64 display_id, LayerBlending blending) {
|
||||
const auto lock_guard = Lock();
|
||||
auto* const display = FindDisplay(display_id);
|
||||
|
||||
if (display == nullptr) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const u64 layer_id = next_layer_id++;
|
||||
CreateLayerAtId(*display, layer_id, blending);
|
||||
return layer_id;
|
||||
}
|
||||
|
||||
void Nvnflinger::CreateLayerAtId(VI::Display& display, u64 layer_id, LayerBlending blending) {
|
||||
const auto buffer_id = next_buffer_queue_id++;
|
||||
display.CreateLayer(layer_id, buffer_id, nvdrv->container);
|
||||
display.FindLayer(layer_id)->SetBlending(blending);
|
||||
}
|
||||
|
||||
bool Nvnflinger::OpenLayer(u64 layer_id) {
|
||||
const auto lock_guard = Lock();
|
||||
|
||||
for (auto& display : displays) {
|
||||
if (auto* layer = display.FindLayer(layer_id); layer) {
|
||||
return layer->Open();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Nvnflinger::CloseLayer(u64 layer_id) {
|
||||
const auto lock_guard = Lock();
|
||||
|
||||
for (auto& display : displays) {
|
||||
if (auto* layer = display.FindLayer(layer_id); layer) {
|
||||
return layer->Close();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Nvnflinger::SetLayerVisibility(u64 layer_id, bool visible) {
|
||||
const auto lock_guard = Lock();
|
||||
|
||||
for (auto& display : displays) {
|
||||
if (auto* layer = display.FindLayer(layer_id); layer) {
|
||||
layer->SetVisibility(visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Nvnflinger::DestroyLayer(u64 layer_id) {
|
||||
const auto lock_guard = Lock();
|
||||
|
||||
for (auto& display : displays) {
|
||||
display.DestroyLayer(layer_id);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<u32> Nvnflinger::FindBufferQueueId(u64 display_id, u64 layer_id) {
|
||||
const auto lock_guard = Lock();
|
||||
const auto* const layer = FindLayer(display_id, layer_id);
|
||||
|
||||
if (layer == nullptr) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return layer->GetBinderId();
|
||||
}
|
||||
|
||||
Result Nvnflinger::FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id) {
|
||||
const auto lock_guard = Lock();
|
||||
auto* const display = FindDisplay(display_id);
|
||||
|
||||
if (display == nullptr) {
|
||||
return VI::ResultNotFound;
|
||||
}
|
||||
|
||||
*out_vsync_event = display->GetVSyncEvent();
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
VI::Display* Nvnflinger::FindDisplay(u64 display_id) {
|
||||
const auto itr =
|
||||
std::find_if(displays.begin(), displays.end(),
|
||||
[&](const VI::Display& display) { return display.GetID() == display_id; });
|
||||
|
||||
if (itr == displays.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &*itr;
|
||||
}
|
||||
|
||||
const VI::Display* Nvnflinger::FindDisplay(u64 display_id) const {
|
||||
const auto itr =
|
||||
std::find_if(displays.begin(), displays.end(),
|
||||
[&](const VI::Display& display) { return display.GetID() == display_id; });
|
||||
|
||||
if (itr == displays.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &*itr;
|
||||
}
|
||||
|
||||
VI::Layer* Nvnflinger::FindLayer(u64 display_id, u64 layer_id) {
|
||||
auto* const display = FindDisplay(display_id);
|
||||
|
||||
if (display == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return display->FindLayer(layer_id);
|
||||
}
|
||||
|
||||
void Nvnflinger::Compose() {
|
||||
for (auto& display : displays) {
|
||||
// Trigger vsync for this display at the end of drawing
|
||||
SCOPE_EXIT({ display.SignalVSyncEvent(); });
|
||||
|
||||
// Don't do anything for displays without layers.
|
||||
if (!display.HasLayers()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!system.IsPoweredOn()) {
|
||||
return; // We are likely shutting down
|
||||
}
|
||||
|
||||
auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>(disp_fd);
|
||||
ASSERT(nvdisp);
|
||||
|
||||
swap_interval = display.GetComposer().ComposeLocked(&compose_speed_scale, display, *nvdisp);
|
||||
}
|
||||
}
|
||||
|
||||
s64 Nvnflinger::GetNextTicks() const {
|
||||
const auto& settings = Settings::values;
|
||||
auto speed_scale = 1.f;
|
||||
if (settings.use_multi_core.GetValue()) {
|
||||
if (settings.use_speed_limit.GetValue()) {
|
||||
// Scales the speed based on speed_limit setting on MC. SC is handled by
|
||||
// SpeedLimiter::DoSpeedLimiting.
|
||||
speed_scale = 100.f / settings.speed_limit.GetValue();
|
||||
} else {
|
||||
// Run at unlocked framerate.
|
||||
speed_scale = 0.01f;
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust by speed limit determined during composition.
|
||||
speed_scale /= compose_speed_scale;
|
||||
|
||||
if (system.GetNVDECActive() && settings.use_video_framerate.GetValue()) {
|
||||
// Run at intended presentation rate during video playback.
|
||||
speed_scale = 1.f;
|
||||
}
|
||||
|
||||
const f32 effective_fps = 60.f / static_cast<f32>(swap_interval);
|
||||
return static_cast<s64>(speed_scale * (1000000000.f / effective_fps));
|
||||
}
|
||||
|
||||
FbShareBufferManager& Nvnflinger::GetSystemBufferManager() {
|
||||
const auto lock_guard = Lock();
|
||||
|
||||
if (!system_buffer_manager) {
|
||||
system_buffer_manager = std::make_unique<FbShareBufferManager>(system, *this, nvdrv);
|
||||
}
|
||||
|
||||
return *system_buffer_manager;
|
||||
void LoopProcess(Core::System& system) {
|
||||
const auto binder_server = std::make_shared<HosBinderDriverServer>();
|
||||
const auto surface_flinger = std::make_shared<SurfaceFlinger>(system, *binder_server);
|
||||
|
||||
auto server_manager = std::make_unique<ServerManager>(system);
|
||||
server_manager->RegisterNamedService(
|
||||
"dispdrv", std::make_shared<IHOSBinderDriver>(system, binder_server, surface_flinger));
|
||||
ServerManager::RunServer(std::move(server_manager));
|
||||
}
|
||||
|
||||
} // namespace Service::Nvnflinger
|
||||
|
@ -3,170 +3,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/polyfill_thread.h"
|
||||
#include "common/thread.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/hle/service/nvnflinger/hwc_layer.h"
|
||||
|
||||
namespace Common {
|
||||
class Event;
|
||||
} // namespace Common
|
||||
|
||||
namespace Core::Timing {
|
||||
class CoreTiming;
|
||||
struct EventType;
|
||||
} // namespace Core::Timing
|
||||
|
||||
namespace Kernel {
|
||||
class KReadableEvent;
|
||||
} // namespace Kernel
|
||||
|
||||
namespace Service::Nvidia {
|
||||
class Module;
|
||||
} // namespace Service::Nvidia
|
||||
|
||||
namespace Service::VI {
|
||||
class Display;
|
||||
class Layer;
|
||||
} // namespace Service::VI
|
||||
|
||||
namespace Service::android {
|
||||
class BufferQueueCore;
|
||||
class BufferQueueProducer;
|
||||
} // namespace Service::android
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Service::Nvnflinger {
|
||||
|
||||
class FbShareBufferManager;
|
||||
class HardwareComposer;
|
||||
class HosBinderDriverServer;
|
||||
|
||||
class Nvnflinger final {
|
||||
public:
|
||||
explicit Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_);
|
||||
~Nvnflinger();
|
||||
|
||||
void ShutdownLayers();
|
||||
|
||||
/// Sets the NVDrv module instance to use to send buffers to the GPU.
|
||||
void SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance);
|
||||
|
||||
/// Opens the specified display and returns the ID.
|
||||
///
|
||||
/// If an invalid display name is provided, then an empty optional is returned.
|
||||
[[nodiscard]] std::optional<u64> OpenDisplay(std::string_view name);
|
||||
|
||||
/// Closes the specified display by its ID.
|
||||
///
|
||||
/// Returns false if an invalid display ID is provided.
|
||||
[[nodiscard]] bool CloseDisplay(u64 display_id);
|
||||
|
||||
/// Creates a layer on the specified display and returns the layer ID.
|
||||
///
|
||||
/// If an invalid display ID is specified, then an empty optional is returned.
|
||||
[[nodiscard]] std::optional<u64> CreateLayer(u64 display_id,
|
||||
LayerBlending blending = LayerBlending::None);
|
||||
|
||||
/// Opens a layer on all displays for the given layer ID.
|
||||
bool OpenLayer(u64 layer_id);
|
||||
|
||||
/// Closes a layer on all displays for the given layer ID.
|
||||
bool CloseLayer(u64 layer_id);
|
||||
|
||||
/// Makes a layer visible on all displays for the given layer ID.
|
||||
void SetLayerVisibility(u64 layer_id, bool visible);
|
||||
|
||||
/// Destroys the given layer ID.
|
||||
void DestroyLayer(u64 layer_id);
|
||||
|
||||
/// Finds the buffer queue ID of the specified layer in the specified display.
|
||||
///
|
||||
/// If an invalid display ID or layer ID is provided, then an empty optional is returned.
|
||||
[[nodiscard]] std::optional<u32> FindBufferQueueId(u64 display_id, u64 layer_id);
|
||||
|
||||
/// Gets the vsync event for the specified display.
|
||||
///
|
||||
/// If an invalid display ID is provided, then VI::ResultNotFound is returned.
|
||||
/// If the vsync event has already been retrieved, then VI::ResultPermissionDenied is returned.
|
||||
[[nodiscard]] Result FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id);
|
||||
|
||||
/// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when
|
||||
/// finished.
|
||||
void Compose();
|
||||
|
||||
[[nodiscard]] s64 GetNextTicks() const;
|
||||
|
||||
FbShareBufferManager& GetSystemBufferManager();
|
||||
|
||||
private:
|
||||
struct Layer {
|
||||
std::unique_ptr<android::BufferQueueCore> core;
|
||||
std::unique_ptr<android::BufferQueueProducer> producer;
|
||||
};
|
||||
|
||||
friend class FbShareBufferManager;
|
||||
|
||||
private:
|
||||
[[nodiscard]] std::unique_lock<std::mutex> Lock() const {
|
||||
return std::unique_lock{*guard};
|
||||
}
|
||||
|
||||
/// Finds the display identified by the specified ID.
|
||||
[[nodiscard]] VI::Display* FindDisplay(u64 display_id);
|
||||
|
||||
/// Finds the display identified by the specified ID.
|
||||
[[nodiscard]] const VI::Display* FindDisplay(u64 display_id) const;
|
||||
|
||||
/// Finds the layer identified by the specified ID in the desired display.
|
||||
[[nodiscard]] VI::Layer* FindLayer(u64 display_id, u64 layer_id);
|
||||
|
||||
/// Creates a layer with the specified layer ID in the desired display.
|
||||
void CreateLayerAtId(VI::Display& display, u64 layer_id, LayerBlending blending);
|
||||
|
||||
void SplitVSync(std::stop_token stop_token);
|
||||
|
||||
std::shared_ptr<Nvidia::Module> nvdrv;
|
||||
s32 disp_fd;
|
||||
|
||||
std::list<VI::Display> displays;
|
||||
|
||||
/// Id to use for the next layer that is created, this counter is shared among all displays.
|
||||
u64 next_layer_id = 1;
|
||||
/// Id to use for the next buffer queue that is created, this counter is shared among all
|
||||
/// layers.
|
||||
u32 next_buffer_queue_id = 1;
|
||||
|
||||
s32 swap_interval = 1;
|
||||
f32 compose_speed_scale = 1.0f;
|
||||
|
||||
bool is_abandoned = false;
|
||||
|
||||
/// Event that handles screen composition.
|
||||
std::shared_ptr<Core::Timing::EventType> multi_composition_event;
|
||||
std::shared_ptr<Core::Timing::EventType> single_composition_event;
|
||||
|
||||
std::unique_ptr<FbShareBufferManager> system_buffer_manager;
|
||||
|
||||
std::shared_ptr<std::mutex> guard;
|
||||
|
||||
Core::System& system;
|
||||
|
||||
Common::Event vsync_signal;
|
||||
|
||||
std::jthread vsync_thread;
|
||||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
|
||||
HosBinderDriverServer& hos_binder_driver_server;
|
||||
};
|
||||
void LoopProcess(Core::System& system);
|
||||
|
||||
} // namespace Service::Nvnflinger
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user