diff options
74 files changed, 1358 insertions, 653 deletions
diff --git a/src/common/ring_buffer.h b/src/common/ring_buffer.h index e7e9fdb38..b92db6185 100644 --- a/src/common/ring_buffer.h +++ b/src/common/ring_buffer.h @@ -8,6 +8,7 @@ #include <atomic> #include <cstddef> #include <cstring> +#include <limits> #include <new> #include <span> #include <type_traits> diff --git a/src/common/settings.h b/src/common/settings.h index b2b071e7e..61969af2b 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -140,7 +140,7 @@ struct Values { Category::LibraryApplet}; Setting<AppletMode> data_erase_applet_mode{linkage, AppletMode::HLE, "data_erase_applet_mode", Category::LibraryApplet}; - Setting<AppletMode> error_applet_mode{linkage, AppletMode::HLE, "error_applet_mode", + Setting<AppletMode> error_applet_mode{linkage, AppletMode::LLE, "error_applet_mode", Category::LibraryApplet}; Setting<AppletMode> net_connect_applet_mode{linkage, AppletMode::HLE, "net_connect_applet_mode", Category::LibraryApplet}; @@ -435,8 +435,6 @@ struct Values { linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug}; Setting<bool> enable_renderdoc_hotkey{linkage, false, "renderdoc_hotkey", Category::RendererDebug}; - // TODO: remove this once AMDVLK supports VK_EXT_depth_bias_control - bool renderer_amdvlk_depth_bias_workaround{}; Setting<bool> disable_buffer_reorder{linkage, false, "disable_buffer_reorder", Category::RendererDebug}; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 93e403b26..de158eea7 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -486,8 +486,10 @@ 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/aoc/aoc_u.cpp - hle/service/aoc/aoc_u.h + hle/service/aoc/addon_content_manager.cpp + hle/service/aoc/addon_content_manager.h + hle/service/aoc/purchase_event_manager.cpp + hle/service/aoc/purchase_event_manager.h hle/service/apm/apm.cpp hle/service/apm/apm.h hle/service/apm/apm_controller.cpp @@ -1049,9 +1051,12 @@ add_library(core STATIC hle/service/spl/spl_module.h hle/service/spl/spl_results.h hle/service/spl/spl_types.h + hle/service/ssl/cert_store.cpp + hle/service/ssl/cert_store.h hle/service/ssl/ssl.cpp hle/service/ssl/ssl.h hle/service/ssl/ssl_backend.h + hle/service/ssl/ssl_types.h hle/service/usb/usb.cpp hle/service/usb/usb.h hle/service/vi/application_display_service.cpp diff --git a/src/core/core.cpp b/src/core/core.cpp index 9e8936728..dc515bc82 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -425,11 +425,6 @@ struct System::Impl { room_member->SendGameInfo(game_info); } - // Workarounds: - // Activate this in Super Smash Brothers Ultimate, it only affects AMD cards using AMDVLK - Settings::values.renderer_amdvlk_depth_bias_workaround = - params.program_id == 0x1006A800016E000ULL; - status = SystemResultStatus::Success; return status; } @@ -489,9 +484,6 @@ struct System::Impl { room_member->SendGameInfo(game_info); } - // Workarounds - Settings::values.renderer_amdvlk_depth_bias_workaround = false; - LOG_DEBUG(Core, "Shutdown OK"); } diff --git a/src/core/file_sys/fssystem/fssystem_aes_xts_storage.cpp b/src/core/file_sys/fssystem/fssystem_aes_xts_storage.cpp index 022424229..efc5aa0b1 100644 --- a/src/core/file_sys/fssystem/fssystem_aes_xts_storage.cpp +++ b/src/core/file_sys/fssystem/fssystem_aes_xts_storage.cpp @@ -31,8 +31,8 @@ AesXtsStorage::AesXtsStorage(VirtualFile base, const void* key1, const void* key ASSERT(iv_size == IvSize); ASSERT(Common::IsAligned(m_block_size, AesBlockSize)); - std::memcpy(m_key.data() + 0, key1, KeySize); - std::memcpy(m_key.data() + 0x10, key2, KeySize); + std::memcpy(m_key.data() + 0, key1, KeySize / 2); + std::memcpy(m_key.data() + 0x10, key2, KeySize / 2); std::memcpy(m_iv.data(), iv, IvSize); m_cipher.emplace(m_key, Core::Crypto::Mode::XTS); diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index f21553644..fad111d44 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -25,8 +25,8 @@ #include "core/hle/service/acc/async_context.h" #include "core/hle/service/acc/errors.h" #include "core/hle/service/acc/profile_manager.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/glue/glue_manager.h" -#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/server_manager.h" #include "core/loader/loader.h" @@ -74,12 +74,12 @@ static void SanitizeJPEGImageSize(std::vector<u8>& image) { class IManagerForSystemService final : public ServiceFramework<IManagerForSystemService> { public: - explicit IManagerForSystemService(Core::System& system_, Common::UUID) - : ServiceFramework{system_, "IManagerForSystemService"} { + explicit IManagerForSystemService(Core::System& system_, Common::UUID uuid) + : ServiceFramework{system_, "IManagerForSystemService"}, account_id{uuid} { // clang-format off static const FunctionInfo functions[] = { - {0, &IManagerForSystemService::CheckAvailability, "CheckAvailability"}, - {1, nullptr, "GetAccountId"}, + {0, D<&IManagerForSystemService::CheckAvailability>, "CheckAvailability"}, + {1, D<&IManagerForSystemService::GetAccountId>, "GetAccountId"}, {2, nullptr, "EnsureIdTokenCacheAsync"}, {3, nullptr, "LoadIdTokenCache"}, {100, nullptr, "SetSystemProgramIdentification"}, @@ -109,11 +109,18 @@ public: } private: - void CheckAvailability(HLERequestContext& ctx) { + Result CheckAvailability() { LOG_WARNING(Service_ACC, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + R_SUCCEED(); } + + Result GetAccountId(Out<u64> out_account_id) { + LOG_WARNING(Service_ACC, "(STUBBED) called"); + *out_account_id = account_id.Hash(); + R_SUCCEED(); + } + + Common::UUID account_id; }; // 3.0.0+ diff --git a/src/core/hle/service/acc/acc_u1.cpp b/src/core/hle/service/acc/acc_u1.cpp index 92f704c2f..eecc94387 100644 --- a/src/core/hle/service/acc/acc_u1.cpp +++ b/src/core/hle/service/acc/acc_u1.cpp @@ -23,7 +23,7 @@ ACC_U1::ACC_U1(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager> {99, nullptr, "DebugActivateOpenContextRetention"}, {100, nullptr, "GetUserRegistrationNotifier"}, {101, nullptr, "GetUserStateChangeNotifier"}, - {102, nullptr, "GetBaasAccountManagerForSystemService"}, + {102, &ACC_U1::GetBaasAccountManagerForSystemService, "GetBaasAccountManagerForSystemService"}, {103, nullptr, "GetBaasUserAvailabilityChangeNotifier"}, {104, nullptr, "GetProfileUpdateNotifier"}, {105, nullptr, "CheckNetworkServiceAvailabilityAsync"}, diff --git a/src/core/hle/service/am/am_types.h b/src/core/hle/service/am/am_types.h index 46afb3996..a14defb40 100644 --- a/src/core/hle/service/am/am_types.h +++ b/src/core/hle/service/am/am_types.h @@ -48,11 +48,6 @@ enum class SystemButtonType { CaptureButtonLongPressing, }; -enum class SysPlatformRegion : s32 { - Global = 1, - Terra = 2, -}; - struct AppletProcessLaunchReason { u8 flag; INSERT_PADDING_BYTES(3); diff --git a/src/core/hle/service/am/service/common_state_getter.cpp b/src/core/hle/service/am/service/common_state_getter.cpp index 548498e83..a32855ffa 100644 --- a/src/core/hle/service/am/service/common_state_getter.cpp +++ b/src/core/hle/service/am/service/common_state_getter.cpp @@ -260,9 +260,9 @@ Result ICommonStateGetter::GetAppletLaunchedHistory( } Result ICommonStateGetter::GetSettingsPlatformRegion( - Out<SysPlatformRegion> out_settings_platform_region) { + Out<Set::PlatformRegion> out_settings_platform_region) { LOG_INFO(Service_AM, "called"); - *out_settings_platform_region = SysPlatformRegion::Global; + *out_settings_platform_region = Set::PlatformRegion::Global; R_SUCCEED(); } diff --git a/src/core/hle/service/am/service/common_state_getter.h b/src/core/hle/service/am/service/common_state_getter.h index 5a8dca3d6..59a46fa94 100644 --- a/src/core/hle/service/am/service/common_state_getter.h +++ b/src/core/hle/service/am/service/common_state_getter.h @@ -8,6 +8,7 @@ #include "core/hle/service/cmif_types.h" #include "core/hle/service/pm/pm.h" #include "core/hle/service/service.h" +#include "core/hle/service/set/settings_types.h" namespace Kernel { class KReadableEvent; @@ -50,7 +51,7 @@ private: Result GetOperationModeSystemInfo(Out<u32> out_operation_mode_system_info); Result GetAppletLaunchedHistory(Out<s32> out_count, OutArray<AppletId, BufferAttr_HipcMapAlias> out_applet_ids); - Result GetSettingsPlatformRegion(Out<SysPlatformRegion> out_settings_platform_region); + Result GetSettingsPlatformRegion(Out<Set::PlatformRegion> out_settings_platform_region); Result SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(); void SetCpuBoostMode(HLERequestContext& ctx); diff --git a/src/core/hle/service/aoc/addon_content_manager.cpp b/src/core/hle/service/aoc/addon_content_manager.cpp new file mode 100644 index 000000000..d47f57d64 --- /dev/null +++ b/src/core/hle/service/aoc/addon_content_manager.cpp @@ -0,0 +1,223 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <algorithm> +#include <numeric> +#include <vector> + +#include "common/logging/log.h" +#include "common/settings.h" +#include "core/core.h" +#include "core/file_sys/common_funcs.h" +#include "core/file_sys/content_archive.h" +#include "core/file_sys/control_metadata.h" +#include "core/file_sys/nca_metadata.h" +#include "core/file_sys/patch_manager.h" +#include "core/file_sys/registered_cache.h" +#include "core/hle/kernel/k_event.h" +#include "core/hle/service/aoc/addon_content_manager.h" +#include "core/hle/service/aoc/purchase_event_manager.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/server_manager.h" +#include "core/loader/loader.h" + +namespace Service::AOC { + +static bool CheckAOCTitleIDMatchesBase(u64 title_id, u64 base) { + return FileSys::GetBaseTitleID(title_id) == base; +} + +static std::vector<u64> AccumulateAOCTitleIDs(Core::System& system) { + std::vector<u64> add_on_content; + const auto& rcu = system.GetContentProvider(); + const auto list = + rcu.ListEntriesFilter(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data); + std::transform(list.begin(), list.end(), std::back_inserter(add_on_content), + [](const FileSys::ContentProviderEntry& rce) { return rce.title_id; }); + add_on_content.erase( + std::remove_if( + add_on_content.begin(), add_on_content.end(), + [&rcu](u64 tid) { + return rcu.GetEntry(tid, FileSys::ContentRecordType::Data)->GetStatus() != + Loader::ResultStatus::Success; + }), + add_on_content.end()); + return add_on_content; +} + +IAddOnContentManager::IAddOnContentManager(Core::System& system_) + : ServiceFramework{system_, "aoc:u"}, add_on_content{AccumulateAOCTitleIDs(system)}, + service_context{system_, "aoc:u"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "CountAddOnContentByApplicationId"}, + {1, nullptr, "ListAddOnContentByApplicationId"}, + {2, D<&IAddOnContentManager::CountAddOnContent>, "CountAddOnContent"}, + {3, D<&IAddOnContentManager::ListAddOnContent>, "ListAddOnContent"}, + {4, nullptr, "GetAddOnContentBaseIdByApplicationId"}, + {5, D<&IAddOnContentManager::GetAddOnContentBaseId>, "GetAddOnContentBaseId"}, + {6, nullptr, "PrepareAddOnContentByApplicationId"}, + {7, D<&IAddOnContentManager::PrepareAddOnContent>, "PrepareAddOnContent"}, + {8, D<&IAddOnContentManager::GetAddOnContentListChangedEvent>, "GetAddOnContentListChangedEvent"}, + {9, nullptr, "GetAddOnContentLostErrorCode"}, + {10, D<&IAddOnContentManager::GetAddOnContentListChangedEventWithProcessId>, "GetAddOnContentListChangedEventWithProcessId"}, + {11, D<&IAddOnContentManager::NotifyMountAddOnContent>, "NotifyMountAddOnContent"}, + {12, D<&IAddOnContentManager::NotifyUnmountAddOnContent>, "NotifyUnmountAddOnContent"}, + {13, nullptr, "IsAddOnContentMountedForDebug"}, + {50, D<&IAddOnContentManager::CheckAddOnContentMountStatus>, "CheckAddOnContentMountStatus"}, + {100, D<&IAddOnContentManager::CreateEcPurchasedEventManager>, "CreateEcPurchasedEventManager"}, + {101, D<&IAddOnContentManager::CreatePermanentEcPurchasedEventManager>, "CreatePermanentEcPurchasedEventManager"}, + {110, nullptr, "CreateContentsServiceManager"}, + {200, nullptr, "SetRequiredAddOnContentsOnContentsAvailabilityTransition"}, + {300, nullptr, "SetupHostAddOnContent"}, + {301, nullptr, "GetRegisteredAddOnContentPath"}, + {302, nullptr, "UpdateCachedList"}, + }; + // clang-format on + + RegisterHandlers(functions); + + aoc_change_event = service_context.CreateEvent("GetAddOnContentListChanged:Event"); +} + +IAddOnContentManager::~IAddOnContentManager() { + service_context.CloseEvent(aoc_change_event); +} + +Result IAddOnContentManager::CountAddOnContent(Out<u32> out_count, ClientProcessId process_id) { + LOG_DEBUG(Service_AOC, "called. process_id={}", process_id.pid); + + const auto current = system.GetApplicationProcessProgramID(); + + const auto& disabled = Settings::values.disabled_addons[current]; + if (std::find(disabled.begin(), disabled.end(), "DLC") != disabled.end()) { + *out_count = 0; + R_SUCCEED(); + } + + *out_count = static_cast<u32>( + std::count_if(add_on_content.begin(), add_on_content.end(), + [current](u64 tid) { return CheckAOCTitleIDMatchesBase(tid, current); })); + + R_SUCCEED(); +} + +Result IAddOnContentManager::ListAddOnContent(Out<u32> out_count, + OutBuffer<BufferAttr_HipcMapAlias> out_addons, + u32 offset, u32 count, ClientProcessId process_id) { + LOG_DEBUG(Service_AOC, "called with offset={}, count={}, process_id={}", offset, count, + process_id.pid); + + const auto current = FileSys::GetBaseTitleID(system.GetApplicationProcessProgramID()); + + std::vector<u32> out; + const auto& disabled = Settings::values.disabled_addons[current]; + if (std::find(disabled.begin(), disabled.end(), "DLC") == disabled.end()) { + for (u64 content_id : add_on_content) { + if (FileSys::GetBaseTitleID(content_id) != current) { + continue; + } + + out.push_back(static_cast<u32>(FileSys::GetAOCID(content_id))); + } + } + + // TODO(DarkLordZach): Find the correct error code. + R_UNLESS(out.size() >= offset, ResultUnknown); + + *out_count = static_cast<u32>(std::min<size_t>(out.size() - offset, count)); + std::rotate(out.begin(), out.begin() + offset, out.end()); + + std::memcpy(out_addons.data(), out.data(), *out_count * sizeof(u32)); + + R_SUCCEED(); +} + +Result IAddOnContentManager::GetAddOnContentBaseId(Out<u64> out_title_id, + ClientProcessId process_id) { + LOG_DEBUG(Service_AOC, "called. process_id={}", process_id.pid); + + const auto title_id = system.GetApplicationProcessProgramID(); + const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), + system.GetContentProvider()}; + + const auto res = pm.GetControlMetadata(); + if (res.first == nullptr) { + *out_title_id = FileSys::GetAOCBaseTitleID(title_id); + R_SUCCEED(); + } + + *out_title_id = res.first->GetDLCBaseTitleId(); + + R_SUCCEED(); +} + +Result IAddOnContentManager::PrepareAddOnContent(s32 addon_index, ClientProcessId process_id) { + LOG_WARNING(Service_AOC, "(STUBBED) called with addon_index={}, process_id={}", addon_index, + process_id.pid); + + R_SUCCEED(); +} + +Result IAddOnContentManager::GetAddOnContentListChangedEvent( + OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_WARNING(Service_AOC, "(STUBBED) called"); + + *out_event = &aoc_change_event->GetReadableEvent(); + + R_SUCCEED(); +} + +Result IAddOnContentManager::GetAddOnContentListChangedEventWithProcessId( + OutCopyHandle<Kernel::KReadableEvent> out_event, ClientProcessId process_id) { + LOG_WARNING(Service_AOC, "(STUBBED) called"); + + *out_event = &aoc_change_event->GetReadableEvent(); + + R_SUCCEED(); +} + +Result IAddOnContentManager::NotifyMountAddOnContent() { + LOG_WARNING(Service_AOC, "(STUBBED) called"); + + R_SUCCEED(); +} + +Result IAddOnContentManager::NotifyUnmountAddOnContent() { + LOG_WARNING(Service_AOC, "(STUBBED) called"); + + R_SUCCEED(); +} + +Result IAddOnContentManager::CheckAddOnContentMountStatus() { + LOG_WARNING(Service_AOC, "(STUBBED) called"); + + R_SUCCEED(); +} + +Result IAddOnContentManager::CreateEcPurchasedEventManager( + OutInterface<IPurchaseEventManager> out_interface) { + LOG_WARNING(Service_AOC, "(STUBBED) called"); + + *out_interface = std::make_shared<IPurchaseEventManager>(system); + + R_SUCCEED(); +} + +Result IAddOnContentManager::CreatePermanentEcPurchasedEventManager( + OutInterface<IPurchaseEventManager> out_interface) { + LOG_WARNING(Service_AOC, "(STUBBED) called"); + + *out_interface = std::make_shared<IPurchaseEventManager>(system); + + R_SUCCEED(); +} + +void LoopProcess(Core::System& system) { + auto server_manager = std::make_unique<ServerManager>(system); + server_manager->RegisterNamedService("aoc:u", std::make_shared<IAddOnContentManager>(system)); + ServerManager::RunServer(std::move(server_manager)); +} + +} // namespace Service::AOC diff --git a/src/core/hle/service/aoc/addon_content_manager.h b/src/core/hle/service/aoc/addon_content_manager.h new file mode 100644 index 000000000..91857df4c --- /dev/null +++ b/src/core/hle/service/aoc/addon_content_manager.h @@ -0,0 +1,51 @@ +// 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/kernel_helpers.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Kernel { +class KEvent; +} + +namespace Service::AOC { + +class IPurchaseEventManager; + +class IAddOnContentManager final : public ServiceFramework<IAddOnContentManager> { +public: + explicit IAddOnContentManager(Core::System& system); + ~IAddOnContentManager() override; + + Result CountAddOnContent(Out<u32> out_count, ClientProcessId process_id); + Result ListAddOnContent(Out<u32> out_count, OutBuffer<BufferAttr_HipcMapAlias> out_addons, + u32 offset, u32 count, ClientProcessId process_id); + Result GetAddOnContentBaseId(Out<u64> out_title_id, ClientProcessId process_id); + Result PrepareAddOnContent(s32 addon_index, ClientProcessId process_id); + Result GetAddOnContentListChangedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result GetAddOnContentListChangedEventWithProcessId( + OutCopyHandle<Kernel::KReadableEvent> out_event, ClientProcessId process_id); + Result NotifyMountAddOnContent(); + Result NotifyUnmountAddOnContent(); + Result CheckAddOnContentMountStatus(); + Result CreateEcPurchasedEventManager(OutInterface<IPurchaseEventManager> out_interface); + Result CreatePermanentEcPurchasedEventManager( + OutInterface<IPurchaseEventManager> out_interface); + +private: + std::vector<u64> add_on_content; + KernelHelpers::ServiceContext service_context; + + Kernel::KEvent* aoc_change_event; +}; + +void LoopProcess(Core::System& system); + +} // namespace Service::AOC diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp deleted file mode 100644 index 486719cc0..000000000 --- a/src/core/hle/service/aoc/aoc_u.cpp +++ /dev/null @@ -1,340 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include <algorithm> -#include <numeric> -#include <vector> - -#include "common/logging/log.h" -#include "common/settings.h" -#include "core/core.h" -#include "core/file_sys/common_funcs.h" -#include "core/file_sys/content_archive.h" -#include "core/file_sys/control_metadata.h" -#include "core/file_sys/nca_metadata.h" -#include "core/file_sys/patch_manager.h" -#include "core/file_sys/registered_cache.h" -#include "core/hle/kernel/k_event.h" -#include "core/hle/service/aoc/aoc_u.h" -#include "core/hle/service/ipc_helpers.h" -#include "core/hle/service/server_manager.h" -#include "core/loader/loader.h" - -namespace Service::AOC { - -constexpr Result ResultNoPurchasedProductInfoAvailable{ErrorModule::NIMShop, 400}; - -static bool CheckAOCTitleIDMatchesBase(u64 title_id, u64 base) { - return FileSys::GetBaseTitleID(title_id) == base; -} - -static std::vector<u64> AccumulateAOCTitleIDs(Core::System& system) { - std::vector<u64> add_on_content; - const auto& rcu = system.GetContentProvider(); - const auto list = - rcu.ListEntriesFilter(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data); - std::transform(list.begin(), list.end(), std::back_inserter(add_on_content), - [](const FileSys::ContentProviderEntry& rce) { return rce.title_id; }); - add_on_content.erase( - std::remove_if( - add_on_content.begin(), add_on_content.end(), - [&rcu](u64 tid) { - return rcu.GetEntry(tid, FileSys::ContentRecordType::Data)->GetStatus() != - Loader::ResultStatus::Success; - }), - add_on_content.end()); - return add_on_content; -} - -class IPurchaseEventManager final : public ServiceFramework<IPurchaseEventManager> { -public: - explicit IPurchaseEventManager(Core::System& system_) - : ServiceFramework{system_, "IPurchaseEventManager"}, service_context{ - system, "IPurchaseEventManager"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, &IPurchaseEventManager::SetDefaultDeliveryTarget, "SetDefaultDeliveryTarget"}, - {1, &IPurchaseEventManager::SetDeliveryTarget, "SetDeliveryTarget"}, - {2, &IPurchaseEventManager::GetPurchasedEventReadableHandle, "GetPurchasedEventReadableHandle"}, - {3, &IPurchaseEventManager::PopPurchasedProductInfo, "PopPurchasedProductInfo"}, - {4, &IPurchaseEventManager::PopPurchasedProductInfoWithUid, "PopPurchasedProductInfoWithUid"}, - }; - // clang-format on - - RegisterHandlers(functions); - - purchased_event = service_context.CreateEvent("IPurchaseEventManager:PurchasedEvent"); - } - - ~IPurchaseEventManager() override { - service_context.CloseEvent(purchased_event); - } - -private: - void SetDefaultDeliveryTarget(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - const auto unknown_1 = rp.Pop<u64>(); - [[maybe_unused]] const auto unknown_2 = ctx.ReadBuffer(); - - LOG_WARNING(Service_AOC, "(STUBBED) called, unknown_1={}", unknown_1); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void SetDeliveryTarget(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - const auto unknown_1 = rp.Pop<u64>(); - [[maybe_unused]] const auto unknown_2 = ctx.ReadBuffer(); - - LOG_WARNING(Service_AOC, "(STUBBED) called, unknown_1={}", unknown_1); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - } - - void GetPurchasedEventReadableHandle(HLERequestContext& ctx) { - LOG_WARNING(Service_AOC, "called"); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(purchased_event->GetReadableEvent()); - } - - void PopPurchasedProductInfo(HLERequestContext& ctx) { - LOG_DEBUG(Service_AOC, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNoPurchasedProductInfoAvailable); - } - - void PopPurchasedProductInfoWithUid(HLERequestContext& ctx) { - LOG_DEBUG(Service_AOC, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultNoPurchasedProductInfoAvailable); - } - - KernelHelpers::ServiceContext service_context; - - Kernel::KEvent* purchased_event; -}; - -AOC_U::AOC_U(Core::System& system_) - : ServiceFramework{system_, "aoc:u"}, add_on_content{AccumulateAOCTitleIDs(system)}, - service_context{system_, "aoc:u"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "CountAddOnContentByApplicationId"}, - {1, nullptr, "ListAddOnContentByApplicationId"}, - {2, &AOC_U::CountAddOnContent, "CountAddOnContent"}, - {3, &AOC_U::ListAddOnContent, "ListAddOnContent"}, - {4, nullptr, "GetAddOnContentBaseIdByApplicationId"}, - {5, &AOC_U::GetAddOnContentBaseId, "GetAddOnContentBaseId"}, - {6, nullptr, "PrepareAddOnContentByApplicationId"}, - {7, &AOC_U::PrepareAddOnContent, "PrepareAddOnContent"}, - {8, &AOC_U::GetAddOnContentListChangedEvent, "GetAddOnContentListChangedEvent"}, - {9, nullptr, "GetAddOnContentLostErrorCode"}, - {10, &AOC_U::GetAddOnContentListChangedEventWithProcessId, "GetAddOnContentListChangedEventWithProcessId"}, - {11, &AOC_U::NotifyMountAddOnContent, "NotifyMountAddOnContent"}, - {12, &AOC_U::NotifyUnmountAddOnContent, "NotifyUnmountAddOnContent"}, - {13, nullptr, "IsAddOnContentMountedForDebug"}, - {50, &AOC_U::CheckAddOnContentMountStatus, "CheckAddOnContentMountStatus"}, - {100, &AOC_U::CreateEcPurchasedEventManager, "CreateEcPurchasedEventManager"}, - {101, &AOC_U::CreatePermanentEcPurchasedEventManager, "CreatePermanentEcPurchasedEventManager"}, - {110, nullptr, "CreateContentsServiceManager"}, - {200, nullptr, "SetRequiredAddOnContentsOnContentsAvailabilityTransition"}, - {300, nullptr, "SetupHostAddOnContent"}, - {301, nullptr, "GetRegisteredAddOnContentPath"}, - {302, nullptr, "UpdateCachedList"}, - }; - // clang-format on - - RegisterHandlers(functions); - - aoc_change_event = service_context.CreateEvent("GetAddOnContentListChanged:Event"); -} - -AOC_U::~AOC_U() { - service_context.CloseEvent(aoc_change_event); -} - -void AOC_U::CountAddOnContent(HLERequestContext& ctx) { - struct Parameters { - u64 process_id; - }; - static_assert(sizeof(Parameters) == 8); - - IPC::RequestParser rp{ctx}; - const auto params = rp.PopRaw<Parameters>(); - - LOG_DEBUG(Service_AOC, "called. process_id={}", params.process_id); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - - const auto current = system.GetApplicationProcessProgramID(); - - const auto& disabled = Settings::values.disabled_addons[current]; - if (std::find(disabled.begin(), disabled.end(), "DLC") != disabled.end()) { - rb.Push<u32>(0); - return; - } - - rb.Push<u32>(static_cast<u32>( - std::count_if(add_on_content.begin(), add_on_content.end(), - [current](u64 tid) { return CheckAOCTitleIDMatchesBase(tid, current); }))); -} - -void AOC_U::ListAddOnContent(HLERequestContext& ctx) { - struct Parameters { - u32 offset; - u32 count; - u64 process_id; - }; - static_assert(sizeof(Parameters) == 16); - - IPC::RequestParser rp{ctx}; - const auto [offset, count, process_id] = rp.PopRaw<Parameters>(); - - LOG_DEBUG(Service_AOC, "called with offset={}, count={}, process_id={}", offset, count, - process_id); - - const auto current = FileSys::GetBaseTitleID(system.GetApplicationProcessProgramID()); - - std::vector<u32> out; - const auto& disabled = Settings::values.disabled_addons[current]; - if (std::find(disabled.begin(), disabled.end(), "DLC") == disabled.end()) { - for (u64 content_id : add_on_content) { - if (FileSys::GetBaseTitleID(content_id) != current) { - continue; - } - - out.push_back(static_cast<u32>(FileSys::GetAOCID(content_id))); - } - } - - if (out.size() < offset) { - IPC::ResponseBuilder rb{ctx, 2}; - // TODO(DarkLordZach): Find the correct error code. - rb.Push(ResultUnknown); - return; - } - - const auto out_count = static_cast<u32>(std::min<size_t>(out.size() - offset, count)); - std::rotate(out.begin(), out.begin() + offset, out.end()); - out.resize(out_count); - - ctx.WriteBuffer(out); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(out_count); -} - -void AOC_U::GetAddOnContentBaseId(HLERequestContext& ctx) { - struct Parameters { - u64 process_id; - }; - static_assert(sizeof(Parameters) == 8); - - IPC::RequestParser rp{ctx}; - const auto params = rp.PopRaw<Parameters>(); - - LOG_DEBUG(Service_AOC, "called. process_id={}", params.process_id); - - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(ResultSuccess); - - const auto title_id = system.GetApplicationProcessProgramID(); - const FileSys::PatchManager pm{title_id, system.GetFileSystemController(), - system.GetContentProvider()}; - - const auto res = pm.GetControlMetadata(); - if (res.first == nullptr) { - rb.Push(FileSys::GetAOCBaseTitleID(title_id)); - return; - } - - rb.Push(res.first->GetDLCBaseTitleId()); -} - -void AOC_U::PrepareAddOnContent(HLERequestContext& ctx) { - struct Parameters { - s32 addon_index; - u64 process_id; - }; - static_assert(sizeof(Parameters) == 16); - - IPC::RequestParser rp{ctx}; - const auto [addon_index, process_id] = rp.PopRaw<Parameters>(); - - LOG_WARNING(Service_AOC, "(STUBBED) called with addon_index={}, process_id={}", addon_index, - process_id); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void AOC_U::GetAddOnContentListChangedEvent(HLERequestContext& ctx) { - LOG_WARNING(Service_AOC, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(aoc_change_event->GetReadableEvent()); -} - -void AOC_U::GetAddOnContentListChangedEventWithProcessId(HLERequestContext& ctx) { - LOG_WARNING(Service_AOC, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(aoc_change_event->GetReadableEvent()); -} - -void AOC_U::NotifyMountAddOnContent(HLERequestContext& ctx) { - LOG_WARNING(Service_AOC, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void AOC_U::NotifyUnmountAddOnContent(HLERequestContext& ctx) { - LOG_WARNING(Service_AOC, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void AOC_U::CheckAddOnContentMountStatus(HLERequestContext& ctx) { - LOG_WARNING(Service_AOC, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); -} - -void AOC_U::CreateEcPurchasedEventManager(HLERequestContext& ctx) { - LOG_WARNING(Service_AOC, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IPurchaseEventManager>(system); -} - -void AOC_U::CreatePermanentEcPurchasedEventManager(HLERequestContext& ctx) { - LOG_WARNING(Service_AOC, "(STUBBED) called"); - - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(ResultSuccess); - rb.PushIpcInterface<IPurchaseEventManager>(system); -} - -void LoopProcess(Core::System& system) { - auto server_manager = std::make_unique<ServerManager>(system); - server_manager->RegisterNamedService("aoc:u", std::make_shared<AOC_U>(system)); - ServerManager::RunServer(std::move(server_manager)); -} - -} // namespace Service::AOC diff --git a/src/core/hle/service/aoc/aoc_u.h b/src/core/hle/service/aoc/aoc_u.h deleted file mode 100644 index 12ccfeb6a..000000000 --- a/src/core/hle/service/aoc/aoc_u.h +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "core/hle/service/kernel_helpers.h" -#include "core/hle/service/service.h" - -namespace Core { -class System; -} - -namespace Kernel { -class KEvent; -} - -namespace Service::AOC { - -class AOC_U final : public ServiceFramework<AOC_U> { -public: - explicit AOC_U(Core::System& system); - ~AOC_U() override; - -private: - void CountAddOnContent(HLERequestContext& ctx); - void ListAddOnContent(HLERequestContext& ctx); - void GetAddOnContentBaseId(HLERequestContext& ctx); - void PrepareAddOnContent(HLERequestContext& ctx); - void GetAddOnContentListChangedEvent(HLERequestContext& ctx); - void GetAddOnContentListChangedEventWithProcessId(HLERequestContext& ctx); - void NotifyMountAddOnContent(HLERequestContext& ctx); - void NotifyUnmountAddOnContent(HLERequestContext& ctx); - void CheckAddOnContentMountStatus(HLERequestContext& ctx); - void CreateEcPurchasedEventManager(HLERequestContext& ctx); - void CreatePermanentEcPurchasedEventManager(HLERequestContext& ctx); - - std::vector<u64> add_on_content; - KernelHelpers::ServiceContext service_context; - - Kernel::KEvent* aoc_change_event; -}; - -void LoopProcess(Core::System& system); - -} // namespace Service::AOC diff --git a/src/core/hle/service/aoc/purchase_event_manager.cpp b/src/core/hle/service/aoc/purchase_event_manager.cpp new file mode 100644 index 000000000..9e718510b --- /dev/null +++ b/src/core/hle/service/aoc/purchase_event_manager.cpp @@ -0,0 +1,67 @@ +// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/hle/service/aoc/purchase_event_manager.h" +#include "core/hle/service/cmif_serialization.h" + +namespace Service::AOC { + +constexpr Result ResultNoPurchasedProductInfoAvailable{ErrorModule::NIMShop, 400}; + +IPurchaseEventManager::IPurchaseEventManager(Core::System& system_) + : ServiceFramework{system_, "IPurchaseEventManager"}, service_context{system, + "IPurchaseEventManager"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&IPurchaseEventManager::SetDefaultDeliveryTarget>, "SetDefaultDeliveryTarget"}, + {1, D<&IPurchaseEventManager::SetDeliveryTarget>, "SetDeliveryTarget"}, + {2, D<&IPurchaseEventManager::GetPurchasedEvent>, "GetPurchasedEvent"}, + {3, D<&IPurchaseEventManager::PopPurchasedProductInfo>, "PopPurchasedProductInfo"}, + {4, D<&IPurchaseEventManager::PopPurchasedProductInfoWithUid>, "PopPurchasedProductInfoWithUid"}, + }; + // clang-format on + + RegisterHandlers(functions); + + purchased_event = service_context.CreateEvent("IPurchaseEventManager:PurchasedEvent"); +} + +IPurchaseEventManager::~IPurchaseEventManager() { + service_context.CloseEvent(purchased_event); +} + +Result IPurchaseEventManager::SetDefaultDeliveryTarget( + ClientProcessId process_id, InBuffer<BufferAttr_HipcMapAlias> in_buffer) { + LOG_WARNING(Service_AOC, "(STUBBED) called, process_id={}", process_id.pid); + + R_SUCCEED(); +} + +Result IPurchaseEventManager::SetDeliveryTarget(u64 unknown, + InBuffer<BufferAttr_HipcMapAlias> in_buffer) { + LOG_WARNING(Service_AOC, "(STUBBED) called, unknown={}", unknown); + + R_SUCCEED(); +} + +Result IPurchaseEventManager::GetPurchasedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_WARNING(Service_AOC, "called"); + + *out_event = &purchased_event->GetReadableEvent(); + + R_SUCCEED(); +} + +Result IPurchaseEventManager::PopPurchasedProductInfo() { + LOG_DEBUG(Service_AOC, "(STUBBED) called"); + + R_RETURN(ResultNoPurchasedProductInfoAvailable); +} + +Result IPurchaseEventManager::PopPurchasedProductInfoWithUid() { + LOG_DEBUG(Service_AOC, "(STUBBED) called"); + + R_RETURN(ResultNoPurchasedProductInfoAvailable); +} + +} // namespace Service::AOC diff --git a/src/core/hle/service/aoc/purchase_event_manager.h b/src/core/hle/service/aoc/purchase_event_manager.h new file mode 100644 index 000000000..ea3836bc9 --- /dev/null +++ b/src/core/hle/service/aoc/purchase_event_manager.h @@ -0,0 +1,30 @@ +// 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/kernel_helpers.h" +#include "core/hle/service/os/event.h" +#include "core/hle/service/service.h" + +namespace Service::AOC { + +class IPurchaseEventManager final : public ServiceFramework<IPurchaseEventManager> { +public: + explicit IPurchaseEventManager(Core::System& system_); + ~IPurchaseEventManager() override; + + Result SetDefaultDeliveryTarget(ClientProcessId process_id, + InBuffer<BufferAttr_HipcMapAlias> in_buffer); + Result SetDeliveryTarget(u64 unknown, InBuffer<BufferAttr_HipcMapAlias> in_buffer); + Result GetPurchasedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); + Result PopPurchasedProductInfo(); + Result PopPurchasedProductInfoWithUid(); + +private: + KernelHelpers::ServiceContext service_context; + Kernel::KEvent* purchased_event; +}; + +} // namespace Service::AOC diff --git a/src/core/hle/service/audio/audio_controller.cpp b/src/core/hle/service/audio/audio_controller.cpp index c9804cf9c..7a51d1023 100644 --- a/src/core/hle/service/audio/audio_controller.cpp +++ b/src/core/hle/service/audio/audio_controller.cpp @@ -138,7 +138,7 @@ Result IAudioController::SetOutputModeSetting(Set::AudioOutputModeTarget target, } Result IAudioController::SetHeadphoneOutputLevelMode(HeadphoneOutputLevelMode output_level_mode) { - LOG_WARNING(Audio, "(STUBBED) called"); + LOG_WARNING(Audio, "(STUBBED) called, output_level_mode={}", output_level_mode); R_SUCCEED(); } diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp index 38cdd57ad..83618a956 100644 --- a/src/core/hle/service/btdrv/btdrv.cpp +++ b/src/core/hle/service/btdrv/btdrv.cpp @@ -5,6 +5,7 @@ #include "core/core.h" #include "core/hle/kernel/k_event.h" #include "core/hle/service/btdrv/btdrv.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/kernel_helpers.h" #include "core/hle/service/server_manager.h" @@ -13,9 +14,9 @@ namespace Service::BtDrv { -class Bt final : public ServiceFramework<Bt> { +class IBluetoothUser final : public ServiceFramework<IBluetoothUser> { public: - explicit Bt(Core::System& system_) + explicit IBluetoothUser(Core::System& system_) : ServiceFramework{system_, "bt"}, service_context{system_, "bt"} { // clang-format off static const FunctionInfo functions[] = { @@ -28,7 +29,7 @@ public: {6, nullptr, "SetLeResponse"}, {7, nullptr, "LeSendIndication"}, {8, nullptr, "GetLeEventInfo"}, - {9, &Bt::RegisterBleEvent, "RegisterBleEvent"}, + {9, C<&IBluetoothUser::RegisterBleEvent>, "RegisterBleEvent"}, }; // clang-format on RegisterHandlers(functions); @@ -36,17 +37,16 @@ public: register_event = service_context.CreateEvent("BT:RegisterEvent"); } - ~Bt() override { + ~IBluetoothUser() override { service_context.CloseEvent(register_event); } private: - void RegisterBleEvent(HLERequestContext& ctx) { + Result RegisterBleEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) { LOG_WARNING(Service_BTM, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 2, 1}; - rb.Push(ResultSuccess); - rb.PushCopyObjects(register_event->GetReadableEvent()); + *out_event = ®ister_event->GetReadableEvent(); + R_SUCCEED(); } KernelHelpers::ServiceContext service_context; @@ -54,9 +54,9 @@ private: Kernel::KEvent* register_event; }; -class BtDrv final : public ServiceFramework<BtDrv> { +class IBluetoothDriver final : public ServiceFramework<IBluetoothDriver> { public: - explicit BtDrv(Core::System& system_) : ServiceFramework{system_, "btdrv"} { + explicit IBluetoothDriver(Core::System& system_) : ServiceFramework{system_, "btdrv"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "InitializeBluetoothDriver"}, @@ -93,7 +93,7 @@ public: {31, nullptr, "EnableMcMode"}, {32, nullptr, "EnableLlrScan"}, {33, nullptr, "DisableLlrScan"}, - {34, nullptr, "EnableRadio"}, + {34, C<&IBluetoothDriver::EnableRadio>, "EnableRadio"}, {35, nullptr, "SetVisibility"}, {36, nullptr, "EnableTbfcScan"}, {37, nullptr, "RegisterHidReportEvent"}, @@ -195,13 +195,19 @@ public: RegisterHandlers(functions); } + +private: + Result EnableRadio() { + LOG_WARNING(Service_BTDRV, "(STUBBED) called"); + R_SUCCEED(); + } }; void LoopProcess(Core::System& system) { auto server_manager = std::make_unique<ServerManager>(system); - server_manager->RegisterNamedService("btdrv", std::make_shared<BtDrv>(system)); - server_manager->RegisterNamedService("bt", std::make_shared<Bt>(system)); + server_manager->RegisterNamedService("btdrv", std::make_shared<IBluetoothDriver>(system)); + server_manager->RegisterNamedService("bt", std::make_shared<IBluetoothUser>(system)); ServerManager::RunServer(std::move(server_manager)); } diff --git a/src/core/hle/service/erpt/erpt.cpp b/src/core/hle/service/erpt/erpt.cpp index 39ae3a723..6b7eab5ef 100644 --- a/src/core/hle/service/erpt/erpt.cpp +++ b/src/core/hle/service/erpt/erpt.cpp @@ -18,7 +18,7 @@ public: // clang-format off static const FunctionInfo functions[] = { {0, C<&ErrorReportContext::SubmitContext>, "SubmitContext"}, - {1, nullptr, "CreateReportV0"}, + {1, C<&ErrorReportContext::CreateReportV0>, "CreateReportV0"}, {2, nullptr, "SetInitialLaunchSettingsCompletionTime"}, {3, nullptr, "ClearInitialLaunchSettingsCompletionTime"}, {4, nullptr, "UpdatePowerOnTime"}, @@ -28,7 +28,8 @@ public: {8, nullptr, "ClearApplicationLaunchTime"}, {9, nullptr, "SubmitAttachment"}, {10, nullptr, "CreateReportWithAttachments"}, - {11, nullptr, "CreateReport"}, + {11, C<&ErrorReportContext::CreateReportV1>, "CreateReportV1"}, + {12, C<&ErrorReportContext::CreateReport>, "CreateReport"}, {20, nullptr, "RegisterRunningApplet"}, {21, nullptr, "UnregisterRunningApplet"}, {22, nullptr, "UpdateAppletSuspendedDuration"}, @@ -40,10 +41,37 @@ public: } 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()); + Result SubmitContext(InBuffer<BufferAttr_HipcMapAlias> context_entry, + InBuffer<BufferAttr_HipcMapAlias> field_list) { + LOG_WARNING(Service_SET, "(STUBBED) called, context_entry_size={}, field_list_size={}", + context_entry.size(), field_list.size()); + R_SUCCEED(); + } + + Result CreateReportV0(u32 report_type, InBuffer<BufferAttr_HipcMapAlias> context_entry, + InBuffer<BufferAttr_HipcMapAlias> report_list, + InBuffer<BufferAttr_HipcMapAlias> report_meta_data) { + LOG_WARNING(Service_SET, "(STUBBED) called, report_type={:#x}", report_type); + R_SUCCEED(); + } + + Result CreateReportV1(u32 report_type, u32 unknown, + InBuffer<BufferAttr_HipcMapAlias> context_entry, + InBuffer<BufferAttr_HipcMapAlias> report_list, + InBuffer<BufferAttr_HipcMapAlias> report_meta_data) { + LOG_WARNING(Service_SET, "(STUBBED) called, report_type={:#x}, unknown={:#x}", report_type, + unknown); + R_SUCCEED(); + } + + Result CreateReport(u32 report_type, u32 unknown, u32 create_report_option_flag, + InBuffer<BufferAttr_HipcMapAlias> context_entry, + InBuffer<BufferAttr_HipcMapAlias> report_list, + InBuffer<BufferAttr_HipcMapAlias> report_meta_data) { + LOG_WARNING( + Service_SET, + "(STUBBED) called, report_type={:#x}, unknown={:#x}, create_report_option_flag={:#x}", + report_type, unknown, create_report_option_flag); R_SUCCEED(); } }; diff --git a/src/core/hle/service/filesystem/fsp/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp/fsp_srv.cpp index 223284255..60290f1a6 100644 --- a/src/core/hle/service/filesystem/fsp/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp/fsp_srv.cpp @@ -71,7 +71,7 @@ FSP_SRV::FSP_SRV(Core::System& system_) {28, nullptr, "DeleteSaveDataFileSystemBySaveDataAttribute"}, {30, nullptr, "OpenGameCardStorage"}, {31, nullptr, "OpenGameCardFileSystem"}, - {32, nullptr, "ExtendSaveDataFileSystem"}, + {32, D<&FSP_SRV::ExtendSaveDataFileSystem>, "ExtendSaveDataFileSystem"}, {33, nullptr, "DeleteCacheStorage"}, {34, D<&FSP_SRV::GetCacheStorageSize>, "GetCacheStorageSize"}, {35, nullptr, "CreateSaveDataFileSystemByHashSalt"}, @@ -79,9 +79,9 @@ FSP_SRV::FSP_SRV(Core::System& system_) {51, D<&FSP_SRV::OpenSaveDataFileSystem>, "OpenSaveDataFileSystem"}, {52, D<&FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId>, "OpenSaveDataFileSystemBySystemSaveDataId"}, {53, D<&FSP_SRV::OpenReadOnlySaveDataFileSystem>, "OpenReadOnlySaveDataFileSystem"}, - {57, nullptr, "ReadSaveDataFileSystemExtraDataBySaveDataSpaceId"}, - {58, nullptr, "ReadSaveDataFileSystemExtraData"}, - {59, nullptr, "WriteSaveDataFileSystemExtraData"}, + {57, D<&FSP_SRV::ReadSaveDataFileSystemExtraDataBySaveDataSpaceId>, "ReadSaveDataFileSystemExtraDataBySaveDataSpaceId"}, + {58, D<&FSP_SRV::ReadSaveDataFileSystemExtraData>, "ReadSaveDataFileSystemExtraData"}, + {59, D<&FSP_SRV::WriteSaveDataFileSystemExtraData>, "WriteSaveDataFileSystemExtraData"}, {60, nullptr, "OpenSaveDataInfoReader"}, {61, D<&FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId>, "OpenSaveDataInfoReaderBySaveDataSpaceId"}, {62, D<&FSP_SRV::OpenSaveDataInfoReaderOnlyCacheStorage>, "OpenSaveDataInfoReaderOnlyCacheStorage"}, @@ -90,8 +90,8 @@ FSP_SRV::FSP_SRV(Core::System& system_) {66, nullptr, "WriteSaveDataFileSystemExtraData2"}, {67, D<&FSP_SRV::FindSaveDataWithFilter>, "FindSaveDataWithFilter"}, {68, nullptr, "OpenSaveDataInfoReaderBySaveDataFilter"}, - {69, nullptr, "ReadSaveDataFileSystemExtraDataBySaveDataAttribute"}, - {70, D<&FSP_SRV::WriteSaveDataFileSystemExtraDataBySaveDataAttribute>, "WriteSaveDataFileSystemExtraDataBySaveDataAttribute"}, + {69, D<&FSP_SRV::ReadSaveDataFileSystemExtraDataBySaveDataAttribute>, "ReadSaveDataFileSystemExtraDataBySaveDataAttribute"}, + {70, D<&FSP_SRV::WriteSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute>, "WriteSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute"}, {71, D<&FSP_SRV::ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute>, "ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute"}, {80, nullptr, "OpenSaveDataMetaFile"}, {81, nullptr, "OpenSaveDataTransferManager"}, @@ -317,9 +317,23 @@ Result FSP_SRV::FindSaveDataWithFilter(Out<s64> out_count, R_THROW(FileSys::ResultTargetNotFound); } -Result FSP_SRV::WriteSaveDataFileSystemExtraDataBySaveDataAttribute() { - LOG_WARNING(Service_FS, "(STUBBED) called."); +Result FSP_SRV::WriteSaveDataFileSystemExtraData(InBuffer<BufferAttr_HipcMapAlias> buffer, + FileSys::SaveDataSpaceId space_id, + u64 save_data_id) { + LOG_WARNING(Service_FS, "(STUBBED) called, space_id={}, save_data_id={:016X}", space_id, + save_data_id); + R_SUCCEED(); +} +Result FSP_SRV::WriteSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute( + InBuffer<BufferAttr_HipcMapAlias> buffer, InBuffer<BufferAttr_HipcMapAlias> mask_buffer, + FileSys::SaveDataSpaceId space_id, FileSys::SaveDataAttribute attribute) { + LOG_WARNING(Service_FS, + "(STUBBED) called, space_id={}, attribute.program_id={:016X}\n" + "attribute.user_id={:016X}{:016X}, attribute.save_id={:016X}\n" + "attribute.type={}, attribute.rank={}, attribute.index={}", + space_id, attribute.program_id, attribute.user_id[1], attribute.user_id[0], + attribute.system_save_data_id, attribute.type, attribute.rank, attribute.index); R_SUCCEED(); } @@ -341,6 +355,38 @@ Result FSP_SRV::ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute( R_SUCCEED(); } +Result FSP_SRV::ReadSaveDataFileSystemExtraData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer, + u64 save_data_id) { + // Stub, backend needs an impl to read/write the SaveDataExtraData + LOG_WARNING(Service_FS, "(STUBBED) called, save_data_id={:016X}", save_data_id); + std::memset(out_buffer.data(), 0, out_buffer.size()); + R_SUCCEED(); +} + +Result FSP_SRV::ReadSaveDataFileSystemExtraDataBySaveDataAttribute( + OutBuffer<BufferAttr_HipcMapAlias> out_buffer, FileSys::SaveDataSpaceId space_id, + FileSys::SaveDataAttribute attribute) { + // Stub, backend needs an impl to read/write the SaveDataExtraData + LOG_WARNING(Service_FS, + "(STUBBED) called, space_id={}, attribute.program_id={:016X}\n" + "attribute.user_id={:016X}{:016X}, attribute.save_id={:016X}\n" + "attribute.type={}, attribute.rank={}, attribute.index={}", + space_id, attribute.program_id, attribute.user_id[1], attribute.user_id[0], + attribute.system_save_data_id, attribute.type, attribute.rank, attribute.index); + std::memset(out_buffer.data(), 0, out_buffer.size()); + R_SUCCEED(); +} + +Result FSP_SRV::ReadSaveDataFileSystemExtraDataBySaveDataSpaceId( + OutBuffer<BufferAttr_HipcMapAlias> out_buffer, FileSys::SaveDataSpaceId space_id, + u64 save_data_id) { + // Stub, backend needs an impl to read/write the SaveDataExtraData + LOG_WARNING(Service_FS, "(STUBBED) called, space_id={}, save_data_id={:016X}", space_id, + save_data_id); + std::memset(out_buffer.data(), 0, out_buffer.size()); + R_SUCCEED(); +} + Result FSP_SRV::OpenSaveDataTransferProhibiter( OutInterface<ISaveDataTransferProhibiter> out_prohibiter, u64 id) { LOG_WARNING(Service_FS, "(STUBBED) called, id={:016X}", id); @@ -476,6 +522,16 @@ Result FSP_SRV::FlushAccessLogOnSdCard() { R_SUCCEED(); } +Result FSP_SRV::ExtendSaveDataFileSystem(FileSys::SaveDataSpaceId space_id, u64 save_data_id, + s64 available_size, s64 journal_size) { + // We don't have an index of save data ids, so we can't implement this. + LOG_WARNING(Service_FS, + "(STUBBED) called, space_id={}, save_data_id={:016X}, available_size={:#x}, " + "journal_size={:#x}", + space_id, save_data_id, available_size, journal_size); + R_SUCCEED(); +} + Result FSP_SRV::GetCacheStorageSize(s32 index, Out<s64> out_data_size, Out<s64> out_journal_size) { LOG_WARNING(Service_FS, "(STUBBED) called with index={}", index); diff --git a/src/core/hle/service/filesystem/fsp/fsp_srv.h b/src/core/hle/service/filesystem/fsp/fsp_srv.h index 83d9cb51c..b565cace0 100644 --- a/src/core/hle/service/filesystem/fsp/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp/fsp_srv.h @@ -70,7 +70,19 @@ private: Result FindSaveDataWithFilter(Out<s64> out_count, OutBuffer<BufferAttr_HipcMapAlias> out_buffer, FileSys::SaveDataSpaceId space_id, FileSys::SaveDataFilter filter); - Result WriteSaveDataFileSystemExtraDataBySaveDataAttribute(); + Result WriteSaveDataFileSystemExtraData(InBuffer<BufferAttr_HipcMapAlias> buffer, + FileSys::SaveDataSpaceId space_id, u64 save_data_id); + Result WriteSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute( + InBuffer<BufferAttr_HipcMapAlias> buffer, InBuffer<BufferAttr_HipcMapAlias> mask_buffer, + FileSys::SaveDataSpaceId space_id, FileSys::SaveDataAttribute attribute); + Result ReadSaveDataFileSystemExtraData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer, + u64 save_data_id); + Result ReadSaveDataFileSystemExtraDataBySaveDataAttribute( + OutBuffer<BufferAttr_HipcMapAlias> out_buffer, FileSys::SaveDataSpaceId space_id, + FileSys::SaveDataAttribute attribute); + Result ReadSaveDataFileSystemExtraDataBySaveDataSpaceId( + OutBuffer<BufferAttr_HipcMapAlias> out_buffer, FileSys::SaveDataSpaceId space_id, + u64 save_data_id); Result ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute( FileSys::SaveDataSpaceId space_id, FileSys::SaveDataAttribute attribute, InBuffer<BufferAttr_HipcMapAlias> mask_buffer, @@ -91,6 +103,8 @@ private: Result GetProgramIndexForAccessLog(Out<AccessLogVersion> out_access_log_version, Out<u32> out_access_log_program_index); Result OpenMultiCommitManager(OutInterface<IMultiCommitManager> out_interface); + Result ExtendSaveDataFileSystem(FileSys::SaveDataSpaceId space_id, u64 save_data_id, + s64 available_size, s64 journal_size); Result GetCacheStorageSize(s32 index, Out<s64> out_data_size, Out<s64> out_journal_size); FileSystemController& fsc; diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp index aeb849efa..38e62761b 100644 --- a/src/core/hle/service/friend/friend.cpp +++ b/src/core/hle/service/friend/friend.cpp @@ -42,13 +42,13 @@ public: {10701, nullptr, "GetPlayHistoryRegistrationKeyWithNetworkServiceAccountId"}, {10702, nullptr, "AddPlayHistory"}, {11000, nullptr, "GetProfileImageUrl"}, - {20100, nullptr, "GetFriendCount"}, - {20101, nullptr, "GetNewlyFriendCount"}, + {20100, &IFriendService::GetFriendCount, "GetFriendCount"}, + {20101, &IFriendService::GetNewlyFriendCount, "GetNewlyFriendCount"}, {20102, nullptr, "GetFriendDetailedInfo"}, {20103, nullptr, "SyncFriendList"}, {20104, nullptr, "RequestSyncFriendList"}, {20110, nullptr, "LoadFriendSetting"}, - {20200, nullptr, "GetReceivedFriendRequestCount"}, + {20200, &IFriendService::GetReceivedFriendRequestCount, "GetReceivedFriendRequestCount"}, {20201, nullptr, "GetFriendRequestList"}, {20300, nullptr, "GetFriendCandidateList"}, {20301, nullptr, "GetNintendoNetworkIdInfo"}, @@ -61,14 +61,14 @@ public: {20501, nullptr, "GetRelationship"}, {20600, nullptr, "GetUserPresenceView"}, {20700, nullptr, "GetPlayHistoryList"}, - {20701, nullptr, "GetPlayHistoryStatistics"}, + {20701, &IFriendService::GetPlayHistoryStatistics, "GetPlayHistoryStatistics"}, {20800, nullptr, "LoadUserSetting"}, {20801, nullptr, "SyncUserSetting"}, {20900, nullptr, "RequestListSummaryOverlayNotification"}, {21000, nullptr, "GetExternalApplicationCatalog"}, {22000, nullptr, "GetReceivedFriendInvitationList"}, {22001, nullptr, "GetReceivedFriendInvitationDetailedInfo"}, - {22010, nullptr, "GetReceivedFriendInvitationCountCache"}, + {22010, &IFriendService::GetReceivedFriendInvitationCountCache, "GetReceivedFriendInvitationCountCache"}, {30100, nullptr, "DropFriendNewlyFlags"}, {30101, nullptr, "DeleteFriend"}, {30110, nullptr, "DropFriendNewlyFlag"}, @@ -144,6 +144,33 @@ private: rb.PushCopyObjects(completion_event->GetReadableEvent()); } + void GetFriendList(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto friend_offset = rp.Pop<u32>(); + const auto uuid = rp.PopRaw<Common::UUID>(); + [[maybe_unused]] const auto filter = rp.PopRaw<SizedFriendFilter>(); + const auto pid = rp.Pop<u64>(); + LOG_WARNING(Service_Friend, "(STUBBED) called, offset={}, uuid=0x{}, pid={}", friend_offset, + uuid.RawString(), pid); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + + rb.Push<u32>(0); // Friend count + // TODO(ogniK): Return a buffer of u64s which are the "NetworkServiceAccountId" + } + + void CheckFriendListAvailability(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto uuid{rp.PopRaw<Common::UUID>()}; + + LOG_WARNING(Service_Friend, "(STUBBED) called, uuid=0x{}", uuid.RawString()); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(true); + } + void GetBlockedUserListIds(HLERequestContext& ctx) { // This is safe to stub, as there should be no adverse consequences from reporting no // blocked users. @@ -153,6 +180,17 @@ private: rb.Push<u32>(0); // Indicates there are no blocked users } + void CheckBlockedUserListAvailability(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto uuid{rp.PopRaw<Common::UUID>()}; + + LOG_WARNING(Service_Friend, "(STUBBED) called, uuid=0x{}", uuid.RawString()); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(true); + } + void DeclareCloseOnlinePlaySession(HLERequestContext& ctx) { // Stub used by Splatoon 2 LOG_WARNING(Service_Friend, "(STUBBED) called"); @@ -179,42 +217,43 @@ private: rb.Push(ResultSuccess); } - void GetFriendList(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto friend_offset = rp.Pop<u32>(); - const auto uuid = rp.PopRaw<Common::UUID>(); - [[maybe_unused]] const auto filter = rp.PopRaw<SizedFriendFilter>(); - const auto pid = rp.Pop<u64>(); - LOG_WARNING(Service_Friend, "(STUBBED) called, offset={}, uuid=0x{}, pid={}", friend_offset, - uuid.RawString(), pid); + void GetFriendCount(HLERequestContext& ctx) { + LOG_DEBUG(Service_Friend, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - - rb.Push<u32>(0); // Friend count - // TODO(ogniK): Return a buffer of u64s which are the "NetworkServiceAccountId" + rb.Push(0); } - void CheckFriendListAvailability(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto uuid{rp.PopRaw<Common::UUID>()}; + void GetNewlyFriendCount(HLERequestContext& ctx) { + LOG_DEBUG(Service_Friend, "(STUBBED) called"); - LOG_WARNING(Service_Friend, "(STUBBED) called, uuid=0x{}", uuid.RawString()); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(0); + } + + void GetReceivedFriendRequestCount(HLERequestContext& ctx) { + LOG_DEBUG(Service_Friend, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(true); + rb.Push(0); } - void CheckBlockedUserListAvailability(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto uuid{rp.PopRaw<Common::UUID>()}; + void GetPlayHistoryStatistics(HLERequestContext& ctx) { + LOG_ERROR(Service_Friend, "(STUBBED) called, check in out"); - LOG_WARNING(Service_Friend, "(STUBBED) called, uuid=0x{}", uuid.RawString()); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + } + + void GetReceivedFriendInvitationCountCache(HLERequestContext& ctx) { + LOG_DEBUG(Service_Friend, "(STUBBED) called, check in out"); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(ResultSuccess); - rb.Push(true); + rb.Push(0); } KernelHelpers::ServiceContext service_context; diff --git a/src/core/hle/service/glue/time/manager.cpp b/src/core/hle/service/glue/time/manager.cpp index 059ac3fc9..cb88486dd 100644 --- a/src/core/hle/service/glue/time/manager.cpp +++ b/src/core/hle/service/glue/time/manager.cpp @@ -51,16 +51,17 @@ s64 CalendarTimeToEpoch(Service::PSC::Time::CalendarTime calendar) { } s64 GetEpochTimeFromInitialYear(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys) { + s32 year{2000}; + set_sys->GetSettingsItemValueImpl(year, "time", "standard_user_clock_initial_year"); + Service::PSC::Time::CalendarTime calendar{ - .year = 2000, + .year = static_cast<s16>(year), .month = 1, .day = 1, .hour = 0, .minute = 0, .second = 0, }; - set_sys->GetSettingsItemValueImpl<s16>(calendar.year, "time", - "standard_user_clock_initial_year"); return CalendarTimeToEpoch(calendar); } diff --git a/src/core/hle/service/glue/time/worker.cpp b/src/core/hle/service/glue/time/worker.cpp index b28569b68..b6bbd7965 100644 --- a/src/core/hle/service/glue/time/worker.cpp +++ b/src/core/hle/service/glue/time/worker.cpp @@ -26,12 +26,9 @@ Service::PSC::Time::SystemClockContext g_report_ephemeral_clock_context{}; template <typename T> T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys, const char* category, const char* name) { - std::vector<u8> interval_buf; - auto res = set_sys->GetSettingsItemValueImpl(interval_buf, category, name); - ASSERT(res == ResultSuccess); - T v{}; - std::memcpy(&v, interval_buf.data(), sizeof(T)); + auto res = set_sys->GetSettingsItemValueImpl(v, category, name); + ASSERT(res == ResultSuccess); return v; } diff --git a/src/core/hle/service/hid/hid_system_server.cpp b/src/core/hle/service/hid/hid_system_server.cpp index 7126a1dcd..b0cd63d72 100644 --- a/src/core/hle/service/hid/hid_system_server.cpp +++ b/src/core/hle/service/hid/hid_system_server.cpp @@ -201,7 +201,7 @@ IHidSystemServer::IHidSystemServer(Core::System& system_, std::shared_ptr<Resour {1269, nullptr, "DeleteButtonConfigStorageLeft"}, {1270, nullptr, "DeleteButtonConfigStorageRight"}, {1271, &IHidSystemServer::IsUsingCustomButtonConfig, "IsUsingCustomButtonConfig"}, - {1272, nullptr, "IsAnyCustomButtonConfigEnabled"}, + {1272, &IHidSystemServer::IsAnyCustomButtonConfigEnabled, "IsAnyCustomButtonConfigEnabled"}, {1273, nullptr, "SetAllCustomButtonConfigEnabled"}, {1274, nullptr, "SetDefaultButtonConfig"}, {1275, nullptr, "SetAllDefaultButtonConfig"}, @@ -926,6 +926,16 @@ void IHidSystemServer::IsUsingCustomButtonConfig(HLERequestContext& ctx) { rb.Push(is_enabled); } +void IHidSystemServer::IsAnyCustomButtonConfigEnabled(HLERequestContext& ctx) { + const bool is_enabled = false; + + LOG_DEBUG(Service_HID, "(STUBBED) called, is_enabled={}", is_enabled); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(is_enabled); +} + std::shared_ptr<ResourceManager> IHidSystemServer::GetResourceManager() { resource_manager->Initialize(); return resource_manager; diff --git a/src/core/hle/service/hid/hid_system_server.h b/src/core/hle/service/hid/hid_system_server.h index 738313e08..1a4f244d7 100644 --- a/src/core/hle/service/hid/hid_system_server.h +++ b/src/core/hle/service/hid/hid_system_server.h @@ -77,6 +77,7 @@ private: void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx); void SetForceHandheldStyleVibration(HLERequestContext& ctx); void IsUsingCustomButtonConfig(HLERequestContext& ctx); + void IsAnyCustomButtonConfigEnabled(HLERequestContext& ctx); std::shared_ptr<ResourceManager> GetResourceManager(); diff --git a/src/core/hle/service/lbl/lbl.cpp b/src/core/hle/service/lbl/lbl.cpp index 98a79365d..c14b24142 100644 --- a/src/core/hle/service/lbl/lbl.cpp +++ b/src/core/hle/service/lbl/lbl.cpp @@ -18,8 +18,8 @@ public: explicit LBL(Core::System& system_) : ServiceFramework{system_, "lbl"} { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "SaveCurrentSetting"}, - {1, nullptr, "LoadCurrentSetting"}, + {0, &LBL::SaveCurrentSetting, "SaveCurrentSetting"}, + {1, &LBL::LoadCurrentSetting, "LoadCurrentSetting"}, {2, &LBL::SetCurrentBrightnessSetting, "SetCurrentBrightnessSetting"}, {3, &LBL::GetCurrentBrightnessSetting, "GetCurrentBrightnessSetting"}, {4, nullptr, "ApplyCurrentBrightnessSettingToBacklight"}, @@ -47,7 +47,7 @@ public: {26, &LBL::EnableVrMode, "EnableVrMode"}, {27, &LBL::DisableVrMode, "DisableVrMode"}, {28, &LBL::IsVrModeEnabled, "IsVrModeEnabled"}, - {29, nullptr, "IsAutoBrightnessControlSupported"}, + {29, &LBL::IsAutoBrightnessControlSupported, "IsAutoBrightnessControlSupported"}, }; // clang-format on @@ -60,6 +60,20 @@ private: On = 1, }; + void SaveCurrentSetting(HLERequestContext& ctx) { + LOG_WARNING(Service_LBL, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + } + + void LoadCurrentSetting(HLERequestContext& ctx) { + LOG_WARNING(Service_LBL, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + } + void SetCurrentBrightnessSetting(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; auto brightness = rp.Pop<float>(); @@ -310,6 +324,14 @@ private: rb.Push(vr_mode_enabled); } + void IsAutoBrightnessControlSupported(HLERequestContext& ctx) { + LOG_DEBUG(Service_LBL, "called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push<u8>(auto_brightness_supported); + } + bool vr_mode_enabled = false; float current_brightness = 1.0f; float ambient_light_value = 0.0f; @@ -317,7 +339,8 @@ private: bool dimming = true; bool backlight_enabled = true; bool update_instantly = false; - bool auto_brightness = false; // TODO(ogniK): Move to system settings + bool auto_brightness = false; + bool auto_brightness_supported = true; // TODO(ogniK): Move to system settings }; void LoopProcess(Core::System& system) { diff --git a/src/core/hle/service/ldn/monitor_service.cpp b/src/core/hle/service/ldn/monitor_service.cpp index 3471f69da..ea6ac4d5d 100644 --- a/src/core/hle/service/ldn/monitor_service.cpp +++ b/src/core/hle/service/ldn/monitor_service.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later #include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/ldn/ldn_results.h" #include "core/hle/service/ldn/monitor_service.h" namespace Service::LDN { @@ -17,7 +18,7 @@ IMonitorService::IMonitorService(Core::System& system_) {4, nullptr, "GetSecurityParameterForMonitor"}, {5, nullptr, "GetNetworkConfigForMonitor"}, {100, C<&IMonitorService::InitializeMonitor>, "InitializeMonitor"}, - {101, nullptr, "FinalizeMonitor"}, + {101, C<&IMonitorService::FinalizeMonitor>, "FinalizeMonitor"}, }; // clang-format on @@ -27,16 +28,18 @@ IMonitorService::IMonitorService(Core::System& system_) IMonitorService::~IMonitorService() = default; Result IMonitorService::GetStateForMonitor(Out<State> out_state) { - LOG_INFO(Service_LDN, "called"); - - *out_state = state; + LOG_WARNING(Service_LDN, "(STUBBED) called"); + *out_state = State::None; R_SUCCEED(); } Result IMonitorService::InitializeMonitor() { LOG_INFO(Service_LDN, "called"); + R_SUCCEED(); +} - state = State::Initialized; +Result IMonitorService::FinalizeMonitor() { + LOG_INFO(Service_LDN, "called"); R_SUCCEED(); } diff --git a/src/core/hle/service/ldn/monitor_service.h b/src/core/hle/service/ldn/monitor_service.h index 61aacef30..e663145b4 100644 --- a/src/core/hle/service/ldn/monitor_service.h +++ b/src/core/hle/service/ldn/monitor_service.h @@ -21,6 +21,7 @@ public: private: Result GetStateForMonitor(Out<State> out_state); Result InitializeMonitor(); + Result FinalizeMonitor(); State state{State::None}; }; diff --git a/src/core/hle/service/nfc/common/device_manager.cpp b/src/core/hle/service/nfc/common/device_manager.cpp index 94a8243b5..2dd3e9f89 100644 --- a/src/core/hle/service/nfc/common/device_manager.cpp +++ b/src/core/hle/service/nfc/common/device_manager.cpp @@ -13,6 +13,7 @@ #include "core/hle/service/nfc/nfc_result.h" #include "core/hle/service/psc/time/steady_clock.h" #include "core/hle/service/service.h" +#include "core/hle/service/set/system_settings_server.h" #include "core/hle/service/sm/sm.h" #include "hid_core/hid_types.h" #include "hid_core/hid_util.h" @@ -32,6 +33,9 @@ DeviceManager::DeviceManager(Core::System& system_, KernelHelpers::ServiceContex } is_initialized = false; + + m_set_sys = + system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true); } DeviceManager ::~DeviceManager() { @@ -774,8 +778,8 @@ Result DeviceManager::CheckDeviceState(std::shared_ptr<NfcDevice> device) const } Result DeviceManager::IsNfcEnabled() const { - // TODO: This calls nn::settings::detail::GetNfcEnableFlag - const bool is_enabled = true; + bool is_enabled{}; + R_TRY(m_set_sys->GetNfcEnableFlag(&is_enabled)); if (!is_enabled) { return ResultNfcDisabled; } diff --git a/src/core/hle/service/nfc/common/device_manager.h b/src/core/hle/service/nfc/common/device_manager.h index c56a2fbda..6c0e6b255 100644 --- a/src/core/hle/service/nfc/common/device_manager.h +++ b/src/core/hle/service/nfc/common/device_manager.h @@ -15,6 +15,10 @@ #include "core/hle/service/service.h" #include "hid_core/hid_types.h" +namespace Service::Set { +class ISystemSettingsServer; +} + namespace Service::NFC { class NfcDevice; @@ -98,6 +102,7 @@ private: Core::System& system; KernelHelpers::ServiceContext service_context; Kernel::KEvent* availability_change_event; + std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; }; } // namespace Service::NFC diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp index 30ae989b9..9d4808dbe 100644 --- a/src/core/hle/service/nfc/nfc.cpp +++ b/src/core/hle/service/nfc/nfc.cpp @@ -57,7 +57,7 @@ public: {1, &NfcInterface::Finalize, "FinalizeOld"}, {2, &NfcInterface::GetState, "GetStateOld"}, {3, &NfcInterface::IsNfcEnabled, "IsNfcEnabledOld"}, - {100, nullptr, "SetNfcEnabledOld"}, + {100, &NfcInterface::SetNfcEnabled, "SetNfcEnabledOld"}, {400, &NfcInterface::Initialize, "Initialize"}, {401, &NfcInterface::Finalize, "Finalize"}, {402, &NfcInterface::GetState, "GetState"}, @@ -71,7 +71,7 @@ public: {410, &NfcInterface::GetTagInfo, "GetTagInfo"}, {411, &NfcInterface::AttachActivateEvent, "AttachActivateEvent"}, {412, &NfcInterface::AttachDeactivateEvent, "AttachDeactivateEvent"}, - {500, nullptr, "SetNfcEnabled"}, + {500, &NfcInterface::SetNfcEnabled, "SetNfcEnabled"}, {510, nullptr, "OutputTestWave"}, {1000, &NfcInterface::ReadMifare, "ReadMifare"}, {1001, &NfcInterface::WriteMifare, "WriteMifare"}, diff --git a/src/core/hle/service/nfc/nfc_interface.cpp b/src/core/hle/service/nfc/nfc_interface.cpp index 3e2c7deab..c28e55431 100644 --- a/src/core/hle/service/nfc/nfc_interface.cpp +++ b/src/core/hle/service/nfc/nfc_interface.cpp @@ -13,13 +13,18 @@ #include "core/hle/service/nfc/nfc_result.h" #include "core/hle/service/nfc/nfc_types.h" #include "core/hle/service/nfp/nfp_result.h" +#include "core/hle/service/set/system_settings_server.h" +#include "core/hle/service/sm/sm.h" #include "hid_core/hid_types.h" namespace Service::NFC { NfcInterface::NfcInterface(Core::System& system_, const char* name, BackendType service_backend) : ServiceFramework{system_, name}, service_context{system_, service_name}, - backend_type{service_backend} {} + backend_type{service_backend} { + m_set_sys = + system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true); +} NfcInterface ::~NfcInterface() = default; @@ -65,11 +70,11 @@ void NfcInterface::GetState(HLERequestContext& ctx) { void NfcInterface::IsNfcEnabled(HLERequestContext& ctx) { LOG_DEBUG(Service_NFC, "called"); - // TODO: This calls nn::settings::detail::GetNfcEnableFlag - const bool is_enabled = true; + bool is_enabled{}; + const auto result = m_set_sys->GetNfcEnableFlag(&is_enabled); IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); + rb.Push(result); rb.Push(is_enabled); } @@ -212,6 +217,17 @@ void NfcInterface::AttachDeactivateEvent(HLERequestContext& ctx) { rb.PushCopyObjects(out_event); } +void NfcInterface::SetNfcEnabled(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto is_enabled{rp.Pop<bool>()}; + LOG_DEBUG(Service_NFC, "called, is_enabled={}", is_enabled); + + const auto result = m_set_sys->SetNfcEnableFlag(is_enabled); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(result); +} + void NfcInterface::ReadMifare(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto device_handle{rp.Pop<u64>()}; diff --git a/src/core/hle/service/nfc/nfc_interface.h b/src/core/hle/service/nfc/nfc_interface.h index 08be174d8..5cc0d8ec0 100644 --- a/src/core/hle/service/nfc/nfc_interface.h +++ b/src/core/hle/service/nfc/nfc_interface.h @@ -7,6 +7,10 @@ #include "core/hle/service/nfc/nfc_types.h" #include "core/hle/service/service.h" +namespace Service::Set { +class ISystemSettingsServer; +} + namespace Service::NFC { class DeviceManager; @@ -29,6 +33,7 @@ public: void AttachActivateEvent(HLERequestContext& ctx); void AttachDeactivateEvent(HLERequestContext& ctx); void ReadMifare(HLERequestContext& ctx); + void SetNfcEnabled(HLERequestContext& ctx); void WriteMifare(HLERequestContext& ctx); void SendCommandByPassThrough(HLERequestContext& ctx); @@ -44,6 +49,7 @@ protected: BackendType backend_type; State state{State::NonInitialized}; std::shared_ptr<DeviceManager> device_manager = nullptr; + std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys; }; } // namespace Service::NFC diff --git a/src/core/hle/service/npns/npns.cpp b/src/core/hle/service/npns/npns.cpp index a162e5c54..e54827efe 100644 --- a/src/core/hle/service/npns/npns.cpp +++ b/src/core/hle/service/npns/npns.cpp @@ -3,22 +3,26 @@ #include <memory> +#include "core/hle/kernel/k_event.h" +#include "core/hle/service/cmif_serialization.h" +#include "core/hle/service/kernel_helpers.h" #include "core/hle/service/npns/npns.h" #include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" namespace Service::NPNS { -class NPNS_S final : public ServiceFramework<NPNS_S> { +class INpnsSystem final : public ServiceFramework<INpnsSystem> { public: - explicit NPNS_S(Core::System& system_) : ServiceFramework{system_, "npns:s"} { + explicit INpnsSystem(Core::System& system_) + : ServiceFramework{system_, "npns:s"}, service_context{system, "npns:s"} { // clang-format off static const FunctionInfo functions[] = { {1, nullptr, "ListenAll"}, - {2, nullptr, "ListenTo"}, + {2, C<&INpnsSystem::ListenTo>, "ListenTo"}, {3, nullptr, "Receive"}, {4, nullptr, "ReceiveRaw"}, - {5, nullptr, "GetReceiveEvent"}, + {5, C<&INpnsSystem::GetReceiveEvent>, "GetReceiveEvent"}, {6, nullptr, "ListenUndelivered"}, {7, nullptr, "GetStateChangeEVent"}, {11, nullptr, "SubscribeTopic"}, @@ -59,12 +63,34 @@ public: // clang-format on RegisterHandlers(functions); + + get_receive_event = service_context.CreateEvent("npns:s:GetReceiveEvent"); } + + ~INpnsSystem() override { + service_context.CloseEvent(get_receive_event); + } + +private: + Result ListenTo(u32 program_id) { + LOG_WARNING(Service_AM, "(STUBBED) called, program_id={}", program_id); + R_SUCCEED(); + } + + Result GetReceiveEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + *out_event = &get_receive_event->GetReadableEvent(); + R_SUCCEED(); + } + + KernelHelpers::ServiceContext service_context; + Kernel::KEvent* get_receive_event; }; -class NPNS_U final : public ServiceFramework<NPNS_U> { +class INpnsUser final : public ServiceFramework<INpnsUser> { public: - explicit NPNS_U(Core::System& system_) : ServiceFramework{system_, "npns:u"} { + explicit INpnsUser(Core::System& system_) : ServiceFramework{system_, "npns:u"} { // clang-format off static const FunctionInfo functions[] = { {1, nullptr, "ListenAll"}, @@ -97,8 +123,8 @@ public: void LoopProcess(Core::System& system) { auto server_manager = std::make_unique<ServerManager>(system); - server_manager->RegisterNamedService("npns:s", std::make_shared<NPNS_S>(system)); - server_manager->RegisterNamedService("npns:u", std::make_shared<NPNS_U>(system)); + server_manager->RegisterNamedService("npns:s", std::make_shared<INpnsSystem>(system)); + server_manager->RegisterNamedService("npns:u", std::make_shared<INpnsUser>(system)); ServerManager::RunServer(std::move(server_manager)); } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index bf12d69a5..efc9cca1c 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp @@ -5,6 +5,7 @@ #include "common/assert.h" #include "common/logging/log.h" #include "core/core.h" +#include "core/hle/kernel/k_process.h" #include "core/hle/service/nvdrv/core/container.h" #include "core/hle/service/nvdrv/core/nvmap.h" #include "core/hle/service/nvdrv/core/syncpoint_manager.h" @@ -75,7 +76,7 @@ NvResult nvhost_gpu::Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> inpu case 0xd: return WrapFixed(this, &nvhost_gpu::SetChannelPriority, input, output); case 0x1a: - return WrapFixed(this, &nvhost_gpu::AllocGPFIFOEx2, input, output); + return WrapFixed(this, &nvhost_gpu::AllocGPFIFOEx2, input, output, fd); case 0x1b: return WrapFixedVariable(this, &nvhost_gpu::SubmitGPFIFOBase1, input, output, true); case 0x1d: @@ -120,8 +121,13 @@ NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> inpu return NvResult::NotImplemented; } -void nvhost_gpu::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {} -void nvhost_gpu::OnClose(DeviceFD fd) {} +void nvhost_gpu::OnOpen(NvCore::SessionId session_id, DeviceFD fd) { + sessions[fd] = session_id; +} + +void nvhost_gpu::OnClose(DeviceFD fd) { + sessions.erase(fd); +} NvResult nvhost_gpu::SetNVMAPfd(IoctlSetNvmapFD& params) { LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd); @@ -161,7 +167,7 @@ NvResult nvhost_gpu::SetChannelPriority(IoctlChannelSetPriority& params) { return NvResult::Success; } -NvResult nvhost_gpu::AllocGPFIFOEx2(IoctlAllocGpfifoEx2& params) { +NvResult nvhost_gpu::AllocGPFIFOEx2(IoctlAllocGpfifoEx2& params, DeviceFD fd) { LOG_WARNING(Service_NVDRV, "(STUBBED) called, num_entries={:X}, flags={:X}, unk0={:X}, " "unk1={:X}, unk2={:X}, unk3={:X}", @@ -173,7 +179,12 @@ NvResult nvhost_gpu::AllocGPFIFOEx2(IoctlAllocGpfifoEx2& params) { return NvResult::AlreadyAllocated; } - system.GPU().InitChannel(*channel_state); + u64 program_id{}; + if (auto* const session = core.GetSession(sessions[fd]); session != nullptr) { + program_id = session->process->GetProgramId(); + } + + system.GPU().InitChannel(*channel_state, program_id); params.fence_out = syncpoint_manager.GetSyncpointFence(channel_syncpoint); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h index e34a978db..e0aeef953 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h @@ -192,7 +192,7 @@ private: NvResult ZCullBind(IoctlZCullBind& params); NvResult SetErrorNotifier(IoctlSetErrorNotifier& params); NvResult SetChannelPriority(IoctlChannelSetPriority& params); - NvResult AllocGPFIFOEx2(IoctlAllocGpfifoEx2& params); + NvResult AllocGPFIFOEx2(IoctlAllocGpfifoEx2& params, DeviceFD fd); NvResult AllocateObjectContext(IoctlAllocObjCtx& params); NvResult SubmitGPFIFOImpl(IoctlSubmitGpfifo& params, Tegra::CommandList&& entries); @@ -210,6 +210,7 @@ private: NvCore::SyncpointManager& syncpoint_manager; NvCore::NvMap& nvmap; std::shared_ptr<Tegra::Control::ChannelState> channel_state; + std::unordered_map<DeviceFD, NvCore::SessionId> sessions; u32 channel_syncpoint; std::mutex channel_mutex; diff --git a/src/core/hle/service/server_manager.cpp b/src/core/hle/service/server_manager.cpp index 0b41bbcb9..3d898725e 100644 --- a/src/core/hle/service/server_manager.cpp +++ b/src/core/hle/service/server_manager.cpp @@ -93,13 +93,19 @@ ServerManager::~ServerManager() { m_threads.clear(); // Clean up ports. - for (auto it = m_servers.begin(); it != m_servers.end(); it = m_servers.erase(it)) { - delete std::addressof(*it); + auto port_it = m_servers.begin(); + while (port_it != m_servers.end()) { + auto* const port = std::addressof(*port_it); + port_it = m_servers.erase(port_it); + delete port; } // Clean up sessions. - for (auto it = m_sessions.begin(); it != m_sessions.end(); it = m_sessions.erase(it)) { - delete std::addressof(*it); + auto session_it = m_sessions.begin(); + while (session_it != m_sessions.end()) { + auto* const session = std::addressof(*session_it); + session_it = m_sessions.erase(session_it); + delete session; } // Close wakeup event. diff --git a/src/core/hle/service/services.cpp b/src/core/hle/service/services.cpp index 1aa85ea54..3defa4b31 100644 --- a/src/core/hle/service/services.cpp +++ b/src/core/hle/service/services.cpp @@ -5,7 +5,7 @@ #include "core/hle/service/acc/acc.h" #include "core/hle/service/am/am.h" -#include "core/hle/service/aoc/aoc_u.h" +#include "core/hle/service/aoc/addon_content_manager.h" #include "core/hle/service/apm/apm.h" #include "core/hle/service/audio/audio.h" #include "core/hle/service/bcat/bcat.h" diff --git a/src/core/hle/service/set/setting_formats/system_settings.cpp b/src/core/hle/service/set/setting_formats/system_settings.cpp index 7231ff78e..caa30c2d5 100644 --- a/src/core/hle/service/set/setting_formats/system_settings.cpp +++ b/src/core/hle/service/set/setting_formats/system_settings.cpp @@ -52,6 +52,10 @@ SystemSettings DefaultSystemSettings() { settings.battery_percentage_flag = true; settings.chinese_traditional_input_method = ChineseTraditionalInputMethod::Unknown0; settings.vibration_master_volume = 1.0f; + settings.touch_screen_mode = TouchScreenMode::Standard; + settings.nfc_enable_flag = true; + settings.bluetooth_enable_flag = true; + settings.wireless_lan_enable_flag = true; const auto language_code = available_language_codes[static_cast<s32>(::Settings::values.language_index.GetValue())]; diff --git a/src/core/hle/service/set/settings_types.h b/src/core/hle/service/set/settings_types.h index 29664e88c..92c2948b0 100644 --- a/src/core/hle/service/set/settings_types.h +++ b/src/core/hle/service/set/settings_types.h @@ -243,6 +243,11 @@ enum class TvResolution : u32 { Resolution480p, }; +enum class PlatformRegion : s32 { + Global = 1, + Terra = 2, +}; + constexpr std::array<LanguageCode, 18> available_language_codes = {{ LanguageCode::JA, LanguageCode::EN_US, @@ -405,8 +410,7 @@ struct EulaVersion { SystemRegionCode region_code; EulaVersionClockType clock_type; INSERT_PADDING_BYTES(0x4); - s64 posix_time; - Service::PSC::Time::SteadyClockTimePoint timestamp; + Service::PSC::Time::SystemClockContext system_clock_context; }; static_assert(sizeof(EulaVersion) == 0x30, "EulaVersion is incorrect size"); diff --git a/src/core/hle/service/set/system_settings_server.cpp b/src/core/hle/service/set/system_settings_server.cpp index 93925f783..0dc8db821 100644 --- a/src/core/hle/service/set/system_settings_server.cpp +++ b/src/core/hle/service/set/system_settings_server.cpp @@ -26,7 +26,7 @@ namespace Service::Set { namespace { -constexpr u32 SETTINGS_VERSION{3u}; +constexpr u32 SETTINGS_VERSION{4u}; constexpr auto SETTINGS_MAGIC = Common::MakeMagic('y', 'u', 'z', 'u', '_', 's', 'e', 't'); struct SettingsHeader { u64 magic; @@ -272,8 +272,8 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) {180, nullptr, "SetZoomFlag"}, {181, nullptr, "GetT"}, {182, nullptr, "SetT"}, - {183, nullptr, "GetPlatformRegion"}, - {184, nullptr, "SetPlatformRegion"}, + {183, C<&ISystemSettingsServer::GetPlatformRegion>, "GetPlatformRegion"}, + {184, C<&ISystemSettingsServer::SetPlatformRegion>, "SetPlatformRegion"}, {185, C<&ISystemSettingsServer::GetHomeMenuSchemeModel>, "GetHomeMenuSchemeModel"}, {186, nullptr, "GetMemoryUsageRateFlag"}, {187, C<&ISystemSettingsServer::GetTouchScreenMode>, "GetTouchScreenMode"}, @@ -306,6 +306,20 @@ ISystemSettingsServer::ISystemSettingsServer(Core::System& system_) RegisterHandlers(functions); SetupSettings(); + + m_system_settings.region_code = + static_cast<SystemRegionCode>(::Settings::values.region_index.GetValue()); + + // TODO: Remove this when starter applet is fully functional + EulaVersion eula_version{ + .version = 0x10000, + .region_code = m_system_settings.region_code, + .clock_type = EulaVersionClockType::SteadyClock, + .system_clock_context = m_system_settings.user_system_clock_context, + }; + m_system_settings.eula_versions[0] = eula_version; + m_system_settings.eula_version_count = 1; + m_save_thread = std::jthread([this](std::stop_token stop_token) { StoreSettingsThreadFunc(stop_token); }); } @@ -701,7 +715,7 @@ Result ISystemSettingsServer::GetSettingsItemValueSize( } Result ISystemSettingsServer::GetSettingsItemValue( - OutBuffer<BufferAttr_HipcMapAlias> out_data, + Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_data, InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer, InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buffer) { const std::string setting_category{Common::StringFromBuffer(*setting_category_buffer)}; @@ -709,7 +723,7 @@ Result ISystemSettingsServer::GetSettingsItemValue( LOG_INFO(Service_SET, "called, category={}, name={}", setting_category, setting_name); - R_RETURN(GetSettingsItemValueImpl(out_data, setting_category, setting_name)); + R_RETURN(GetSettingsItemValueImpl(out_data, *out_size, setting_category, setting_name)); } Result ISystemSettingsServer::GetTvSettings(Out<TvSettings> out_tv_settings) { @@ -1236,6 +1250,18 @@ Result ISystemSettingsServer::GetHomeMenuScheme(Out<HomeMenuScheme> out_home_men R_SUCCEED(); } +Result ISystemSettingsServer::GetPlatformRegion(Out<PlatformRegion> out_platform_region) { + LOG_WARNING(Service_SET, "(STUBBED) called"); + + *out_platform_region = PlatformRegion::Global; + R_SUCCEED(); +} + +Result ISystemSettingsServer::SetPlatformRegion(PlatformRegion platform_region) { + LOG_WARNING(Service_SET, "(STUBBED) called"); + R_SUCCEED(); +} + Result ISystemSettingsServer::GetHomeMenuSchemeModel(Out<u32> out_home_menu_scheme_model) { LOG_WARNING(Service_SET, "(STUBBED) called"); @@ -1349,13 +1375,16 @@ void ISystemSettingsServer::SetSaveNeeded() { m_save_needed = true; } -Result ISystemSettingsServer::GetSettingsItemValueImpl(std::vector<u8>& out_value, +Result ISystemSettingsServer::GetSettingsItemValueImpl(std::span<u8> out_value, u64& out_size, const std::string& category, const std::string& name) { auto settings{GetSettings()}; R_UNLESS(settings.contains(category) && settings[category].contains(name), ResultUnknown); - out_value = settings[category][name]; + ASSERT_MSG(out_value.size() >= settings[category][name].size(), + "Stored type is bigger than requested type"); + out_size = std::min<u64>(settings[category][name].size(), out_value.size()); + std::memcpy(out_value.data(), settings[category][name].data(), out_size); R_SUCCEED(); } diff --git a/src/core/hle/service/set/system_settings_server.h b/src/core/hle/service/set/system_settings_server.h index 46e06c8ea..993e5de7d 100644 --- a/src/core/hle/service/set/system_settings_server.h +++ b/src/core/hle/service/set/system_settings_server.h @@ -34,20 +34,17 @@ public: explicit ISystemSettingsServer(Core::System& system_); ~ISystemSettingsServer() override; - Result GetSettingsItemValueImpl(std::vector<u8>& out_value, const std::string& category, - const std::string& name); + Result GetSettingsItemValueImpl(std::span<u8> out_value, u64& out_size, + const std::string& category, const std::string& name); template <typename T> - Result GetSettingsItemValueImpl(T& value, const std::string& category, + Result GetSettingsItemValueImpl(T& out_value, const std::string& category, const std::string& name) { - std::vector<u8> data; - const auto result = GetSettingsItemValueImpl(data, category, name); - if (result.IsError()) { - return result; - } - ASSERT(data.size() >= sizeof(T)); - std::memcpy(&value, data.data(), sizeof(T)); - return result; + u64 data_size{}; + std::vector<u8> data(sizeof(T)); + R_TRY(GetSettingsItemValueImpl(data, data_size, category, name)); + std::memcpy(&out_value, data.data(), data_size); + R_SUCCEED(); } public: @@ -84,7 +81,7 @@ public: InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer, InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buf); Result GetSettingsItemValue( - OutBuffer<BufferAttr_HipcMapAlias> out_data, + Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_data, InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer, InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buffer); Result GetTvSettings(Out<TvSettings> out_tv_settings); @@ -152,6 +149,8 @@ public: Result GetHomeMenuScheme(Out<HomeMenuScheme> out_home_menu_scheme); Result GetHomeMenuSchemeModel(Out<u32> out_home_menu_scheme_model); Result GetTouchScreenMode(Out<TouchScreenMode> out_touch_screen_mode); + Result GetPlatformRegion(Out<PlatformRegion> out_platform_region); + Result SetPlatformRegion(PlatformRegion platform_region); Result SetTouchScreenMode(TouchScreenMode touch_screen_mode); Result GetFieldTestingFlag(Out<bool> out_field_testing_flag); Result GetPanelCrcMode(Out<s32> out_panel_crc_mode); diff --git a/src/core/hle/service/ssl/cert_store.cpp b/src/core/hle/service/ssl/cert_store.cpp new file mode 100644 index 000000000..b321e5d32 --- /dev/null +++ b/src/core/hle/service/ssl/cert_store.cpp @@ -0,0 +1,156 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/alignment.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/hle/service/filesystem/filesystem.h" +#include "core/hle/service/ssl/cert_store.h" + +namespace Service::SSL { + +// https://switchbrew.org/wiki/SSL_services#CertStore + +CertStore::CertStore(Core::System& system) { + constexpr u64 CertStoreDataId = 0x0100000000000800ULL; + + auto& fsc = system.GetFileSystemController(); + + // Attempt to load certificate data from storage + const auto nca = + fsc.GetSystemNANDContents()->GetEntry(CertStoreDataId, FileSys::ContentRecordType::Data); + if (!nca) { + return; + } + const auto romfs = nca->GetRomFS(); + if (!romfs) { + return; + } + const auto extracted = FileSys::ExtractRomFS(romfs); + if (!extracted) { + LOG_ERROR(Service_SSL, "CertStore could not be extracted, corrupt RomFS?"); + return; + } + const auto cert_store_file = extracted->GetFile("ssl_TrustedCerts.bdf"); + if (!cert_store_file) { + LOG_ERROR(Service_SSL, "Failed to find trusted certificates in CertStore"); + return; + } + + // Read and verify the header. + CertStoreHeader header; + cert_store_file->ReadObject(std::addressof(header)); + + if (header.magic != Common::MakeMagic('s', 's', 'l', 'T')) { + LOG_ERROR(Service_SSL, "Invalid certificate store magic"); + return; + } + + // Ensure the file can contains the number of entries it says it does. + const u64 expected_size = sizeof(header) + sizeof(CertStoreEntry) * header.num_entries; + const u64 actual_size = cert_store_file->GetSize(); + if (actual_size < expected_size) { + LOG_ERROR(Service_SSL, "Size mismatch, expected at least {} bytes, got {}", expected_size, + actual_size); + return; + } + + // Read entries. + std::vector<CertStoreEntry> entries(header.num_entries); + cert_store_file->ReadArray(entries.data(), header.num_entries, sizeof(header)); + + // Insert into memory store. + for (const auto& entry : entries) { + m_certs.emplace(entry.certificate_id, + Certificate{ + .status = entry.certificate_status, + .der_data = cert_store_file->ReadBytes( + entry.der_size, entry.der_offset + sizeof(header)), + }); + } +} + +CertStore::~CertStore() = default; + +template <typename F> +void CertStore::ForEachCertificate(std::span<const CaCertificateId> certificate_ids, F&& f) { + if (certificate_ids.size() == 1 && certificate_ids.front() == CaCertificateId::All) { + for (const auto& entry : m_certs) { + f(entry); + } + } else { + for (const auto certificate_id : certificate_ids) { + const auto entry = m_certs.find(certificate_id); + if (entry == m_certs.end()) { + continue; + } + f(*entry); + } + } +} + +Result CertStore::GetCertificates(u32* out_num_entries, std::span<u8> out_data, + std::span<const CaCertificateId> certificate_ids) { + // Ensure the buffer is large enough to hold the output. + u32 required_size; + R_TRY(this->GetCertificateBufSize(std::addressof(required_size), out_num_entries, + certificate_ids)); + R_UNLESS(out_data.size_bytes() >= required_size, ResultUnknown); + + // Make parallel arrays. + std::vector<BuiltInCertificateInfo> cert_infos; + std::vector<u8> der_datas; + + const u32 der_data_offset = (*out_num_entries + 1) * sizeof(BuiltInCertificateInfo); + u32 cur_der_offset = der_data_offset; + + // Fill output. + this->ForEachCertificate(certificate_ids, [&](auto& entry) { + const auto& [status, cur_der_data] = entry.second; + BuiltInCertificateInfo cert_info{ + .cert_id = entry.first, + .status = status, + .der_size = cur_der_data.size(), + .der_offset = cur_der_offset, + }; + + cert_infos.push_back(cert_info); + der_datas.insert(der_datas.end(), cur_der_data.begin(), cur_der_data.end()); + cur_der_offset += static_cast<u32>(cur_der_data.size()); + }); + + // Append terminator entry. + cert_infos.push_back(BuiltInCertificateInfo{ + .cert_id = CaCertificateId::All, + .status = TrustedCertStatus::Invalid, + .der_size = 0, + .der_offset = 0, + }); + + // Write to output span. + std::memcpy(out_data.data(), cert_infos.data(), + cert_infos.size() * sizeof(BuiltInCertificateInfo)); + std::memcpy(out_data.data() + der_data_offset, der_datas.data(), der_datas.size()); + + R_SUCCEED(); +} + +Result CertStore::GetCertificateBufSize(u32* out_size, u32* out_num_entries, + std::span<const CaCertificateId> certificate_ids) { + // Output size is at least the size of the terminator entry. + *out_size = sizeof(BuiltInCertificateInfo); + *out_num_entries = 0; + + this->ForEachCertificate(certificate_ids, [&](auto& entry) { + *out_size += sizeof(BuiltInCertificateInfo); + *out_size += Common::AlignUp(static_cast<u32>(entry.second.der_data.size()), 4); + (*out_num_entries)++; + }); + + R_SUCCEED(); +} + +} // namespace Service::SSL diff --git a/src/core/hle/service/ssl/cert_store.h b/src/core/hle/service/ssl/cert_store.h new file mode 100644 index 000000000..613d7b02a --- /dev/null +++ b/src/core/hle/service/ssl/cert_store.h @@ -0,0 +1,42 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <map> +#include <span> +#include <vector> + +#include "core/hle/result.h" +#include "core/hle/service/ssl/ssl_types.h" + +namespace Core { +class System; +} + +namespace Service::SSL { + +class CertStore { +public: + explicit CertStore(Core::System& system); + ~CertStore(); + + Result GetCertificates(u32* out_num_entries, std::span<u8> out_data, + std::span<const CaCertificateId> certificate_ids); + Result GetCertificateBufSize(u32* out_size, u32* out_num_entries, + std::span<const CaCertificateId> certificate_ids); + +private: + template <typename F> + void ForEachCertificate(std::span<const CaCertificateId> certs, F&& f); + +private: + struct Certificate { + TrustedCertStatus status; + std::vector<u8> der_data; + }; + + std::map<CaCertificateId, Certificate> m_certs; +}; + +} // namespace Service::SSL diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp index 0fbb43057..008ee4492 100644 --- a/src/core/hle/service/ssl/ssl.cpp +++ b/src/core/hle/service/ssl/ssl.cpp @@ -5,11 +5,13 @@ #include "core/core.h" #include "core/hle/result.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/ipc_helpers.h" #include "core/hle/service/server_manager.h" #include "core/hle/service/service.h" #include "core/hle/service/sm/sm.h" #include "core/hle/service/sockets/bsd.h" +#include "core/hle/service/ssl/cert_store.h" #include "core/hle/service/ssl/ssl.h" #include "core/hle/service/ssl/ssl_backend.h" #include "core/internal_network/network.h" @@ -492,13 +494,14 @@ private: class ISslService final : public ServiceFramework<ISslService> { public: - explicit ISslService(Core::System& system_) : ServiceFramework{system_, "ssl"} { + explicit ISslService(Core::System& system_) + : ServiceFramework{system_, "ssl"}, cert_store{system} { // clang-format off static const FunctionInfo functions[] = { {0, &ISslService::CreateContext, "CreateContext"}, {1, nullptr, "GetContextCount"}, - {2, nullptr, "GetCertificates"}, - {3, nullptr, "GetCertificateBufSize"}, + {2, D<&ISslService::GetCertificates>, "GetCertificates"}, + {3, D<&ISslService::GetCertificateBufSize>, "GetCertificateBufSize"}, {4, nullptr, "DebugIoctl"}, {5, &ISslService::SetInterfaceVersion, "SetInterfaceVersion"}, {6, nullptr, "FlushSessionCache"}, @@ -540,6 +543,22 @@ private: IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } + + Result GetCertificateBufSize( + Out<u32> out_size, InArray<CaCertificateId, BufferAttr_HipcMapAlias> certificate_ids) { + LOG_INFO(Service_SSL, "called"); + u32 num_entries; + R_RETURN(cert_store.GetCertificateBufSize(out_size, &num_entries, certificate_ids)); + } + + Result GetCertificates(Out<u32> out_num_entries, OutBuffer<BufferAttr_HipcMapAlias> out_buffer, + InArray<CaCertificateId, BufferAttr_HipcMapAlias> certificate_ids) { + LOG_INFO(Service_SSL, "called"); + R_RETURN(cert_store.GetCertificates(out_num_entries, out_buffer, certificate_ids)); + } + +private: + CertStore cert_store; }; void LoopProcess(Core::System& system) { diff --git a/src/core/hle/service/ssl/ssl_types.h b/src/core/hle/service/ssl/ssl_types.h new file mode 100644 index 000000000..dbc3dbf64 --- /dev/null +++ b/src/core/hle/service/ssl/ssl_types.h @@ -0,0 +1,107 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/common_types.h" + +namespace Service::SSL { + +enum class CaCertificateId : s32 { + All = -1, + NintendoCAG3 = 1, + NintendoClass2CAG3 = 2, + NintendoRootCAG4 = 3, + AmazonRootCA1 = 1000, + StarfieldServicesRootCertificateAuthorityG2 = 1001, + AddTrustExternalCARoot = 1002, + COMODOCertificationAuthority = 1003, + UTNDATACorpSGC = 1004, + UTNUSERFirstHardware = 1005, + BaltimoreCyberTrustRoot = 1006, + CybertrustGlobalRoot = 1007, + VerizonGlobalRootCA = 1008, + DigiCertAssuredIDRootCA = 1009, + DigiCertAssuredIDRootG2 = 1010, + DigiCertGlobalRootCA = 1011, + DigiCertGlobalRootG2 = 1012, + DigiCertHighAssuranceEVRootCA = 1013, + EntrustnetCertificationAuthority2048 = 1014, + EntrustRootCertificationAuthority = 1015, + EntrustRootCertificationAuthorityG2 = 1016, + GeoTrustGlobalCA2 = 1017, + GeoTrustGlobalCA = 1018, + GeoTrustPrimaryCertificationAuthorityG3 = 1019, + GeoTrustPrimaryCertificationAuthority = 1020, + GlobalSignRootCA = 1021, + GlobalSignRootCAR2 = 1022, + GlobalSignRootCAR3 = 1023, + GoDaddyClass2CertificationAuthority = 1024, + GoDaddyRootCertificateAuthorityG2 = 1025, + StarfieldClass2CertificationAuthority = 1026, + StarfieldRootCertificateAuthorityG2 = 1027, + thawtePrimaryRootCAG3 = 1028, + thawtePrimaryRootCA = 1029, + VeriSignClass3PublicPrimaryCertificationAuthorityG3 = 1030, + VeriSignClass3PublicPrimaryCertificationAuthorityG5 = 1031, + VeriSignUniversalRootCertificationAuthority = 1032, + DSTRootCAX3 = 1033, + USERTrustRsaCertificationAuthority = 1034, + ISRGRootX10 = 1035, + USERTrustEccCertificationAuthority = 1036, + COMODORsaCertificationAuthority = 1037, + COMODOEccCertificationAuthority = 1038, + AmazonRootCA2 = 1039, + AmazonRootCA3 = 1040, + AmazonRootCA4 = 1041, + DigiCertAssuredIDRootG3 = 1042, + DigiCertGlobalRootG3 = 1043, + DigiCertTrustedRootG4 = 1044, + EntrustRootCertificationAuthorityEC1 = 1045, + EntrustRootCertificationAuthorityG4 = 1046, + GlobalSignECCRootCAR4 = 1047, + GlobalSignECCRootCAR5 = 1048, + GlobalSignECCRootCAR6 = 1049, + GTSRootR1 = 1050, + GTSRootR2 = 1051, + GTSRootR3 = 1052, + GTSRootR4 = 1053, + SecurityCommunicationRootCA = 1054, + GlobalSignRootE4 = 1055, + GlobalSignRootR4 = 1056, + TTeleSecGlobalRootClass2 = 1057, + DigiCertTLSECCP384RootG5 = 1058, + DigiCertTLSRSA4096RootG5 = 1059, +}; + +enum class TrustedCertStatus : s32 { + Invalid = -1, + Removed = 0, + EnabledTrusted = 1, + EnabledNotTrusted = 2, + Revoked = 3, +}; + +struct BuiltInCertificateInfo { + CaCertificateId cert_id; + TrustedCertStatus status; + u64 der_size; + u64 der_offset; +}; +static_assert(sizeof(BuiltInCertificateInfo) == 0x18, "BuiltInCertificateInfo has incorrect size."); + +struct CertStoreHeader { + u32 magic; + u32 num_entries; +}; +static_assert(sizeof(CertStoreHeader) == 0x8, "CertStoreHeader has incorrect size."); + +struct CertStoreEntry { + CaCertificateId certificate_id; + TrustedCertStatus certificate_status; + u32 der_size; + u32 der_offset; +}; +static_assert(sizeof(CertStoreEntry) == 0x10, "CertStoreEntry has incorrect size."); + +} // namespace Service::SSL diff --git a/src/hid_core/frontend/emulated_controller.cpp b/src/hid_core/frontend/emulated_controller.cpp index 5cd26819c..9aa08d5cc 100644 --- a/src/hid_core/frontend/emulated_controller.cpp +++ b/src/hid_core/frontend/emulated_controller.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include <algorithm> +#include <chrono> #include <common/scope_exit.h> #include "common/polyfill_ranges.h" @@ -175,10 +176,9 @@ void EmulatedController::LoadDevices() { if (npad_id_type == NpadIdType::Player1 || npad_id_type == NpadIdType::Handheld) { camera_params[1] = Common::ParamPackage{"engine:camera,camera:1"}; nfc_params[0] = Common::ParamPackage{"engine:virtual_amiibo,nfc:1"}; -#ifdef HAVE_LIBUSB +#ifndef ANDROID ring_params[1] = Common::ParamPackage{"engine:joycon,axis_x:100,axis_y:101"}; -#endif -#ifdef ANDROID +#else android_params = Common::ParamPackage{"engine:android,port:100"}; #endif } @@ -1287,6 +1287,22 @@ bool EmulatedController::SetVibration(DeviceIndex device_index, const VibrationV return false; } + if (!Settings::values.enable_accurate_vibrations.GetValue()) { + using std::chrono::duration_cast; + using std::chrono::milliseconds; + using std::chrono::steady_clock; + + const auto now = steady_clock::now(); + + // Filter out non-zero vibrations that are within 15ms of each other. + if ((vibration.low_amplitude != 0.0f || vibration.high_amplitude != 0.0f) && + duration_cast<milliseconds>(now - last_vibration_timepoint[index]) < milliseconds(15)) { + return false; + } + + last_vibration_timepoint[index] = now; + } + // Exponential amplification is too strong at low amplitudes. Switch to a linear // amplification if strength is set below 0.7f const Common::Input::VibrationAmplificationType type = diff --git a/src/hid_core/frontend/emulated_controller.h b/src/hid_core/frontend/emulated_controller.h index ab3c6fcd3..17ad6069e 100644 --- a/src/hid_core/frontend/emulated_controller.h +++ b/src/hid_core/frontend/emulated_controller.h @@ -583,6 +583,7 @@ private: std::size_t nfc_handles{0}; std::array<VibrationValue, 2> last_vibration_value{DEFAULT_VIBRATION_VALUE, DEFAULT_VIBRATION_VALUE}; + std::array<std::chrono::steady_clock::time_point, 2> last_vibration_timepoint{}; // Temporary values to avoid doing changes while the controller is in configuring mode NpadStyleIndex tmp_npad_type{NpadStyleIndex::None}; diff --git a/src/hid_core/hid_types.h b/src/hid_core/hid_types.h index 165ecf9de..40a90c2bc 100644 --- a/src/hid_core/hid_types.h +++ b/src/hid_core/hid_types.h @@ -630,7 +630,11 @@ struct VibrationValue { if (low_amplitude != b.low_amplitude || high_amplitude != b.high_amplitude) { return false; } - if (low_frequency != b.low_amplitude || high_frequency != b.high_frequency) { + // Changes in frequency without amplitude don't have any effect + if (low_amplitude == 0 && high_amplitude == 0) { + return true; + } + if (low_frequency != b.low_frequency || high_frequency != b.high_frequency) { return false; } return true; diff --git a/src/hid_core/resources/npad/npad.cpp b/src/hid_core/resources/npad/npad.cpp index e10e97e1c..ca1ccd659 100644 --- a/src/hid_core/resources/npad/npad.cpp +++ b/src/hid_core/resources/npad/npad.cpp @@ -3,7 +3,6 @@ #include <algorithm> #include <array> -#include <chrono> #include <cstring> #include "common/assert.h" diff --git a/src/input_common/drivers/android.cpp b/src/input_common/drivers/android.cpp index e859cc538..d40fa66ae 100644 --- a/src/input_common/drivers/android.cpp +++ b/src/input_common/drivers/android.cpp @@ -3,6 +3,7 @@ #include <set> #include <common/settings_input.h> +#include <common/thread.h> #include <jni.h> #include "common/android/android_common.h" #include "common/android/id_cache.h" @@ -10,7 +11,18 @@ namespace InputCommon { -Android::Android(std::string input_engine_) : InputEngine(std::move(input_engine_)) {} +Android::Android(std::string input_engine_) : InputEngine(std::move(input_engine_)) { + vibration_thread = std::jthread([this](std::stop_token token) { + Common::SetCurrentThreadName("Android_Vibration"); + auto env = Common::Android::GetEnvForThread(); + using namespace std::chrono_literals; + while (!token.stop_requested()) { + SendVibrations(env, token); + } + }); +} + +Android::~Android() = default; void Android::RegisterController(jobject j_input_device) { auto env = Common::Android::GetEnvForThread(); @@ -57,17 +69,11 @@ void Android::SetMotionState(std::string guid, size_t port, u64 delta_timestamp, Common::Input::DriverResult Android::SetVibration( [[maybe_unused]] const PadIdentifier& identifier, [[maybe_unused]] const Common::Input::VibrationStatus& vibration) { - auto device = input_devices.find(identifier); - if (device != input_devices.end()) { - Common::Android::RunJNIOnFiber<void>([&](JNIEnv* env) { - float average_intensity = - static_cast<float>((vibration.high_amplitude + vibration.low_amplitude) / 2.0); - env->CallVoidMethod(device->second, Common::Android::GetYuzuDeviceVibrate(), - average_intensity); - }); - return Common::Input::DriverResult::Success; - } - return Common::Input::DriverResult::NotSupported; + vibration_queue.Push(VibrationRequest{ + .identifier = identifier, + .vibration = vibration, + }); + return Common::Input::DriverResult::Success; } bool Android::IsVibrationEnabled([[maybe_unused]] const PadIdentifier& identifier) { @@ -347,4 +353,15 @@ PadIdentifier Android::GetIdentifier(const std::string& guid, size_t port) const }; } +void Android::SendVibrations(JNIEnv* env, std::stop_token token) { + VibrationRequest request = vibration_queue.PopWait(token); + auto device = input_devices.find(request.identifier); + if (device != input_devices.end()) { + float average_intensity = static_cast<float>( + (request.vibration.high_amplitude + request.vibration.low_amplitude) / 2.0); + env->CallVoidMethod(device->second, Common::Android::GetYuzuDeviceVibrate(), + average_intensity); + } +} + } // namespace InputCommon diff --git a/src/input_common/drivers/android.h b/src/input_common/drivers/android.h index 8a386c1b1..03e2b2c98 100644 --- a/src/input_common/drivers/android.h +++ b/src/input_common/drivers/android.h @@ -4,6 +4,7 @@ #pragma once #include <set> +#include <common/threadsafe_queue.h> #include <jni.h> #include "input_common/input_engine.h" @@ -16,6 +17,8 @@ class Android final : public InputEngine { public: explicit Android(std::string input_engine_); + ~Android() override; + /** * Registers controller number to accept new inputs. * @param j_input_device YuzuInputDevice object from the Android frontend to register. @@ -89,6 +92,9 @@ private: /// Returns the correct identifier corresponding to the player index PadIdentifier GetIdentifier(const std::string& guid, size_t port) const; + /// Takes all vibrations from the queue and sends the command to the controller + void SendVibrations(JNIEnv* env, std::stop_token token); + static constexpr s32 AXIS_X = 0; static constexpr s32 AXIS_Y = 1; static constexpr s32 AXIS_Z = 11; @@ -133,6 +139,10 @@ private: redmagic_vid, backbone_labs_vid, xbox_vid}; const std::vector<std::string> flipped_xy_vids{sony_vid, razer_vid, redmagic_vid, backbone_labs_vid, xbox_vid}; + + /// Queue of vibration request to controllers + Common::SPSCQueue<VibrationRequest> vibration_queue; + std::jthread vibration_thread; }; } // namespace InputCommon diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h index 08e49a0da..a140ad072 100644 --- a/src/input_common/drivers/sdl_driver.h +++ b/src/input_common/drivers/sdl_driver.h @@ -69,11 +69,6 @@ public: bool IsVibrationEnabled(const PadIdentifier& identifier) override; private: - struct VibrationRequest { - PadIdentifier identifier; - Common::Input::VibrationStatus vibration; - }; - void InitJoystick(int joystick_index); void CloseJoystick(SDL_Joystick* sdl_joystick); diff --git a/src/input_common/input_engine.h b/src/input_common/input_engine.h index c2d0cbb34..3e328509b 100644 --- a/src/input_common/input_engine.h +++ b/src/input_common/input_engine.h @@ -46,6 +46,11 @@ enum class EngineInputType { Nfc, }; +struct VibrationRequest { + PadIdentifier identifier; + Common::Input::VibrationStatus vibration; +}; + namespace std { // Hash used to create lists from PadIdentifier data template <> diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index ed7a5b27e..af237703d 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -1488,7 +1488,10 @@ void BufferCache<P>::ImmediateUploadMemory([[maybe_unused]] Buffer& buffer, std::span<const u8> upload_span; const DAddr device_addr = buffer.CpuAddr() + copy.dst_offset; if (IsRangeGranular(device_addr, copy.size)) { - upload_span = std::span(device_memory.GetPointer<u8>(device_addr), copy.size); + auto* const ptr = device_memory.GetPointer<u8>(device_addr); + if (ptr != nullptr) { + upload_span = std::span(ptr, copy.size); + } } else { if (immediate_buffer.empty()) { immediate_buffer = ImmediateBuffer(largest_copy); diff --git a/src/video_core/buffer_cache/usage_tracker.h b/src/video_core/buffer_cache/usage_tracker.h index 5f8688d31..ae511ccb6 100644 --- a/src/video_core/buffer_cache/usage_tracker.h +++ b/src/video_core/buffer_cache/usage_tracker.h @@ -26,6 +26,9 @@ public: void Track(u64 offset, u64 size) noexcept { const size_t page = offset >> PAGE_SHIFT; const size_t page_end = (offset + size) >> PAGE_SHIFT; + if (page_end < page || page_end >= pages.size()) { + return; + } TrackPage(page, offset, size); if (page == page_end) { return; @@ -41,6 +44,9 @@ public: [[nodiscard]] bool IsUsed(u64 offset, u64 size) const noexcept { const size_t page = offset >> PAGE_SHIFT; const size_t page_end = (offset + size) >> PAGE_SHIFT; + if (page_end < page || page_end >= pages.size()) { + return false; + } if (IsPageUsed(page, offset, size)) { return true; } diff --git a/src/video_core/control/channel_state.cpp b/src/video_core/control/channel_state.cpp index 832025d75..2539997d5 100644 --- a/src/video_core/control/channel_state.cpp +++ b/src/video_core/control/channel_state.cpp @@ -16,8 +16,9 @@ namespace Tegra::Control { ChannelState::ChannelState(s32 bind_id_) : bind_id{bind_id_}, initialized{} {} -void ChannelState::Init(Core::System& system, GPU& gpu) { +void ChannelState::Init(Core::System& system, GPU& gpu, u64 program_id_) { ASSERT(memory_manager); + program_id = program_id_; dma_pusher = std::make_unique<Tegra::DmaPusher>(system, gpu, *memory_manager, *this); maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, *memory_manager); fermi_2d = std::make_unique<Engines::Fermi2D>(*memory_manager); diff --git a/src/video_core/control/channel_state.h b/src/video_core/control/channel_state.h index 3a7b9872c..b385f4939 100644 --- a/src/video_core/control/channel_state.h +++ b/src/video_core/control/channel_state.h @@ -40,11 +40,12 @@ struct ChannelState { ChannelState(ChannelState&& other) noexcept = default; ChannelState& operator=(ChannelState&& other) noexcept = default; - void Init(Core::System& system, GPU& gpu); + void Init(Core::System& system, GPU& gpu, u64 program_id); void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); s32 bind_id = -1; + u64 program_id = 0; /// 3D engine std::unique_ptr<Engines::Maxwell3D> maxwell_3d; /// 2D engine diff --git a/src/video_core/control/channel_state_cache.cpp b/src/video_core/control/channel_state_cache.cpp index 4ebeb6356..f8c6a762d 100644 --- a/src/video_core/control/channel_state_cache.cpp +++ b/src/video_core/control/channel_state_cache.cpp @@ -7,7 +7,7 @@ namespace VideoCommon { ChannelInfo::ChannelInfo(Tegra::Control::ChannelState& channel_state) : maxwell3d{*channel_state.maxwell_3d}, kepler_compute{*channel_state.kepler_compute}, - gpu_memory{*channel_state.memory_manager} {} + gpu_memory{*channel_state.memory_manager}, program_id{channel_state.program_id} {} template class VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo>; diff --git a/src/video_core/control/channel_state_cache.h b/src/video_core/control/channel_state_cache.h index 1dbfda299..7480d60d1 100644 --- a/src/video_core/control/channel_state_cache.h +++ b/src/video_core/control/channel_state_cache.h @@ -39,6 +39,7 @@ public: Tegra::Engines::Maxwell3D& maxwell3d; Tegra::Engines::KeplerCompute& kepler_compute; Tegra::MemoryManager& gpu_memory; + u64 program_id; }; template <class P> @@ -77,9 +78,10 @@ protected: P* channel_state; size_t current_channel_id{UNSET_CHANNEL}; size_t current_address_space{}; - Tegra::Engines::Maxwell3D* maxwell3d; - Tegra::Engines::KeplerCompute* kepler_compute; - Tegra::MemoryManager* gpu_memory; + Tegra::Engines::Maxwell3D* maxwell3d{}; + Tegra::Engines::KeplerCompute* kepler_compute{}; + Tegra::MemoryManager* gpu_memory{}; + u64 program_id{}; std::deque<P> channel_storage; std::deque<size_t> free_channel_ids; diff --git a/src/video_core/control/channel_state_cache.inc b/src/video_core/control/channel_state_cache.inc index 31f792ddd..d882d8222 100644 --- a/src/video_core/control/channel_state_cache.inc +++ b/src/video_core/control/channel_state_cache.inc @@ -58,6 +58,7 @@ void ChannelSetupCaches<P>::BindToChannel(s32 id) { maxwell3d = &channel_state->maxwell3d; kepler_compute = &channel_state->kepler_compute; gpu_memory = &channel_state->gpu_memory; + program_id = channel_state->program_id; current_address_space = gpu_memory->GetID(); } @@ -76,6 +77,7 @@ void ChannelSetupCaches<P>::EraseChannel(s32 id) { maxwell3d = nullptr; kepler_compute = nullptr; gpu_memory = nullptr; + program_id = 0; } else if (current_channel_id != UNSET_CHANNEL) { channel_state = &channel_storage[current_channel_id]; } diff --git a/src/video_core/engines/draw_manager.cpp b/src/video_core/engines/draw_manager.cpp index d77ff455b..971025cb5 100644 --- a/src/video_core/engines/draw_manager.cpp +++ b/src/video_core/engines/draw_manager.cpp @@ -216,14 +216,11 @@ void DrawManager::DrawTexture() { const bool lower_left{regs.window_origin.mode != Maxwell3D::Regs::WindowOrigin::Mode::UpperLeft}; if (lower_left) { - draw_texture_state.dst_y0 -= dst_height; + draw_texture_state.dst_y0 = + static_cast<f32>(regs.surface_clip.height) - draw_texture_state.dst_y0; } - draw_texture_state.dst_x1 = - draw_texture_state.dst_x0 + - static_cast<f32>(Settings::values.resolution_info.ScaleUp(static_cast<u32>(dst_width))); - draw_texture_state.dst_y1 = - draw_texture_state.dst_y0 + - static_cast<f32>(Settings::values.resolution_info.ScaleUp(static_cast<u32>(dst_height))); + draw_texture_state.dst_x1 = draw_texture_state.dst_x0 + dst_width; + draw_texture_state.dst_y1 = draw_texture_state.dst_y0 + dst_height; draw_texture_state.src_x0 = static_cast<float>(regs.draw_texture.src_x0) / 4096.f; draw_texture_state.src_y0 = static_cast<float>(regs.draw_texture.src_y0) / 4096.f; draw_texture_state.src_x1 = diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 8e663f2a8..6d0b32339 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -67,8 +67,8 @@ struct GPU::Impl { return CreateChannel(new_channel_id++); } - void InitChannel(Control::ChannelState& to_init) { - to_init.Init(system, gpu); + void InitChannel(Control::ChannelState& to_init, u64 program_id) { + to_init.Init(system, gpu, program_id); to_init.BindRasterizer(rasterizer); rasterizer->InitializeChannel(to_init); } @@ -412,8 +412,8 @@ std::shared_ptr<Control::ChannelState> GPU::AllocateChannel() { return impl->AllocateChannel(); } -void GPU::InitChannel(Control::ChannelState& to_init) { - impl->InitChannel(to_init); +void GPU::InitChannel(Control::ChannelState& to_init, u64 program_id) { + impl->InitChannel(to_init, program_id); } void GPU::BindChannel(s32 channel_id) { diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index ad535512c..50014e51f 100644 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -149,7 +149,7 @@ public: std::shared_ptr<Control::ChannelState> AllocateChannel(); - void InitChannel(Control::ChannelState& to_init); + void InitChannel(Control::ChannelState& to_init, u64 program_id); void BindChannel(s32 channel_id); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 16af8e6bd..d376d86d8 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -370,27 +370,32 @@ void RasterizerOpenGL::DrawTexture() { const auto& sampler = texture_cache.GetGraphicsSampler(draw_texture_state.src_sampler); const auto& texture = texture_cache.GetImageView(draw_texture_state.src_texture); + const auto Scale = [&](auto dim) -> s32 { + return Settings::values.resolution_info.ScaleUp(static_cast<s32>(dim)); + }; + + Region2D dst_region = { + Offset2D{.x = Scale(draw_texture_state.dst_x0), .y = Scale(draw_texture_state.dst_y0)}, + Offset2D{.x = Scale(draw_texture_state.dst_x1), .y = Scale(draw_texture_state.dst_y1)}}; + Region2D src_region = { + Offset2D{.x = Scale(draw_texture_state.src_x0), .y = Scale(draw_texture_state.src_y0)}, + Offset2D{.x = Scale(draw_texture_state.src_x1), .y = Scale(draw_texture_state.src_y1)}}; + Extent3D src_size = {static_cast<u32>(Scale(texture.size.width)), + static_cast<u32>(Scale(texture.size.height)), texture.size.depth}; + if (device.HasDrawTexture()) { state_tracker.BindFramebuffer(texture_cache.GetFramebuffer()->Handle()); - glDrawTextureNV(texture.DefaultHandle(), sampler->Handle(), draw_texture_state.dst_x0, - draw_texture_state.dst_y0, draw_texture_state.dst_x1, - draw_texture_state.dst_y1, 0, + glDrawTextureNV(texture.DefaultHandle(), sampler->Handle(), + static_cast<f32>(dst_region.start.x), static_cast<f32>(dst_region.start.y), + static_cast<f32>(dst_region.end.x), static_cast<f32>(dst_region.end.y), 0, draw_texture_state.src_x0 / static_cast<float>(texture.size.width), draw_texture_state.src_y0 / static_cast<float>(texture.size.height), draw_texture_state.src_x1 / static_cast<float>(texture.size.width), draw_texture_state.src_y1 / static_cast<float>(texture.size.height)); } else { - Region2D dst_region = {Offset2D{.x = static_cast<s32>(draw_texture_state.dst_x0), - .y = static_cast<s32>(draw_texture_state.dst_y0)}, - Offset2D{.x = static_cast<s32>(draw_texture_state.dst_x1), - .y = static_cast<s32>(draw_texture_state.dst_y1)}}; - Region2D src_region = {Offset2D{.x = static_cast<s32>(draw_texture_state.src_x0), - .y = static_cast<s32>(draw_texture_state.src_y0)}, - Offset2D{.x = static_cast<s32>(draw_texture_state.src_x1), - .y = static_cast<s32>(draw_texture_state.src_y1)}}; blit_image.BlitColor(texture_cache.GetFramebuffer()->Handle(), texture.DefaultHandle(), - sampler->Handle(), dst_region, src_region, texture.size); + sampler->Handle(), dst_region, src_region, src_size); state_tracker.InvalidateState(); } diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 50462cdde..c4bad6fca 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -215,6 +215,7 @@ ShaderCache::ShaderCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, .support_gl_variable_aoffi = device.HasVariableAoffi(), .support_gl_sparse_textures = device.HasSparseTexture2(), .support_gl_derivative_control = device.HasDerivativeControl(), + .support_geometry_streams = true, .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyLargerThanGuest(), diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index 7cbc9c73c..a28296bda 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp @@ -1064,8 +1064,6 @@ public: } }); } - auto* ptr = device_memory.GetPointer<u8>(new_query->dependant_address); - ASSERT(ptr != nullptr); new_query->dependant_manage = must_manage_dependance; pending_flush_queries.push_back(index); @@ -1104,9 +1102,11 @@ public: tfb_streamer.Free(query->dependant_index); } else { u8* pointer = device_memory.GetPointer<u8>(query->dependant_address); - u32 result; - std::memcpy(&result, pointer, sizeof(u32)); - num_vertices = static_cast<u64>(result) / query->stride; + if (pointer != nullptr) { + u32 result; + std::memcpy(&result, pointer, sizeof(u32)); + num_vertices = static_cast<u64>(result) / query->stride; + } } query->value = [&]() -> u64 { switch (query->topology) { @@ -1360,7 +1360,9 @@ bool QueryCacheRuntime::HostConditionalRenderingCompareValues(VideoCommon::Looku const auto check_value = [&](DAddr address) { u8* ptr = impl->device_memory.GetPointer<u8>(address); u64 value{}; - std::memcpy(&value, ptr, sizeof(value)); + if (ptr != nullptr) { + std::memcpy(&value, ptr, sizeof(value)); + } return value == 0; }; std::array<VideoCommon::LookupData*, 2> objects{&object_1, &object_2}; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 74f9f099e..8ba50a834 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -125,11 +125,23 @@ VkRect2D GetScissorState(const Maxwell& regs, size_t index, u32 up_scale = 1, u3 return value < 0 ? std::min<s32>(converted_value - acumm, -1) : std::max<s32>(converted_value + acumm, 1); }; + + const bool lower_left = regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft; + const s32 clip_height = regs.surface_clip.height; + + // Flip coordinates if lower left + s32 min_y = lower_left ? (clip_height - src.max_y) : src.min_y.Value(); + s32 max_y = lower_left ? (clip_height - src.min_y) : src.max_y.Value(); + + // Bound to render area + min_y = std::max(min_y, 0); + max_y = std::max(max_y, 0); + if (src.enable) { - scissor.offset.x = scale_up(static_cast<s32>(src.min_x)); - scissor.offset.y = scale_up(static_cast<s32>(src.min_y)); + scissor.offset.x = scale_up(src.min_x); + scissor.offset.y = scale_up(min_y); scissor.extent.width = scale_up(src.max_x - src.min_x); - scissor.extent.height = scale_up(src.max_y - src.min_y); + scissor.extent.height = scale_up(max_y - min_y); } else { scissor.offset.x = 0; scissor.offset.y = 0; @@ -308,17 +320,33 @@ void RasterizerVulkan::DrawTexture() { const auto& draw_texture_state = maxwell3d->draw_manager->GetDrawTextureState(); const auto& sampler = texture_cache.GetGraphicsSampler(draw_texture_state.src_sampler); const auto& texture = texture_cache.GetImageView(draw_texture_state.src_texture); - Region2D dst_region = {Offset2D{.x = static_cast<s32>(draw_texture_state.dst_x0), - .y = static_cast<s32>(draw_texture_state.dst_y0)}, - Offset2D{.x = static_cast<s32>(draw_texture_state.dst_x1), - .y = static_cast<s32>(draw_texture_state.dst_y1)}}; - Region2D src_region = {Offset2D{.x = static_cast<s32>(draw_texture_state.src_x0), - .y = static_cast<s32>(draw_texture_state.src_y0)}, - Offset2D{.x = static_cast<s32>(draw_texture_state.src_x1), - .y = static_cast<s32>(draw_texture_state.src_y1)}}; - blit_image.BlitColor(texture_cache.GetFramebuffer(), texture.RenderTarget(), - texture.ImageHandle(), sampler->Handle(), dst_region, src_region, - texture.size); + const auto* framebuffer = texture_cache.GetFramebuffer(); + + const bool src_rescaling = texture_cache.IsRescaling() && texture.IsRescaled(); + const bool dst_rescaling = texture_cache.IsRescaling() && framebuffer->IsRescaled(); + + const auto ScaleSrc = [&](auto dim_f) -> s32 { + auto dim = static_cast<s32>(dim_f); + return src_rescaling ? Settings::values.resolution_info.ScaleUp(dim) : dim; + }; + + const auto ScaleDst = [&](auto dim_f) -> s32 { + auto dim = static_cast<s32>(dim_f); + return dst_rescaling ? Settings::values.resolution_info.ScaleUp(dim) : dim; + }; + + Region2D dst_region = {Offset2D{.x = ScaleDst(draw_texture_state.dst_x0), + .y = ScaleDst(draw_texture_state.dst_y0)}, + Offset2D{.x = ScaleDst(draw_texture_state.dst_x1), + .y = ScaleDst(draw_texture_state.dst_y1)}}; + Region2D src_region = {Offset2D{.x = ScaleSrc(draw_texture_state.src_x0), + .y = ScaleSrc(draw_texture_state.src_y0)}, + Offset2D{.x = ScaleSrc(draw_texture_state.src_x1), + .y = ScaleSrc(draw_texture_state.src_y1)}}; + Extent3D src_size = {static_cast<u32>(ScaleSrc(texture.size.width)), + static_cast<u32>(ScaleSrc(texture.size.height)), texture.size.depth}; + blit_image.BlitColor(framebuffer, texture.RenderTarget(), texture.ImageHandle(), + sampler->Handle(), dst_region, src_region, src_size); } void RasterizerVulkan::Clear(u32 layer_count) { @@ -1054,37 +1082,16 @@ void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) { regs.zeta.format == Tegra::DepthFormat::X8Z24_UNORM || regs.zeta.format == Tegra::DepthFormat::S8Z24_UNORM || regs.zeta.format == Tegra::DepthFormat::V8Z24_UNORM; - bool force_unorm = ([&] { - if (!is_d24 || device.SupportsD24DepthBuffer()) { - return false; - } - if (device.IsExtDepthBiasControlSupported()) { - return true; - } - if (!Settings::values.renderer_amdvlk_depth_bias_workaround) { - return false; - } + if (is_d24 && !device.SupportsD24DepthBuffer() && program_id == 0x1006A800016E000ULL) { + // Only activate this in Super Smash Brothers Ultimate // the base formulas can be obtained from here: // https://docs.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-output-merger-stage-depth-bias const double rescale_factor = static_cast<double>(1ULL << (32 - 24)) / (static_cast<double>(0x1.ep+127)); units = static_cast<float>(static_cast<double>(units) * rescale_factor); - return false; - })(); + } scheduler.Record([constant = units, clamp = regs.depth_bias_clamp, - factor = regs.slope_scale_depth_bias, force_unorm, - precise = device.HasExactDepthBiasControl()](vk::CommandBuffer cmdbuf) { - if (force_unorm) { - VkDepthBiasRepresentationInfoEXT info{ - .sType = VK_STRUCTURE_TYPE_DEPTH_BIAS_REPRESENTATION_INFO_EXT, - .pNext = nullptr, - .depthBiasRepresentation = - VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT, - .depthBiasExact = precise ? VK_TRUE : VK_FALSE, - }; - cmdbuf.SetDepthBias(constant, clamp, factor, &info); - return; - } + factor = regs.slope_scale_depth_bias](vk::CommandBuffer cmdbuf) { cmdbuf.SetDepthBias(constant, clamp, factor); }); } diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 832b5e2b1..6d4deb0eb 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -1962,21 +1962,22 @@ Framebuffer::Framebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM } Framebuffer::Framebuffer(TextureCacheRuntime& runtime, ImageView* color_buffer, - ImageView* depth_buffer, VkExtent2D extent, bool is_rescaled) + ImageView* depth_buffer, VkExtent2D extent, bool is_rescaled_) : render_area{extent} { std::array<ImageView*, NUM_RT> color_buffers{color_buffer}; - CreateFramebuffer(runtime, color_buffers, depth_buffer, is_rescaled); + CreateFramebuffer(runtime, color_buffers, depth_buffer, is_rescaled_); } Framebuffer::~Framebuffer() = default; void Framebuffer::CreateFramebuffer(TextureCacheRuntime& runtime, std::span<ImageView*, NUM_RT> color_buffers, - ImageView* depth_buffer, bool is_rescaled) { + ImageView* depth_buffer, bool is_rescaled_) { boost::container::small_vector<VkImageView, NUM_RT + 1> attachments; RenderPassKey renderpass_key{}; s32 num_layers = 1; + is_rescaled = is_rescaled_; const auto& resolution = runtime.resolution; u32 width = std::numeric_limits<u32>::max(); diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index aaeb5ef93..8501ec384 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -361,6 +361,10 @@ public: return has_stencil; } + [[nodiscard]] bool IsRescaled() const noexcept { + return is_rescaled; + } + private: vk::Framebuffer framebuffer; VkRenderPass renderpass{}; @@ -373,6 +377,7 @@ private: std::array<size_t, NUM_RT> rt_map{}; bool has_depth{}; bool has_stencil{}; + bool is_rescaled{}; }; struct TextureCacheParams { diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 53b4876f2..feb1c575e 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -72,12 +72,19 @@ TextureCache<P>::TextureCache(Runtime& runtime_, Tegra::MaxwellDeviceMemoryManag template <class P> void TextureCache<P>::RunGarbageCollector() { - bool high_priority_mode = total_used_memory >= expected_memory; - bool aggressive_mode = total_used_memory >= critical_memory; - const u64 ticks_to_destroy = aggressive_mode ? 10ULL : high_priority_mode ? 25ULL : 50ULL; - size_t num_iterations = aggressive_mode ? 40 : (high_priority_mode ? 20 : 10); - const auto clean_up = [this, &num_iterations, &high_priority_mode, - &aggressive_mode](ImageId image_id) { + bool high_priority_mode = false; + bool aggressive_mode = false; + u64 ticks_to_destroy = 0; + size_t num_iterations = 0; + + const auto Configure = [&](bool allow_aggressive) { + high_priority_mode = total_used_memory >= expected_memory; + aggressive_mode = allow_aggressive && total_used_memory >= critical_memory; + ticks_to_destroy = aggressive_mode ? 10ULL : high_priority_mode ? 25ULL : 50ULL; + num_iterations = aggressive_mode ? 40 : (high_priority_mode ? 20 : 10); + }; + const auto Cleanup = [this, &num_iterations, &high_priority_mode, + &aggressive_mode](ImageId image_id) { if (num_iterations == 0) { return true; } @@ -123,7 +130,16 @@ void TextureCache<P>::RunGarbageCollector() { } return false; }; - lru_cache.ForEachItemBelow(frame_tick - ticks_to_destroy, clean_up); + + // Try to remove anything old enough and not high priority. + Configure(false); + lru_cache.ForEachItemBelow(frame_tick - ticks_to_destroy, Cleanup); + + // If pressure is still too high, prune aggressively. + if (total_used_memory >= critical_memory) { + Configure(true); + lru_cache.ForEachItemBelow(frame_tick - ticks_to_destroy, Cleanup); + } } template <class P> @@ -2098,7 +2114,9 @@ void TextureCache<P>::TrackImage(ImageBase& image, ImageId image_id) { ASSERT(False(image.flags & ImageFlagBits::Tracked)); image.flags |= ImageFlagBits::Tracked; if (False(image.flags & ImageFlagBits::Sparse)) { - device_memory.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, 1); + if (image.cpu_addr < ~(1ULL << 40)) { + device_memory.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, 1); + } return; } if (True(image.flags & ImageFlagBits::Registered)) { @@ -2124,7 +2142,9 @@ void TextureCache<P>::UntrackImage(ImageBase& image, ImageId image_id) { ASSERT(True(image.flags & ImageFlagBits::Tracked)); image.flags &= ~ImageFlagBits::Tracked; if (False(image.flags & ImageFlagBits::Sparse)) { - device_memory.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, -1); + if (image.cpu_addr < ~(1ULL << 40)) { + device_memory.UpdatePagesCachedCount(image.cpu_addr, image.guest_size_bytes, -1); + } return; } ASSERT(True(image.flags & ImageFlagBits::Registered)); diff --git a/src/yuzu/configuration/configure_applets.cpp b/src/yuzu/configuration/configure_applets.cpp index 513ecb548..139bfa9da 100644 --- a/src/yuzu/configuration/configure_applets.cpp +++ b/src/yuzu/configuration/configure_applets.cpp @@ -59,9 +59,7 @@ void ConfigureApplets::Setup(const ConfigurationShared::Builder& builder) { // Untested applets if (setting->Id() == Settings::values.data_erase_applet_mode.Id() || - setting->Id() == Settings::values.error_applet_mode.Id() || setting->Id() == Settings::values.net_connect_applet_mode.Id() || - setting->Id() == Settings::values.web_applet_mode.Id() || setting->Id() == Settings::values.shop_applet_mode.Id() || setting->Id() == Settings::values.login_share_applet_mode.Id() || setting->Id() == Settings::values.wifi_web_auth_applet_mode.Id() || diff --git a/tools/reset-submodules.sh b/tools/reset-submodules.sh new file mode 100755 index 000000000..6fdfe0bcd --- /dev/null +++ b/tools/reset-submodules.sh @@ -0,0 +1,8 @@ +#!/bin/bash -ex + +# SPDX-FileCopyrightText: 2024 yuzu Emulator Project +# SPDX-License-Identifier: MIT + +git submodule sync +git submodule foreach --recursive git reset --hard +git submodule update --init --recursive |