summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio_core/renderer/command/mix/depop_prepare.h2
-rw-r--r--src/common/string_util.cpp5
-rw-r--r--src/common/string_util.h1
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/core.cpp4
-rw-r--r--src/core/debugger/gdbstub.cpp17
-rw-r--r--src/core/file_sys/vfs.h2
-rw-r--r--src/core/hle/kernel/k_memory_layout.cpp2
-rw-r--r--src/core/hle/kernel/k_page_table.cpp12
-rw-r--r--src/core/hle/service/am/am.cpp166
-rw-r--r--src/core/hle/service/am/am.h17
-rw-r--r--src/core/hle/service/am/applets/applet_cabinet.h11
-rw-r--r--src/core/hle/service/am/applets/applet_general_backend.cpp6
-rw-r--r--src/core/hle/service/am/applets/applets.cpp16
-rw-r--r--src/core/hle/service/am/applets/applets.h49
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp3
-rw-r--r--src/core/hle/service/ldn/ldn.cpp91
-rw-r--r--src/core/hle/service/nfc/common/device.cpp9
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.h14
-rw-r--r--src/core/hle/service/nvnflinger/buffer_item.h2
-rw-r--r--src/core/hle/service/nvnflinger/buffer_slot.h2
-rw-r--r--src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp351
-rw-r--r--src/core/hle/service/nvnflinger/fb_share_buffer_manager.h65
-rw-r--r--src/core/hle/service/nvnflinger/graphic_buffer_producer.h2
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.cpp11
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.h9
-rw-r--r--src/core/hle/service/nvnflinger/ui/fence.h3
-rw-r--r--src/core/hle/service/nvnflinger/ui/graphic_buffer.h4
-rw-r--r--src/core/hle/service/vi/vi.cpp129
-rw-r--r--src/input_common/drivers/virtual_gamepad.h2
-rw-r--r--src/input_common/helpers/joycon_protocol/generic_functions.h2
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp2
-rw-r--r--src/video_core/dma_pusher.h2
-rw-r--r--src/video_core/query_cache/bank_base.h1
-rw-r--r--src/video_core/renderer_opengl/maxwell_to_gl.h1
-rw-r--r--src/video_core/renderer_vulkan/maxwell_to_vk.cpp5
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp1
-rw-r--r--src/video_core/renderer_vulkan/vk_query_cache.cpp1
-rw-r--r--src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp33
-rw-r--r--src/video_core/renderer_vulkan/vk_staging_buffer_pool.h5
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp1
-rw-r--r--src/video_core/surface.cpp3
-rw-r--r--src/video_core/surface.h4
-rw-r--r--src/video_core/texture_cache/format_lookup_table.cpp4
-rw-r--r--src/video_core/texture_cache/formatter.h2
-rw-r--r--src/video_core/texture_cache/image_base.h2
-rw-r--r--src/video_core/texture_cache/image_view_base.cpp1
-rw-r--r--src/video_core/texture_cache/util.cpp2
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp56
-rw-r--r--src/video_core/vulkan_common/vulkan_device.h2
-rw-r--r--src/video_core/vulkan_common/vulkan_memory_allocator.cpp21
-rw-r--r--src/video_core/vulkan_common/vulkan_memory_allocator.h14
-rw-r--r--src/yuzu/configuration/configure_audio.cpp3
-rw-r--r--src/yuzu/configuration/shared_translation.cpp3
-rw-r--r--src/yuzu/main.cpp78
-rw-r--r--src/yuzu/main.h5
-rw-r--r--src/yuzu/main.ui30
-rw-r--r--src/yuzu/uisettings.h2
58 files changed, 1180 insertions, 115 deletions
diff --git a/src/audio_core/renderer/command/mix/depop_prepare.h b/src/audio_core/renderer/command/mix/depop_prepare.h
index 161a94461..a0cc228f7 100644
--- a/src/audio_core/renderer/command/mix/depop_prepare.h
+++ b/src/audio_core/renderer/command/mix/depop_prepare.h
@@ -16,7 +16,7 @@ namespace AudioCore::Renderer {
16 16
17/** 17/**
18 * AudioRenderer command for preparing depop. 18 * AudioRenderer command for preparing depop.
19 * Adds the previusly output last samples to the depop buffer. 19 * Adds the previously output last samples to the depop buffer.
20 */ 20 */
21struct DepopPrepareCommand : ICommand { 21struct DepopPrepareCommand : ICommand {
22 /** 22 /**
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp
index feab1653d..4c7aba3f5 100644
--- a/src/common/string_util.cpp
+++ b/src/common/string_util.cpp
@@ -135,6 +135,11 @@ std::u16string UTF8ToUTF16(std::string_view input) {
135 return convert.from_bytes(input.data(), input.data() + input.size()); 135 return convert.from_bytes(input.data(), input.data() + input.size());
136} 136}
137 137
138std::u32string UTF8ToUTF32(std::string_view input) {
139 std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert;
140 return convert.from_bytes(input.data(), input.data() + input.size());
141}
142
138#ifdef _WIN32 143#ifdef _WIN32
139static std::wstring CPToUTF16(u32 code_page, std::string_view input) { 144static std::wstring CPToUTF16(u32 code_page, std::string_view input) {
140 const auto size = 145 const auto size =
diff --git a/src/common/string_util.h b/src/common/string_util.h
index c351f1a0c..9da1ca4e9 100644
--- a/src/common/string_util.h
+++ b/src/common/string_util.h
@@ -38,6 +38,7 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _
38 38
39[[nodiscard]] std::string UTF16ToUTF8(std::u16string_view input); 39[[nodiscard]] std::string UTF16ToUTF8(std::u16string_view input);
40[[nodiscard]] std::u16string UTF8ToUTF16(std::string_view input); 40[[nodiscard]] std::u16string UTF8ToUTF16(std::string_view input);
41[[nodiscard]] std::u32string UTF8ToUTF32(std::string_view input);
41 42
42#ifdef _WIN32 43#ifdef _WIN32
43[[nodiscard]] std::string UTF16ToUTF8(std::wstring_view input); 44[[nodiscard]] std::string UTF16ToUTF8(std::wstring_view input);
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index d0f76e57e..e02ededfc 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -698,6 +698,8 @@ add_library(core STATIC
698 hle/service/nvnflinger/consumer_base.cpp 698 hle/service/nvnflinger/consumer_base.cpp
699 hle/service/nvnflinger/consumer_base.h 699 hle/service/nvnflinger/consumer_base.h
700 hle/service/nvnflinger/consumer_listener.h 700 hle/service/nvnflinger/consumer_listener.h
701 hle/service/nvnflinger/fb_share_buffer_manager.cpp
702 hle/service/nvnflinger/fb_share_buffer_manager.h
701 hle/service/nvnflinger/graphic_buffer_producer.cpp 703 hle/service/nvnflinger/graphic_buffer_producer.cpp
702 hle/service/nvnflinger/graphic_buffer_producer.h 704 hle/service/nvnflinger/graphic_buffer_producer.h
703 hle/service/nvnflinger/hos_binder_driver_server.cpp 705 hle/service/nvnflinger/hos_binder_driver_server.cpp
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 08cbb8978..0ab2e3b76 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -1078,6 +1078,10 @@ void System::ApplySettings() {
1078 impl->RefreshTime(); 1078 impl->RefreshTime();
1079 1079
1080 if (IsPoweredOn()) { 1080 if (IsPoweredOn()) {
1081 if (Settings::values.custom_rtc_enabled) {
1082 const s64 posix_time{Settings::values.custom_rtc.GetValue()};
1083 GetTimeManager().UpdateLocalSystemClockTime(posix_time);
1084 }
1081 Renderer().RefreshBaseSettings(); 1085 Renderer().RefreshBaseSettings();
1082 } 1086 }
1083} 1087}
diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp
index e55831f27..82964f0a1 100644
--- a/src/core/debugger/gdbstub.cpp
+++ b/src/core/debugger/gdbstub.cpp
@@ -2,6 +2,8 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <atomic> 4#include <atomic>
5#include <codecvt>
6#include <locale>
5#include <numeric> 7#include <numeric>
6#include <optional> 8#include <optional>
7#include <thread> 9#include <thread>
@@ -12,6 +14,7 @@
12#include "common/logging/log.h" 14#include "common/logging/log.h"
13#include "common/scope_exit.h" 15#include "common/scope_exit.h"
14#include "common/settings.h" 16#include "common/settings.h"
17#include "common/string_util.h"
15#include "core/arm/arm_interface.h" 18#include "core/arm/arm_interface.h"
16#include "core/core.h" 19#include "core/core.h"
17#include "core/debugger/gdbstub.h" 20#include "core/debugger/gdbstub.h"
@@ -68,10 +71,16 @@ static std::string EscapeGDB(std::string_view data) {
68} 71}
69 72
70static std::string EscapeXML(std::string_view data) { 73static std::string EscapeXML(std::string_view data) {
74 std::u32string converted = U"[Encoding error]";
75 try {
76 converted = Common::UTF8ToUTF32(data);
77 } catch (std::range_error&) {
78 }
79
71 std::string escaped; 80 std::string escaped;
72 escaped.reserve(data.size()); 81 escaped.reserve(data.size());
73 82
74 for (char c : data) { 83 for (char32_t c : converted) {
75 switch (c) { 84 switch (c) {
76 case '&': 85 case '&':
77 escaped += "&amp;"; 86 escaped += "&amp;";
@@ -86,7 +95,11 @@ static std::string EscapeXML(std::string_view data) {
86 escaped += "&gt;"; 95 escaped += "&gt;";
87 break; 96 break;
88 default: 97 default:
89 escaped += c; 98 if (c > 0x7f) {
99 escaped += fmt::format("&#{};", static_cast<u32>(c));
100 } else {
101 escaped += static_cast<char>(c);
102 }
90 break; 103 break;
91 } 104 }
92 } 105 }
diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h
index a93e21f67..a7cd1cae3 100644
--- a/src/core/file_sys/vfs.h
+++ b/src/core/file_sys/vfs.h
@@ -175,7 +175,7 @@ public:
175 return Write(reinterpret_cast<const u8*>(&data), sizeof(T), offset); 175 return Write(reinterpret_cast<const u8*>(&data), sizeof(T), offset);
176 } 176 }
177 177
178 // Renames the file to name. Returns whether or not the operation was successsful. 178 // Renames the file to name. Returns whether or not the operation was successful.
179 virtual bool Rename(std::string_view name) = 0; 179 virtual bool Rename(std::string_view name) = 0;
180 180
181 // Returns the full path of this file as a string, recursively 181 // Returns the full path of this file as a string, recursively
diff --git a/src/core/hle/kernel/k_memory_layout.cpp b/src/core/hle/kernel/k_memory_layout.cpp
index af40092c0..bec714668 100644
--- a/src/core/hle/kernel/k_memory_layout.cpp
+++ b/src/core/hle/kernel/k_memory_layout.cpp
@@ -61,7 +61,7 @@ bool KMemoryRegionTree::Insert(u64 address, size_t size, u32 type_id, u32 new_at
61 found->Reset(address, inserted_region_last, old_pair, new_attr, type_id); 61 found->Reset(address, inserted_region_last, old_pair, new_attr, type_id);
62 this->insert(*found); 62 this->insert(*found);
63 } else { 63 } else {
64 // If we can't re-use, adjust the old region. 64 // If we can't reuse, adjust the old region.
65 found->Reset(old_address, address - 1, old_pair, old_attr, old_type); 65 found->Reset(old_address, address - 1, old_pair, old_attr, old_type);
66 this->insert(*found); 66 this->insert(*found);
67 67
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp
index 9bfc85b34..5b51edf30 100644
--- a/src/core/hle/kernel/k_page_table.cpp
+++ b/src/core/hle/kernel/k_page_table.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/literals.h" 6#include "common/literals.h"
7#include "common/scope_exit.h" 7#include "common/scope_exit.h"
8#include "common/settings.h"
8#include "core/core.h" 9#include "core/core.h"
9#include "core/hle/kernel/k_address_space_info.h" 10#include "core/hle/kernel/k_address_space_info.h"
10#include "core/hle/kernel/k_memory_block.h" 11#include "core/hle/kernel/k_memory_block.h"
@@ -337,11 +338,14 @@ Result KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_type
337} 338}
338 339
339void KPageTable::Finalize() { 340void KPageTable::Finalize() {
341 auto HostUnmapCallback = [&](KProcessAddress addr, u64 size) {
342 if (Settings::IsFastmemEnabled()) {
343 m_system.DeviceMemory().buffer.Unmap(GetInteger(addr), size);
344 }
345 };
346
340 // Finalize memory blocks. 347 // Finalize memory blocks.
341 m_memory_block_manager.Finalize(m_memory_block_slab_manager, 348 m_memory_block_manager.Finalize(m_memory_block_slab_manager, std::move(HostUnmapCallback));
342 [&](KProcessAddress addr, u64 size) {
343 m_memory->UnmapRegion(*m_page_table_impl, addr, size);
344 });
345 349
346 // Release any insecure mapped memory. 350 // Release any insecure mapped memory.
347 if (m_mapped_insecure_memory) { 351 if (m_mapped_insecure_memory) {
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index a83622f7c..819dea6a7 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -8,6 +8,7 @@
8#include "common/settings.h" 8#include "common/settings.h"
9#include "common/settings_enums.h" 9#include "common/settings_enums.h"
10#include "core/core.h" 10#include "core/core.h"
11#include "core/core_timing.h"
11#include "core/file_sys/control_metadata.h" 12#include "core/file_sys/control_metadata.h"
12#include "core/file_sys/patch_manager.h" 13#include "core/file_sys/patch_manager.h"
13#include "core/file_sys/registered_cache.h" 14#include "core/file_sys/registered_cache.h"
@@ -19,6 +20,7 @@
19#include "core/hle/service/am/am.h" 20#include "core/hle/service/am/am.h"
20#include "core/hle/service/am/applet_ae.h" 21#include "core/hle/service/am/applet_ae.h"
21#include "core/hle/service/am/applet_oe.h" 22#include "core/hle/service/am/applet_oe.h"
23#include "core/hle/service/am/applets/applet_cabinet.h"
22#include "core/hle/service/am/applets/applet_mii_edit_types.h" 24#include "core/hle/service/am/applets/applet_mii_edit_types.h"
23#include "core/hle/service/am/applets/applet_profile_select.h" 25#include "core/hle/service/am/applets/applet_profile_select.h"
24#include "core/hle/service/am/applets/applet_web_browser.h" 26#include "core/hle/service/am/applets/applet_web_browser.h"
@@ -33,11 +35,13 @@
33#include "core/hle/service/filesystem/filesystem.h" 35#include "core/hle/service/filesystem/filesystem.h"
34#include "core/hle/service/ipc_helpers.h" 36#include "core/hle/service/ipc_helpers.h"
35#include "core/hle/service/ns/ns.h" 37#include "core/hle/service/ns/ns.h"
38#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
36#include "core/hle/service/nvnflinger/nvnflinger.h" 39#include "core/hle/service/nvnflinger/nvnflinger.h"
37#include "core/hle/service/pm/pm.h" 40#include "core/hle/service/pm/pm.h"
38#include "core/hle/service/server_manager.h" 41#include "core/hle/service/server_manager.h"
39#include "core/hle/service/sm/sm.h" 42#include "core/hle/service/sm/sm.h"
40#include "core/hle/service/vi/vi.h" 43#include "core/hle/service/vi/vi.h"
44#include "core/hle/service/vi/vi_results.h"
41#include "core/memory.h" 45#include "core/memory.h"
42 46
43namespace Service::AM { 47namespace Service::AM {
@@ -190,7 +194,7 @@ IDisplayController::IDisplayController(Core::System& system_)
190 {4, nullptr, "UpdateCallerAppletCaptureImage"}, 194 {4, nullptr, "UpdateCallerAppletCaptureImage"},
191 {5, nullptr, "GetLastForegroundCaptureImageEx"}, 195 {5, nullptr, "GetLastForegroundCaptureImageEx"},
192 {6, nullptr, "GetLastApplicationCaptureImageEx"}, 196 {6, nullptr, "GetLastApplicationCaptureImageEx"},
193 {7, nullptr, "GetCallerAppletCaptureImageEx"}, 197 {7, &IDisplayController::GetCallerAppletCaptureImageEx, "GetCallerAppletCaptureImageEx"},
194 {8, &IDisplayController::TakeScreenShotOfOwnLayer, "TakeScreenShotOfOwnLayer"}, 198 {8, &IDisplayController::TakeScreenShotOfOwnLayer, "TakeScreenShotOfOwnLayer"},
195 {9, nullptr, "CopyBetweenCaptureBuffers"}, 199 {9, nullptr, "CopyBetweenCaptureBuffers"},
196 {10, nullptr, "AcquireLastApplicationCaptureBuffer"}, 200 {10, nullptr, "AcquireLastApplicationCaptureBuffer"},
@@ -208,8 +212,8 @@ IDisplayController::IDisplayController(Core::System& system_)
208 {23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"}, 212 {23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"},
209 {24, nullptr, "AcquireLastForegroundCaptureSharedBuffer"}, 213 {24, nullptr, "AcquireLastForegroundCaptureSharedBuffer"},
210 {25, nullptr, "ReleaseLastForegroundCaptureSharedBuffer"}, 214 {25, nullptr, "ReleaseLastForegroundCaptureSharedBuffer"},
211 {26, nullptr, "AcquireCallerAppletCaptureSharedBuffer"}, 215 {26, &IDisplayController::AcquireCallerAppletCaptureSharedBuffer, "AcquireCallerAppletCaptureSharedBuffer"},
212 {27, nullptr, "ReleaseCallerAppletCaptureSharedBuffer"}, 216 {27, &IDisplayController::ReleaseCallerAppletCaptureSharedBuffer, "ReleaseCallerAppletCaptureSharedBuffer"},
213 {28, nullptr, "TakeScreenShotOfOwnLayerEx"}, 217 {28, nullptr, "TakeScreenShotOfOwnLayerEx"},
214 }; 218 };
215 // clang-format on 219 // clang-format on
@@ -219,6 +223,15 @@ IDisplayController::IDisplayController(Core::System& system_)
219 223
220IDisplayController::~IDisplayController() = default; 224IDisplayController::~IDisplayController() = default;
221 225
226void IDisplayController::GetCallerAppletCaptureImageEx(HLERequestContext& ctx) {
227 LOG_WARNING(Service_AM, "(STUBBED) called");
228
229 IPC::ResponseBuilder rb{ctx, 4};
230 rb.Push(ResultSuccess);
231 rb.Push(1u);
232 rb.Push(0);
233}
234
222void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) { 235void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) {
223 LOG_WARNING(Service_AM, "(STUBBED) called"); 236 LOG_WARNING(Service_AM, "(STUBBED) called");
224 237
@@ -226,6 +239,22 @@ void IDisplayController::TakeScreenShotOfOwnLayer(HLERequestContext& ctx) {
226 rb.Push(ResultSuccess); 239 rb.Push(ResultSuccess);
227} 240}
228 241
242void IDisplayController::AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) {
243 LOG_WARNING(Service_AM, "(STUBBED) called");
244
245 IPC::ResponseBuilder rb{ctx, 4};
246 rb.Push(ResultSuccess);
247 rb.Push(1U);
248 rb.Push(0);
249}
250
251void IDisplayController::ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx) {
252 LOG_WARNING(Service_AM, "(STUBBED) called");
253
254 IPC::ResponseBuilder rb{ctx, 2};
255 rb.Push(ResultSuccess);
256}
257
229IDebugFunctions::IDebugFunctions(Core::System& system_) 258IDebugFunctions::IDebugFunctions(Core::System& system_)
230 : ServiceFramework{system_, "IDebugFunctions"} { 259 : ServiceFramework{system_, "IDebugFunctions"} {
231 // clang-format off 260 // clang-format off
@@ -285,14 +314,14 @@ ISelfController::ISelfController(Core::System& system_, Nvnflinger::Nvnflinger&
285 {20, nullptr, "SetDesirableKeyboardLayout"}, 314 {20, nullptr, "SetDesirableKeyboardLayout"},
286 {21, nullptr, "GetScreenShotProgramId"}, 315 {21, nullptr, "GetScreenShotProgramId"},
287 {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"}, 316 {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
288 {41, nullptr, "IsSystemBufferSharingEnabled"}, 317 {41, &ISelfController::IsSystemBufferSharingEnabled, "IsSystemBufferSharingEnabled"},
289 {42, nullptr, "GetSystemSharedLayerHandle"}, 318 {42, &ISelfController::GetSystemSharedLayerHandle, "GetSystemSharedLayerHandle"},
290 {43, nullptr, "GetSystemSharedBufferHandle"}, 319 {43, &ISelfController::GetSystemSharedBufferHandle, "GetSystemSharedBufferHandle"},
291 {44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"}, 320 {44, &ISelfController::CreateManagedDisplaySeparableLayer, "CreateManagedDisplaySeparableLayer"},
292 {45, nullptr, "SetManagedDisplayLayerSeparationMode"}, 321 {45, nullptr, "SetManagedDisplayLayerSeparationMode"},
293 {46, nullptr, "SetRecordingLayerCompositionEnabled"}, 322 {46, nullptr, "SetRecordingLayerCompositionEnabled"},
294 {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"}, 323 {50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
295 {51, nullptr, "ApproveToDisplay"}, 324 {51, &ISelfController::ApproveToDisplay, "ApproveToDisplay"},
296 {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"}, 325 {60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
297 {61, nullptr, "SetMediaPlaybackState"}, 326 {61, nullptr, "SetMediaPlaybackState"},
298 {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"}, 327 {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"},
@@ -491,6 +520,50 @@ void ISelfController::CreateManagedDisplayLayer(HLERequestContext& ctx) {
491 rb.Push(*layer_id); 520 rb.Push(*layer_id);
492} 521}
493 522
523void ISelfController::IsSystemBufferSharingEnabled(HLERequestContext& ctx) {
524 LOG_WARNING(Service_AM, "(STUBBED) called");
525
526 IPC::ResponseBuilder rb{ctx, 2};
527 rb.Push(this->EnsureBufferSharingEnabled());
528}
529
530void ISelfController::GetSystemSharedLayerHandle(HLERequestContext& ctx) {
531 LOG_WARNING(Service_AM, "(STUBBED) called");
532
533 IPC::ResponseBuilder rb{ctx, 6};
534 rb.Push(this->EnsureBufferSharingEnabled());
535 rb.Push<s64>(system_shared_buffer_id);
536 rb.Push<s64>(system_shared_layer_id);
537}
538
539void ISelfController::GetSystemSharedBufferHandle(HLERequestContext& ctx) {
540 LOG_WARNING(Service_AM, "(STUBBED) called");
541
542 IPC::ResponseBuilder rb{ctx, 4};
543 rb.Push(this->EnsureBufferSharingEnabled());
544 rb.Push<s64>(system_shared_buffer_id);
545}
546
547Result ISelfController::EnsureBufferSharingEnabled() {
548 if (buffer_sharing_enabled) {
549 return ResultSuccess;
550 }
551
552 if (system.GetAppletManager().GetCurrentAppletId() <= Applets::AppletId::Application) {
553 return VI::ResultOperationFailed;
554 }
555
556 const auto display_id = nvnflinger.OpenDisplay("Default");
557 const auto result = nvnflinger.GetSystemBufferManager().Initialize(
558 &system_shared_buffer_id, &system_shared_layer_id, *display_id);
559
560 if (result.IsSuccess()) {
561 buffer_sharing_enabled = true;
562 }
563
564 return result;
565}
566
494void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) { 567void ISelfController::CreateManagedDisplaySeparableLayer(HLERequestContext& ctx) {
495 LOG_WARNING(Service_AM, "(STUBBED) called"); 568 LOG_WARNING(Service_AM, "(STUBBED) called");
496 569
@@ -516,6 +589,13 @@ void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) {
516 rb.Push(ResultSuccess); 589 rb.Push(ResultSuccess);
517} 590}
518 591
592void ISelfController::ApproveToDisplay(HLERequestContext& ctx) {
593 LOG_WARNING(Service_AM, "(STUBBED) called");
594
595 IPC::ResponseBuilder rb{ctx, 2};
596 rb.Push(ResultSuccess);
597}
598
519void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) { 599void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
520 IPC::RequestParser rp{ctx}; 600 IPC::RequestParser rp{ctx};
521 idle_time_detection_extension = rp.Pop<u32>(); 601 idle_time_detection_extension = rp.Pop<u32>();
@@ -686,7 +766,8 @@ void AppletMessageQueue::OperationModeChanged() {
686 766
687ICommonStateGetter::ICommonStateGetter(Core::System& system_, 767ICommonStateGetter::ICommonStateGetter(Core::System& system_,
688 std::shared_ptr<AppletMessageQueue> msg_queue_) 768 std::shared_ptr<AppletMessageQueue> msg_queue_)
689 : ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)} { 769 : ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)},
770 service_context{system_, "ICommonStateGetter"} {
690 // clang-format off 771 // clang-format off
691 static const FunctionInfo functions[] = { 772 static const FunctionInfo functions[] = {
692 {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, 773 {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
@@ -699,10 +780,10 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
699 {7, nullptr, "GetCradleStatus"}, 780 {7, nullptr, "GetCradleStatus"},
700 {8, &ICommonStateGetter::GetBootMode, "GetBootMode"}, 781 {8, &ICommonStateGetter::GetBootMode, "GetBootMode"},
701 {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"}, 782 {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"},
702 {10, nullptr, "RequestToAcquireSleepLock"}, 783 {10, &ICommonStateGetter::RequestToAcquireSleepLock, "RequestToAcquireSleepLock"},
703 {11, nullptr, "ReleaseSleepLock"}, 784 {11, nullptr, "ReleaseSleepLock"},
704 {12, nullptr, "ReleaseSleepLockTransiently"}, 785 {12, nullptr, "ReleaseSleepLockTransiently"},
705 {13, nullptr, "GetAcquiredSleepLockEvent"}, 786 {13, &ICommonStateGetter::GetAcquiredSleepLockEvent, "GetAcquiredSleepLockEvent"},
706 {14, nullptr, "GetWakeupCount"}, 787 {14, nullptr, "GetWakeupCount"},
707 {20, nullptr, "PushToGeneralChannel"}, 788 {20, nullptr, "PushToGeneralChannel"},
708 {30, nullptr, "GetHomeButtonReaderLockAccessor"}, 789 {30, nullptr, "GetHomeButtonReaderLockAccessor"},
@@ -745,6 +826,8 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
745 826
746 RegisterHandlers(functions); 827 RegisterHandlers(functions);
747 828
829 sleep_lock_event = service_context.CreateEvent("ICommonStateGetter::SleepLockEvent");
830
748 // Configure applets to be in foreground state 831 // Configure applets to be in foreground state
749 msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged); 832 msg_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
750 msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground); 833 msg_queue->PushMessage(AppletMessageQueue::AppletMessage::ChangeIntoForeground);
@@ -793,6 +876,24 @@ void ICommonStateGetter::GetCurrentFocusState(HLERequestContext& ctx) {
793 rb.Push(static_cast<u8>(FocusState::InFocus)); 876 rb.Push(static_cast<u8>(FocusState::InFocus));
794} 877}
795 878
879void ICommonStateGetter::RequestToAcquireSleepLock(HLERequestContext& ctx) {
880 LOG_WARNING(Service_AM, "(STUBBED) called");
881
882 // Sleep lock is acquired immediately.
883 sleep_lock_event->Signal();
884
885 IPC::ResponseBuilder rb{ctx, 2};
886 rb.Push(ResultSuccess);
887}
888
889void ICommonStateGetter::GetAcquiredSleepLockEvent(HLERequestContext& ctx) {
890 LOG_WARNING(Service_AM, "called");
891
892 IPC::ResponseBuilder rb{ctx, 2, 1};
893 rb.Push(ResultSuccess);
894 rb.PushCopyObjects(sleep_lock_event->GetReadableEvent());
895}
896
796void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) { 897void ICommonStateGetter::IsVrModeEnabled(HLERequestContext& ctx) {
797 LOG_DEBUG(Service_AM, "called"); 898 LOG_DEBUG(Service_AM, "called");
798 899
@@ -1385,7 +1486,16 @@ ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_)
1385 // clang-format on 1486 // clang-format on
1386 RegisterHandlers(functions); 1487 RegisterHandlers(functions);
1387 1488
1388 PushInShowMiiEditData(); 1489 switch (system.GetAppletManager().GetCurrentAppletId()) {
1490 case Applets::AppletId::Cabinet:
1491 PushInShowCabinetData();
1492 break;
1493 case Applets::AppletId::MiiEdit:
1494 PushInShowMiiEditData();
1495 break;
1496 default:
1497 break;
1498 }
1389} 1499}
1390 1500
1391ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default; 1501ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default;
@@ -1431,7 +1541,7 @@ void ILibraryAppletSelfAccessor::GetLibraryAppletInfo(HLERequestContext& ctx) {
1431 LOG_WARNING(Service_AM, "(STUBBED) called"); 1541 LOG_WARNING(Service_AM, "(STUBBED) called");
1432 1542
1433 const LibraryAppletInfo applet_info{ 1543 const LibraryAppletInfo applet_info{
1434 .applet_id = Applets::AppletId::MiiEdit, 1544 .applet_id = system.GetAppletManager().GetCurrentAppletId(),
1435 .library_applet_mode = Applets::LibraryAppletMode::AllForeground, 1545 .library_applet_mode = Applets::LibraryAppletMode::AllForeground,
1436 }; 1546 };
1437 1547
@@ -1459,6 +1569,35 @@ void ILibraryAppletSelfAccessor::GetCallerAppletIdentityInfo(HLERequestContext&
1459 rb.PushRaw(applet_info); 1569 rb.PushRaw(applet_info);
1460} 1570}
1461 1571
1572void ILibraryAppletSelfAccessor::PushInShowCabinetData() {
1573 const Applets::CommonArguments arguments{
1574 .arguments_version = Applets::CommonArgumentVersion::Version3,
1575 .size = Applets::CommonArgumentSize::Version3,
1576 .library_version = static_cast<u32>(Applets::CabinetAppletVersion::Version1),
1577 .theme_color = Applets::ThemeColor::BasicBlack,
1578 .play_startup_sound = true,
1579 .system_tick = system.CoreTiming().GetClockTicks(),
1580 };
1581
1582 const Applets::StartParamForAmiiboSettings amiibo_settings{
1583 .param_1 = 0,
1584 .applet_mode = system.GetAppletManager().GetCabinetMode(),
1585 .flags = Applets::CabinetFlags::None,
1586 .amiibo_settings_1 = 0,
1587 .device_handle = 0,
1588 .tag_info{},
1589 .register_info{},
1590 .amiibo_settings_3{},
1591 };
1592
1593 std::vector<u8> argument_data(sizeof(arguments));
1594 std::vector<u8> settings_data(sizeof(amiibo_settings));
1595 std::memcpy(argument_data.data(), &arguments, sizeof(arguments));
1596 std::memcpy(settings_data.data(), &amiibo_settings, sizeof(amiibo_settings));
1597 queue_data.emplace_back(std::move(argument_data));
1598 queue_data.emplace_back(std::move(settings_data));
1599}
1600
1462void ILibraryAppletSelfAccessor::PushInShowMiiEditData() { 1601void ILibraryAppletSelfAccessor::PushInShowMiiEditData() {
1463 struct MiiEditV3 { 1602 struct MiiEditV3 {
1464 Applets::MiiEditAppletInputCommon common; 1603 Applets::MiiEditAppletInputCommon common;
@@ -2235,7 +2374,7 @@ void IProcessWindingController::GetLaunchReason(HLERequestContext& ctx) {
2235} 2374}
2236 2375
2237void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) { 2376void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx) {
2238 const auto applet_id = Applets::AppletId::MiiEdit; 2377 const auto applet_id = system.GetAppletManager().GetCurrentAppletId();
2239 const auto applet_mode = Applets::LibraryAppletMode::AllForeground; 2378 const auto applet_mode = Applets::LibraryAppletMode::AllForeground;
2240 2379
2241 LOG_WARNING(Service_AM, "(STUBBED) called with applet_id={:08X}, applet_mode={:08X}", applet_id, 2380 LOG_WARNING(Service_AM, "(STUBBED) called with applet_id={:08X}, applet_mode={:08X}", applet_id,
@@ -2256,4 +2395,5 @@ void IProcessWindingController::OpenCallingLibraryApplet(HLERequestContext& ctx)
2256 rb.Push(ResultSuccess); 2395 rb.Push(ResultSuccess);
2257 rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet); 2396 rb.PushIpcInterface<ILibraryAppletAccessor>(system, applet);
2258} 2397}
2398
2259} // namespace Service::AM 2399} // namespace Service::AM
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 5b97eb5e3..349482dcc 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -122,7 +122,10 @@ public:
122 ~IDisplayController() override; 122 ~IDisplayController() override;
123 123
124private: 124private:
125 void GetCallerAppletCaptureImageEx(HLERequestContext& ctx);
125 void TakeScreenShotOfOwnLayer(HLERequestContext& ctx); 126 void TakeScreenShotOfOwnLayer(HLERequestContext& ctx);
127 void AcquireCallerAppletCaptureSharedBuffer(HLERequestContext& ctx);
128 void ReleaseCallerAppletCaptureSharedBuffer(HLERequestContext& ctx);
126}; 129};
127 130
128class IDebugFunctions final : public ServiceFramework<IDebugFunctions> { 131class IDebugFunctions final : public ServiceFramework<IDebugFunctions> {
@@ -150,9 +153,13 @@ private:
150 void SetRestartMessageEnabled(HLERequestContext& ctx); 153 void SetRestartMessageEnabled(HLERequestContext& ctx);
151 void SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx); 154 void SetOutOfFocusSuspendingEnabled(HLERequestContext& ctx);
152 void SetAlbumImageOrientation(HLERequestContext& ctx); 155 void SetAlbumImageOrientation(HLERequestContext& ctx);
156 void IsSystemBufferSharingEnabled(HLERequestContext& ctx);
157 void GetSystemSharedBufferHandle(HLERequestContext& ctx);
158 void GetSystemSharedLayerHandle(HLERequestContext& ctx);
153 void CreateManagedDisplayLayer(HLERequestContext& ctx); 159 void CreateManagedDisplayLayer(HLERequestContext& ctx);
154 void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx); 160 void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx);
155 void SetHandlesRequestToDisplay(HLERequestContext& ctx); 161 void SetHandlesRequestToDisplay(HLERequestContext& ctx);
162 void ApproveToDisplay(HLERequestContext& ctx);
156 void SetIdleTimeDetectionExtension(HLERequestContext& ctx); 163 void SetIdleTimeDetectionExtension(HLERequestContext& ctx);
157 void GetIdleTimeDetectionExtension(HLERequestContext& ctx); 164 void GetIdleTimeDetectionExtension(HLERequestContext& ctx);
158 void ReportUserIsActive(HLERequestContext& ctx); 165 void ReportUserIsActive(HLERequestContext& ctx);
@@ -164,6 +171,8 @@ private:
164 void SaveCurrentScreenshot(HLERequestContext& ctx); 171 void SaveCurrentScreenshot(HLERequestContext& ctx);
165 void SetRecordVolumeMuted(HLERequestContext& ctx); 172 void SetRecordVolumeMuted(HLERequestContext& ctx);
166 173
174 Result EnsureBufferSharingEnabled();
175
167 enum class ScreenshotPermission : u32 { 176 enum class ScreenshotPermission : u32 {
168 Inherit = 0, 177 Inherit = 0,
169 Enable = 1, 178 Enable = 1,
@@ -179,7 +188,10 @@ private:
179 188
180 u32 idle_time_detection_extension = 0; 189 u32 idle_time_detection_extension = 0;
181 u64 num_fatal_sections_entered = 0; 190 u64 num_fatal_sections_entered = 0;
191 u64 system_shared_buffer_id = 0;
192 u64 system_shared_layer_id = 0;
182 bool is_auto_sleep_disabled = false; 193 bool is_auto_sleep_disabled = false;
194 bool buffer_sharing_enabled = false;
183 ScreenshotPermission screenshot_permission = ScreenshotPermission::Inherit; 195 ScreenshotPermission screenshot_permission = ScreenshotPermission::Inherit;
184}; 196};
185 197
@@ -223,6 +235,8 @@ private:
223 void GetEventHandle(HLERequestContext& ctx); 235 void GetEventHandle(HLERequestContext& ctx);
224 void ReceiveMessage(HLERequestContext& ctx); 236 void ReceiveMessage(HLERequestContext& ctx);
225 void GetCurrentFocusState(HLERequestContext& ctx); 237 void GetCurrentFocusState(HLERequestContext& ctx);
238 void RequestToAcquireSleepLock(HLERequestContext& ctx);
239 void GetAcquiredSleepLockEvent(HLERequestContext& ctx);
226 void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx); 240 void GetDefaultDisplayResolutionChangeEvent(HLERequestContext& ctx);
227 void GetOperationMode(HLERequestContext& ctx); 241 void GetOperationMode(HLERequestContext& ctx);
228 void GetPerformanceMode(HLERequestContext& ctx); 242 void GetPerformanceMode(HLERequestContext& ctx);
@@ -240,6 +254,8 @@ private:
240 254
241 std::shared_ptr<AppletMessageQueue> msg_queue; 255 std::shared_ptr<AppletMessageQueue> msg_queue;
242 bool vr_mode_state{}; 256 bool vr_mode_state{};
257 Kernel::KEvent* sleep_lock_event;
258 KernelHelpers::ServiceContext service_context;
243}; 259};
244 260
245class IStorageImpl { 261class IStorageImpl {
@@ -311,6 +327,7 @@ private:
311 void ExitProcessAndReturn(HLERequestContext& ctx); 327 void ExitProcessAndReturn(HLERequestContext& ctx);
312 void GetCallerAppletIdentityInfo(HLERequestContext& ctx); 328 void GetCallerAppletIdentityInfo(HLERequestContext& ctx);
313 329
330 void PushInShowCabinetData();
314 void PushInShowMiiEditData(); 331 void PushInShowMiiEditData();
315 332
316 std::deque<std::vector<u8>> queue_data; 333 std::deque<std::vector<u8>> queue_data;
diff --git a/src/core/hle/service/am/applets/applet_cabinet.h b/src/core/hle/service/am/applets/applet_cabinet.h
index b56427021..f498796f7 100644
--- a/src/core/hle/service/am/applets/applet_cabinet.h
+++ b/src/core/hle/service/am/applets/applet_cabinet.h
@@ -29,6 +29,15 @@ enum class CabinetAppletVersion : u32 {
29 Version1 = 0x1, 29 Version1 = 0x1,
30}; 30};
31 31
32enum class CabinetFlags : u8 {
33 None = 0,
34 DeviceHandle = 1 << 0,
35 TagInfo = 1 << 1,
36 RegisterInfo = 1 << 2,
37 All = DeviceHandle | TagInfo | RegisterInfo,
38};
39DECLARE_ENUM_FLAG_OPERATORS(CabinetFlags)
40
32enum class CabinetResult : u8 { 41enum class CabinetResult : u8 {
33 Cancel = 0, 42 Cancel = 0,
34 TagInfo = 1 << 1, 43 TagInfo = 1 << 1,
@@ -51,7 +60,7 @@ static_assert(sizeof(AmiiboSettingsStartParam) == 0x30,
51struct StartParamForAmiiboSettings { 60struct StartParamForAmiiboSettings {
52 u8 param_1; 61 u8 param_1;
53 Service::NFP::CabinetMode applet_mode; 62 Service::NFP::CabinetMode applet_mode;
54 u8 flags; 63 CabinetFlags flags;
55 u8 amiibo_settings_1; 64 u8 amiibo_settings_1;
56 u64 device_handle; 65 u64 device_handle;
57 Service::NFP::TagInfo tag_info; 66 Service::NFP::TagInfo tag_info;
diff --git a/src/core/hle/service/am/applets/applet_general_backend.cpp b/src/core/hle/service/am/applets/applet_general_backend.cpp
index 8b352020e..c0032f652 100644
--- a/src/core/hle/service/am/applets/applet_general_backend.cpp
+++ b/src/core/hle/service/am/applets/applet_general_backend.cpp
@@ -223,9 +223,9 @@ void StubApplet::Initialize() {
223 223
224 const auto data = broker.PeekDataToAppletForDebug(); 224 const auto data = broker.PeekDataToAppletForDebug();
225 system.GetReporter().SaveUnimplementedAppletReport( 225 system.GetReporter().SaveUnimplementedAppletReport(
226 static_cast<u32>(id), common_args.arguments_version, common_args.library_version, 226 static_cast<u32>(id), static_cast<u32>(common_args.arguments_version),
227 common_args.theme_color, common_args.play_startup_sound, common_args.system_tick, 227 common_args.library_version, static_cast<u32>(common_args.theme_color),
228 data.normal, data.interactive); 228 common_args.play_startup_sound, common_args.system_tick, data.normal, data.interactive);
229 229
230 LogCurrentStorage(broker, "Initialize"); 230 LogCurrentStorage(broker, "Initialize");
231} 231}
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index 10afbc2da..89d5434af 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -199,6 +199,14 @@ const AppletFrontendSet& AppletManager::GetAppletFrontendSet() const {
199 return frontend; 199 return frontend;
200} 200}
201 201
202NFP::CabinetMode AppletManager::GetCabinetMode() const {
203 return cabinet_mode;
204}
205
206AppletId AppletManager::GetCurrentAppletId() const {
207 return current_applet_id;
208}
209
202void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) { 210void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) {
203 if (set.cabinet != nullptr) { 211 if (set.cabinet != nullptr) {
204 frontend.cabinet = std::move(set.cabinet); 212 frontend.cabinet = std::move(set.cabinet);
@@ -237,6 +245,14 @@ void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) {
237 } 245 }
238} 246}
239 247
248void AppletManager::SetCabinetMode(NFP::CabinetMode mode) {
249 cabinet_mode = mode;
250}
251
252void AppletManager::SetCurrentAppletId(AppletId applet_id) {
253 current_applet_id = applet_id;
254}
255
240void AppletManager::SetDefaultAppletFrontendSet() { 256void AppletManager::SetDefaultAppletFrontendSet() {
241 ClearAll(); 257 ClearAll();
242 SetDefaultAppletsIfMissing(); 258 SetDefaultAppletsIfMissing();
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index 12f374199..f02bbc450 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -34,6 +34,10 @@ class KEvent;
34class KReadableEvent; 34class KReadableEvent;
35} // namespace Kernel 35} // namespace Kernel
36 36
37namespace Service::NFP {
38enum class CabinetMode : u8;
39} // namespace Service::NFP
40
37namespace Service::AM { 41namespace Service::AM {
38 42
39class IStorage; 43class IStorage;
@@ -41,6 +45,8 @@ class IStorage;
41namespace Applets { 45namespace Applets {
42 46
43enum class AppletId : u32 { 47enum class AppletId : u32 {
48 None = 0x00,
49 Application = 0x01,
44 OverlayDisplay = 0x02, 50 OverlayDisplay = 0x02,
45 QLaunch = 0x03, 51 QLaunch = 0x03,
46 Starter = 0x04, 52 Starter = 0x04,
@@ -71,6 +77,32 @@ enum class LibraryAppletMode : u32 {
71 AllForegroundInitiallyHidden = 4, 77 AllForegroundInitiallyHidden = 4,
72}; 78};
73 79
80enum class CommonArgumentVersion : u32 {
81 Version0,
82 Version1,
83 Version2,
84 Version3,
85};
86
87enum class CommonArgumentSize : u32 {
88 Version3 = 0x20,
89};
90
91enum class ThemeColor : u32 {
92 BasicWhite = 0,
93 BasicBlack = 3,
94};
95
96struct CommonArguments {
97 CommonArgumentVersion arguments_version;
98 CommonArgumentSize size;
99 u32 library_version;
100 ThemeColor theme_color;
101 bool play_startup_sound;
102 u64_le system_tick;
103};
104static_assert(sizeof(CommonArguments) == 0x20, "CommonArguments has incorrect size.");
105
74class AppletDataBroker final { 106class AppletDataBroker final {
75public: 107public:
76 explicit AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_); 108 explicit AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_);
@@ -161,16 +193,6 @@ public:
161 } 193 }
162 194
163protected: 195protected:
164 struct CommonArguments {
165 u32_le arguments_version;
166 u32_le size;
167 u32_le library_version;
168 u32_le theme_color;
169 bool play_startup_sound;
170 u64_le system_tick;
171 };
172 static_assert(sizeof(CommonArguments) == 0x20, "CommonArguments has incorrect size.");
173
174 CommonArguments common_args{}; 196 CommonArguments common_args{};
175 AppletDataBroker broker; 197 AppletDataBroker broker;
176 LibraryAppletMode applet_mode; 198 LibraryAppletMode applet_mode;
@@ -219,8 +241,12 @@ public:
219 ~AppletManager(); 241 ~AppletManager();
220 242
221 const AppletFrontendSet& GetAppletFrontendSet() const; 243 const AppletFrontendSet& GetAppletFrontendSet() const;
244 NFP::CabinetMode GetCabinetMode() const;
245 AppletId GetCurrentAppletId() const;
222 246
223 void SetAppletFrontendSet(AppletFrontendSet set); 247 void SetAppletFrontendSet(AppletFrontendSet set);
248 void SetCabinetMode(NFP::CabinetMode mode);
249 void SetCurrentAppletId(AppletId applet_id);
224 void SetDefaultAppletFrontendSet(); 250 void SetDefaultAppletFrontendSet();
225 void SetDefaultAppletsIfMissing(); 251 void SetDefaultAppletsIfMissing();
226 void ClearAll(); 252 void ClearAll();
@@ -228,6 +254,9 @@ public:
228 std::shared_ptr<Applet> GetApplet(AppletId id, LibraryAppletMode mode) const; 254 std::shared_ptr<Applet> GetApplet(AppletId id, LibraryAppletMode mode) const;
229 255
230private: 256private:
257 AppletId current_applet_id{};
258 NFP::CabinetMode cabinet_mode{};
259
231 AppletFrontendSet frontend; 260 AppletFrontendSet frontend;
232 Core::System& system; 261 Core::System& system;
233}; 262};
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index c2054e8a0..126cd6ffd 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -855,6 +855,9 @@ FSP_SRV::FSP_SRV(Core::System& system_)
855 if (Settings::values.enable_fs_access_log) { 855 if (Settings::values.enable_fs_access_log) {
856 access_log_mode = AccessLogMode::SdCard; 856 access_log_mode = AccessLogMode::SdCard;
857 } 857 }
858
859 // This should be true on creation
860 fsc.SetAutoSaveDataCreation(true);
858} 861}
859 862
860FSP_SRV::~FSP_SRV() = default; 863FSP_SRV::~FSP_SRV() = default;
diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp
index 9d149a7cd..7927f8264 100644
--- a/src/core/hle/service/ldn/ldn.cpp
+++ b/src/core/hle/service/ldn/ldn.cpp
@@ -23,19 +23,39 @@ public:
23 explicit IMonitorService(Core::System& system_) : ServiceFramework{system_, "IMonitorService"} { 23 explicit IMonitorService(Core::System& system_) : ServiceFramework{system_, "IMonitorService"} {
24 // clang-format off 24 // clang-format off
25 static const FunctionInfo functions[] = { 25 static const FunctionInfo functions[] = {
26 {0, nullptr, "GetStateForMonitor"}, 26 {0, &IMonitorService::GetStateForMonitor, "GetStateForMonitor"},
27 {1, nullptr, "GetNetworkInfoForMonitor"}, 27 {1, nullptr, "GetNetworkInfoForMonitor"},
28 {2, nullptr, "GetIpv4AddressForMonitor"}, 28 {2, nullptr, "GetIpv4AddressForMonitor"},
29 {3, nullptr, "GetDisconnectReasonForMonitor"}, 29 {3, nullptr, "GetDisconnectReasonForMonitor"},
30 {4, nullptr, "GetSecurityParameterForMonitor"}, 30 {4, nullptr, "GetSecurityParameterForMonitor"},
31 {5, nullptr, "GetNetworkConfigForMonitor"}, 31 {5, nullptr, "GetNetworkConfigForMonitor"},
32 {100, nullptr, "InitializeMonitor"}, 32 {100, &IMonitorService::InitializeMonitor, "InitializeMonitor"},
33 {101, nullptr, "FinalizeMonitor"}, 33 {101, nullptr, "FinalizeMonitor"},
34 }; 34 };
35 // clang-format on 35 // clang-format on
36 36
37 RegisterHandlers(functions); 37 RegisterHandlers(functions);
38 } 38 }
39
40private:
41 void GetStateForMonitor(HLERequestContext& ctx) {
42 LOG_INFO(Service_LDN, "called");
43
44 IPC::ResponseBuilder rb{ctx, 3};
45 rb.Push(ResultSuccess);
46 rb.PushEnum(state);
47 }
48
49 void InitializeMonitor(HLERequestContext& ctx) {
50 LOG_INFO(Service_LDN, "called");
51
52 state = State::Initialized;
53
54 IPC::ResponseBuilder rb{ctx, 2};
55 rb.Push(ResultSuccess);
56 }
57
58 State state{State::None};
39}; 59};
40 60
41class LDNM final : public ServiceFramework<LDNM> { 61class LDNM final : public ServiceFramework<LDNM> {
@@ -731,14 +751,81 @@ public:
731 } 751 }
732}; 752};
733 753
754class ISfMonitorService final : public ServiceFramework<ISfMonitorService> {
755public:
756 explicit ISfMonitorService(Core::System& system_)
757 : ServiceFramework{system_, "ISfMonitorService"} {
758 // clang-format off
759 static const FunctionInfo functions[] = {
760 {0, &ISfMonitorService::Initialize, "Initialize"},
761 {288, &ISfMonitorService::GetGroupInfo, "GetGroupInfo"},
762 {320, nullptr, "GetLinkLevel"},
763 };
764 // clang-format on
765
766 RegisterHandlers(functions);
767 }
768
769private:
770 void Initialize(HLERequestContext& ctx) {
771 LOG_WARNING(Service_LDN, "(STUBBED) called");
772
773 IPC::ResponseBuilder rb{ctx, 3};
774 rb.Push(ResultSuccess);
775 rb.Push(0);
776 }
777
778 void GetGroupInfo(HLERequestContext& ctx) {
779 LOG_WARNING(Service_LDN, "(STUBBED) called");
780
781 struct GroupInfo {
782 std::array<u8, 0x200> info;
783 };
784
785 GroupInfo group_info{};
786
787 ctx.WriteBuffer(group_info);
788 IPC::ResponseBuilder rb{ctx, 2};
789 rb.Push(ResultSuccess);
790 }
791};
792
793class LP2PM final : public ServiceFramework<LP2PM> {
794public:
795 explicit LP2PM(Core::System& system_) : ServiceFramework{system_, "lp2p:m"} {
796 // clang-format off
797 static const FunctionInfo functions[] = {
798 {0, &LP2PM::CreateMonitorService, "CreateMonitorService"},
799 };
800 // clang-format on
801
802 RegisterHandlers(functions);
803 }
804
805private:
806 void CreateMonitorService(HLERequestContext& ctx) {
807 IPC::RequestParser rp{ctx};
808 const u64 reserved_input = rp.Pop<u64>();
809
810 LOG_INFO(Service_LDN, "called, reserved_input={}", reserved_input);
811
812 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
813 rb.Push(ResultSuccess);
814 rb.PushIpcInterface<ISfMonitorService>(system);
815 }
816};
817
734void LoopProcess(Core::System& system) { 818void LoopProcess(Core::System& system) {
735 auto server_manager = std::make_unique<ServerManager>(system); 819 auto server_manager = std::make_unique<ServerManager>(system);
736 820
737 server_manager->RegisterNamedService("ldn:m", std::make_shared<LDNM>(system)); 821 server_manager->RegisterNamedService("ldn:m", std::make_shared<LDNM>(system));
738 server_manager->RegisterNamedService("ldn:s", std::make_shared<LDNS>(system)); 822 server_manager->RegisterNamedService("ldn:s", std::make_shared<LDNS>(system));
739 server_manager->RegisterNamedService("ldn:u", std::make_shared<LDNU>(system)); 823 server_manager->RegisterNamedService("ldn:u", std::make_shared<LDNU>(system));
824
740 server_manager->RegisterNamedService("lp2p:app", std::make_shared<LP2PAPP>(system)); 825 server_manager->RegisterNamedService("lp2p:app", std::make_shared<LP2PAPP>(system));
741 server_manager->RegisterNamedService("lp2p:sys", std::make_shared<LP2PSYS>(system)); 826 server_manager->RegisterNamedService("lp2p:sys", std::make_shared<LP2PSYS>(system));
827 server_manager->RegisterNamedService("lp2p:m", std::make_shared<LP2PM>(system));
828
742 ServerManager::RunServer(std::move(server_manager)); 829 ServerManager::RunServer(std::move(server_manager));
743} 830}
744 831
diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp
index 68c407f81..e7a00deb3 100644
--- a/src/core/hle/service/nfc/common/device.cpp
+++ b/src/core/hle/service/nfc/common/device.cpp
@@ -830,11 +830,6 @@ Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& registe
830 return ResultWrongDeviceState; 830 return ResultWrongDeviceState;
831 } 831 }
832 832
833 Service::Mii::StoreData store_data{};
834 Service::Mii::NfpStoreDataExtension extension{};
835 store_data.BuildBase(Mii::Gender::Male);
836 extension.SetFromStoreData(store_data);
837
838 auto& settings = tag_data.settings; 833 auto& settings = tag_data.settings;
839 834
840 if (tag_data.settings.settings.amiibo_initialized == 0) { 835 if (tag_data.settings.settings.amiibo_initialized == 0) {
@@ -843,8 +838,8 @@ Result NfcDevice::SetRegisterInfoPrivate(const NFP::RegisterInfoPrivate& registe
843 } 838 }
844 839
845 SetAmiiboName(settings, register_info.amiibo_name); 840 SetAmiiboName(settings, register_info.amiibo_name);
846 tag_data.owner_mii.BuildFromStoreData(store_data); 841 tag_data.owner_mii.BuildFromStoreData(register_info.mii_store_data);
847 tag_data.mii_extension = extension; 842 tag_data.mii_extension.SetFromStoreData(register_info.mii_store_data);
848 tag_data.unknown = 0; 843 tag_data.unknown = 0;
849 tag_data.unknown2 = {}; 844 tag_data.unknown2 = {};
850 settings.country_code_id = 0; 845 settings.country_code_id = 0;
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h
index 40c65b430..4c0cc71cd 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.h
+++ b/src/core/hle/service/nvdrv/devices/nvmap.h
@@ -45,13 +45,6 @@ public:
45 IsSharedMemMapped = 6 45 IsSharedMemMapped = 6
46 }; 46 };
47 47
48private:
49 /// Id to use for the next handle that is created.
50 u32 next_handle = 0;
51
52 /// Id to use for the next object that is created.
53 u32 next_id = 0;
54
55 struct IocCreateParams { 48 struct IocCreateParams {
56 // Input 49 // Input
57 u32_le size{}; 50 u32_le size{};
@@ -113,6 +106,13 @@ private:
113 NvResult IocParam(std::span<const u8> input, std::span<u8> output); 106 NvResult IocParam(std::span<const u8> input, std::span<u8> output);
114 NvResult IocFree(std::span<const u8> input, std::span<u8> output); 107 NvResult IocFree(std::span<const u8> input, std::span<u8> output);
115 108
109private:
110 /// Id to use for the next handle that is created.
111 u32 next_handle = 0;
112
113 /// Id to use for the next object that is created.
114 u32 next_id = 0;
115
116 NvCore::Container& container; 116 NvCore::Container& container;
117 NvCore::NvMap& file; 117 NvCore::NvMap& file;
118}; 118};
diff --git a/src/core/hle/service/nvnflinger/buffer_item.h b/src/core/hle/service/nvnflinger/buffer_item.h
index 7fd808f54..3da8cc3aa 100644
--- a/src/core/hle/service/nvnflinger/buffer_item.h
+++ b/src/core/hle/service/nvnflinger/buffer_item.h
@@ -15,7 +15,7 @@
15 15
16namespace Service::android { 16namespace Service::android {
17 17
18class GraphicBuffer; 18struct GraphicBuffer;
19 19
20class BufferItem final { 20class BufferItem final {
21public: 21public:
diff --git a/src/core/hle/service/nvnflinger/buffer_slot.h b/src/core/hle/service/nvnflinger/buffer_slot.h
index d25bca049..d8c9dec3b 100644
--- a/src/core/hle/service/nvnflinger/buffer_slot.h
+++ b/src/core/hle/service/nvnflinger/buffer_slot.h
@@ -13,7 +13,7 @@
13 13
14namespace Service::android { 14namespace Service::android {
15 15
16class GraphicBuffer; 16struct GraphicBuffer;
17 17
18enum class BufferState : u32 { 18enum class BufferState : u32 {
19 Free = 0, 19 Free = 0,
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
new file mode 100644
index 000000000..469a53244
--- /dev/null
+++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
@@ -0,0 +1,351 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <random>
5
6#include "core/core.h"
7#include "core/hle/kernel/k_process.h"
8#include "core/hle/kernel/k_system_resource.h"
9#include "core/hle/service/nvdrv/devices/nvmap.h"
10#include "core/hle/service/nvdrv/nvdrv.h"
11#include "core/hle/service/nvnflinger/buffer_queue_producer.h"
12#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
13#include "core/hle/service/nvnflinger/pixel_format.h"
14#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
15#include "core/hle/service/vi/layer/vi_layer.h"
16#include "core/hle/service/vi/vi_results.h"
17
18namespace Service::Nvnflinger {
19
20namespace {
21
22Result AllocateIoForProcessAddressSpace(Common::ProcessAddress* out_map_address,
23 std::unique_ptr<Kernel::KPageGroup>* out_page_group,
24 Core::System& system, u32 size) {
25 using Core::Memory::YUZU_PAGESIZE;
26
27 // Allocate memory for the system shared buffer.
28 // FIXME: Because the gmmu can only point to cpu addresses, we need
29 // to map this in the application space to allow it to be used.
30 // FIXME: Add proper smmu emulation.
31 // FIXME: This memory belongs to vi's .data section.
32 auto& kernel = system.Kernel();
33 auto* process = system.ApplicationProcess();
34 auto& page_table = process->GetPageTable();
35
36 // Hold a temporary page group reference while we try to map it.
37 auto pg = std::make_unique<Kernel::KPageGroup>(
38 kernel, std::addressof(kernel.GetSystemSystemResource().GetBlockInfoManager()));
39
40 // Allocate memory from secure pool.
41 R_TRY(kernel.MemoryManager().AllocateAndOpen(
42 pg.get(), size / YUZU_PAGESIZE,
43 Kernel::KMemoryManager::EncodeOption(Kernel::KMemoryManager::Pool::Secure,
44 Kernel::KMemoryManager::Direction::FromBack)));
45
46 // Get bounds of where mapping is possible.
47 const VAddr alias_code_begin = GetInteger(page_table.GetAliasCodeRegionStart());
48 const VAddr alias_code_size = page_table.GetAliasCodeRegionSize() / YUZU_PAGESIZE;
49 const auto state = Kernel::KMemoryState::Io;
50 const auto perm = Kernel::KMemoryPermission::UserReadWrite;
51 std::mt19937_64 rng{process->GetRandomEntropy(0)};
52
53 // Retry up to 64 times to map into alias code range.
54 Result res = ResultSuccess;
55 int i;
56 for (i = 0; i < 64; i++) {
57 *out_map_address = alias_code_begin + ((rng() % alias_code_size) * YUZU_PAGESIZE);
58 res = page_table.MapPageGroup(*out_map_address, *pg, state, perm);
59 if (R_SUCCEEDED(res)) {
60 break;
61 }
62 }
63
64 // Return failure, if necessary
65 R_UNLESS(i < 64, res);
66
67 // Return the mapped page group.
68 *out_page_group = std::move(pg);
69
70 // We succeeded.
71 R_SUCCEED();
72}
73
74template <typename T>
75std::span<u8> SerializeIoc(T& params) {
76 return std::span(reinterpret_cast<u8*>(std::addressof(params)), sizeof(T));
77}
78
79Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap, u32 size) {
80 // Create a handle.
81 Nvidia::Devices::nvmap::IocCreateParams create_in_params{
82 .size = size,
83 .handle = 0,
84 };
85 Nvidia::Devices::nvmap::IocCreateParams create_out_params{};
86 R_UNLESS(nvmap.IocCreate(SerializeIoc(create_in_params), SerializeIoc(create_out_params)) ==
87 Nvidia::NvResult::Success,
88 VI::ResultOperationFailed);
89
90 // Assign the output handle.
91 *out_nv_map_handle = create_out_params.handle;
92
93 // We succeeded.
94 R_SUCCEED();
95}
96
97Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle) {
98 // Free the handle.
99 Nvidia::Devices::nvmap::IocFreeParams free_in_params{
100 .handle = handle,
101 };
102 Nvidia::Devices::nvmap::IocFreeParams free_out_params{};
103 R_UNLESS(nvmap.IocFree(SerializeIoc(free_in_params), SerializeIoc(free_out_params)) ==
104 Nvidia::NvResult::Success,
105 VI::ResultOperationFailed);
106
107 // We succeeded.
108 R_SUCCEED();
109}
110
111Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::ProcessAddress buffer,
112 u32 size) {
113 // Assign the allocated memory to the handle.
114 Nvidia::Devices::nvmap::IocAllocParams alloc_in_params{
115 .handle = handle,
116 .heap_mask = 0,
117 .flags = {},
118 .align = 0,
119 .kind = 0,
120 .address = GetInteger(buffer),
121 };
122 Nvidia::Devices::nvmap::IocAllocParams alloc_out_params{};
123 R_UNLESS(nvmap.IocAlloc(SerializeIoc(alloc_in_params), SerializeIoc(alloc_out_params)) ==
124 Nvidia::NvResult::Success,
125 VI::ResultOperationFailed);
126
127 // We succeeded.
128 R_SUCCEED();
129}
130
131Result AllocateHandleForBuffer(u32* out_handle, Nvidia::Module& nvdrv,
132 Common::ProcessAddress buffer, u32 size) {
133 // Get the nvmap device.
134 auto nvmap_fd = nvdrv.Open("/dev/nvmap");
135 auto nvmap = nvdrv.GetDevice<Nvidia::Devices::nvmap>(nvmap_fd);
136 ASSERT(nvmap != nullptr);
137
138 // Create a handle.
139 R_TRY(CreateNvMapHandle(out_handle, *nvmap, size));
140
141 // Ensure we maintain a clean state on failure.
142 ON_RESULT_FAILURE {
143 ASSERT(R_SUCCEEDED(FreeNvMapHandle(*nvmap, *out_handle)));
144 };
145
146 // Assign the allocated memory to the handle.
147 R_RETURN(AllocNvMapHandle(*nvmap, *out_handle, buffer, size));
148}
149
150constexpr auto SharedBufferBlockLinearFormat = android::PixelFormat::Rgba8888;
151constexpr u32 SharedBufferBlockLinearBpp = 4;
152
153constexpr u32 SharedBufferBlockLinearWidth = 1280;
154constexpr u32 SharedBufferBlockLinearHeight = 768;
155constexpr u32 SharedBufferBlockLinearStride =
156 SharedBufferBlockLinearWidth * SharedBufferBlockLinearBpp;
157constexpr u32 SharedBufferNumSlots = 7;
158
159constexpr u32 SharedBufferWidth = 1280;
160constexpr u32 SharedBufferHeight = 720;
161constexpr u32 SharedBufferAsync = false;
162
163constexpr u32 SharedBufferSlotSize =
164 SharedBufferBlockLinearWidth * SharedBufferBlockLinearHeight * SharedBufferBlockLinearBpp;
165constexpr u32 SharedBufferSize = SharedBufferSlotSize * SharedBufferNumSlots;
166
167constexpr SharedMemoryPoolLayout SharedBufferPoolLayout = [] {
168 SharedMemoryPoolLayout layout{};
169 layout.num_slots = SharedBufferNumSlots;
170
171 for (u32 i = 0; i < SharedBufferNumSlots; i++) {
172 layout.slots[i].buffer_offset = i * SharedBufferSlotSize;
173 layout.slots[i].size = SharedBufferSlotSize;
174 layout.slots[i].width = SharedBufferWidth;
175 layout.slots[i].height = SharedBufferHeight;
176 }
177
178 return layout;
179}();
180
181void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) {
182 auto buffer = std::make_shared<android::GraphicBuffer>();
183 buffer->width = SharedBufferWidth;
184 buffer->height = SharedBufferHeight;
185 buffer->stride = SharedBufferBlockLinearStride;
186 buffer->format = SharedBufferBlockLinearFormat;
187 buffer->buffer_id = handle;
188 buffer->offset = slot * SharedBufferSlotSize;
189 ASSERT(producer.SetPreallocatedBuffer(slot, buffer) == android::Status::NoError);
190}
191
192} // namespace
193
194FbShareBufferManager::FbShareBufferManager(Core::System& system, Nvnflinger& flinger,
195 std::shared_ptr<Nvidia::Module> nvdrv)
196 : m_system(system), m_flinger(flinger), m_nvdrv(std::move(nvdrv)) {}
197
198FbShareBufferManager::~FbShareBufferManager() = default;
199
200Result FbShareBufferManager::Initialize(u64* out_buffer_id, u64* out_layer_id, u64 display_id) {
201 std::scoped_lock lk{m_guard};
202
203 // Ensure we have not already created a buffer.
204 R_UNLESS(m_buffer_id == 0, VI::ResultOperationFailed);
205
206 // Allocate memory and space for the shared buffer.
207 Common::ProcessAddress map_address;
208 R_TRY(AllocateIoForProcessAddressSpace(std::addressof(map_address),
209 std::addressof(m_buffer_page_group), m_system,
210 SharedBufferSize));
211
212 // Create an nvmap handle for the buffer and assign the memory to it.
213 R_TRY(AllocateHandleForBuffer(std::addressof(m_buffer_nvmap_handle), *m_nvdrv, map_address,
214 SharedBufferSize));
215
216 // Record the display id.
217 m_display_id = display_id;
218
219 // Create a layer for the display.
220 m_layer_id = m_flinger.CreateLayer(m_display_id).value();
221
222 // Set up the buffer.
223 m_buffer_id = m_next_buffer_id++;
224
225 // Get the layer.
226 VI::Layer* layer = m_flinger.FindLayer(m_display_id, m_layer_id);
227 ASSERT(layer != nullptr);
228
229 // Get the producer and set preallocated buffers.
230 auto& producer = layer->GetBufferQueue();
231 MakeGraphicBuffer(producer, 0, m_buffer_nvmap_handle);
232 MakeGraphicBuffer(producer, 1, m_buffer_nvmap_handle);
233
234 // Assign outputs.
235 *out_buffer_id = m_buffer_id;
236 *out_layer_id = m_layer_id;
237
238 // We succeeded.
239 R_SUCCEED();
240}
241
242Result FbShareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size,
243 s32* out_nvmap_handle,
244 SharedMemoryPoolLayout* out_pool_layout,
245 u64 buffer_id,
246 u64 applet_resource_user_id) {
247 std::scoped_lock lk{m_guard};
248
249 R_UNLESS(m_buffer_id > 0, VI::ResultNotFound);
250 R_UNLESS(buffer_id == m_buffer_id, VI::ResultNotFound);
251
252 *out_pool_layout = SharedBufferPoolLayout;
253 *out_buffer_size = SharedBufferSize;
254 *out_nvmap_handle = m_buffer_nvmap_handle;
255
256 R_SUCCEED();
257}
258
259Result FbShareBufferManager::GetLayerFromId(VI::Layer** out_layer, u64 layer_id) {
260 // Ensure the layer id is valid.
261 R_UNLESS(m_layer_id > 0 && layer_id == m_layer_id, VI::ResultNotFound);
262
263 // Get the layer.
264 VI::Layer* layer = m_flinger.FindLayer(m_display_id, layer_id);
265 R_UNLESS(layer != nullptr, VI::ResultNotFound);
266
267 // We succeeded.
268 *out_layer = layer;
269 R_SUCCEED();
270}
271
272Result FbShareBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence,
273 std::array<s32, 4>& out_slot_indexes,
274 s64* out_target_slot, u64 layer_id) {
275 std::scoped_lock lk{m_guard};
276
277 // Get the layer.
278 VI::Layer* layer;
279 R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id));
280
281 // Get the producer.
282 auto& producer = layer->GetBufferQueue();
283
284 // Get the next buffer from the producer.
285 s32 slot;
286 R_UNLESS(producer.DequeueBuffer(std::addressof(slot), out_fence, SharedBufferAsync != 0,
287 SharedBufferWidth, SharedBufferHeight,
288 SharedBufferBlockLinearFormat, 0) == android::Status::NoError,
289 VI::ResultOperationFailed);
290
291 // Assign remaining outputs.
292 *out_target_slot = slot;
293 out_slot_indexes = {0, 1, -1, -1};
294
295 // We succeeded.
296 R_SUCCEED();
297}
298
299Result FbShareBufferManager::PresentSharedFrameBuffer(android::Fence fence,
300 Common::Rectangle<s32> crop_region,
301 u32 transform, s32 swap_interval,
302 u64 layer_id, s64 slot) {
303 std::scoped_lock lk{m_guard};
304
305 // Get the layer.
306 VI::Layer* layer;
307 R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id));
308
309 // Get the producer.
310 auto& producer = layer->GetBufferQueue();
311
312 // Request to queue the buffer.
313 std::shared_ptr<android::GraphicBuffer> buffer;
314 R_UNLESS(producer.RequestBuffer(static_cast<s32>(slot), std::addressof(buffer)) ==
315 android::Status::NoError,
316 VI::ResultOperationFailed);
317
318 // Queue the buffer to the producer.
319 android::QueueBufferInput input{};
320 android::QueueBufferOutput output{};
321 input.crop = crop_region;
322 input.fence = fence;
323 input.transform = static_cast<android::NativeWindowTransform>(transform);
324 input.swap_interval = swap_interval;
325 R_UNLESS(producer.QueueBuffer(static_cast<s32>(slot), input, std::addressof(output)) ==
326 android::Status::NoError,
327 VI::ResultOperationFailed);
328
329 // We succeeded.
330 R_SUCCEED();
331}
332
333Result FbShareBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event,
334 u64 layer_id) {
335 std::scoped_lock lk{m_guard};
336
337 // Get the layer.
338 VI::Layer* layer;
339 R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id));
340
341 // Get the producer.
342 auto& producer = layer->GetBufferQueue();
343
344 // Set the event.
345 *out_event = std::addressof(producer.GetNativeHandle());
346
347 // We succeeded.
348 R_SUCCEED();
349}
350
351} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h
new file mode 100644
index 000000000..c809c01b4
--- /dev/null
+++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h
@@ -0,0 +1,65 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "common/math_util.h"
7#include "core/hle/service/nvnflinger/nvnflinger.h"
8#include "core/hle/service/nvnflinger/ui/fence.h"
9
10namespace Kernel {
11class KPageGroup;
12}
13
14namespace Service::Nvnflinger {
15
16struct SharedMemorySlot {
17 u64 buffer_offset;
18 u64 size;
19 s32 width;
20 s32 height;
21};
22static_assert(sizeof(SharedMemorySlot) == 0x18, "SharedMemorySlot has wrong size");
23
24struct SharedMemoryPoolLayout {
25 s32 num_slots;
26 std::array<SharedMemorySlot, 0x10> slots;
27};
28static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size");
29
30class FbShareBufferManager final {
31public:
32 explicit FbShareBufferManager(Core::System& system, Nvnflinger& flinger,
33 std::shared_ptr<Nvidia::Module> nvdrv);
34 ~FbShareBufferManager();
35
36 Result Initialize(u64* out_buffer_id, u64* out_layer_handle, u64 display_id);
37 Result GetSharedBufferMemoryHandleId(u64* out_buffer_size, s32* out_nvmap_handle,
38 SharedMemoryPoolLayout* out_pool_layout, u64 buffer_id,
39 u64 applet_resource_user_id);
40 Result AcquireSharedFrameBuffer(android::Fence* out_fence, std::array<s32, 4>& out_slots,
41 s64* out_target_slot, u64 layer_id);
42 Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region,
43 u32 transform, s32 swap_interval, u64 layer_id, s64 slot);
44 Result GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, u64 layer_id);
45
46private:
47 Result GetLayerFromId(VI::Layer** out_layer, u64 layer_id);
48
49private:
50 u64 m_next_buffer_id = 1;
51 u64 m_display_id = 0;
52 u64 m_buffer_id = 0;
53 u64 m_layer_id = 0;
54 u32 m_buffer_nvmap_handle = 0;
55 SharedMemoryPoolLayout m_pool_layout = {};
56
57 std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group;
58
59 std::mutex m_guard;
60 Core::System& m_system;
61 Nvnflinger& m_flinger;
62 std::shared_ptr<Nvidia::Module> m_nvdrv;
63};
64
65} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/graphic_buffer_producer.h b/src/core/hle/service/nvnflinger/graphic_buffer_producer.h
index 21d7b31f3..5d7cff7d3 100644
--- a/src/core/hle/service/nvnflinger/graphic_buffer_producer.h
+++ b/src/core/hle/service/nvnflinger/graphic_buffer_producer.h
@@ -19,6 +19,7 @@ class InputParcel;
19#pragma pack(push, 1) 19#pragma pack(push, 1)
20struct QueueBufferInput final { 20struct QueueBufferInput final {
21 explicit QueueBufferInput(InputParcel& parcel); 21 explicit QueueBufferInput(InputParcel& parcel);
22 explicit QueueBufferInput() = default;
22 23
23 void Deflate(s64* timestamp_, bool* is_auto_timestamp_, Common::Rectangle<s32>* crop_, 24 void Deflate(s64* timestamp_, bool* is_auto_timestamp_, Common::Rectangle<s32>* crop_,
24 NativeWindowScalingMode* scaling_mode_, NativeWindowTransform* transform_, 25 NativeWindowScalingMode* scaling_mode_, NativeWindowTransform* transform_,
@@ -34,7 +35,6 @@ struct QueueBufferInput final {
34 *fence_ = fence; 35 *fence_ = fence;
35 } 36 }
36 37
37private:
38 s64 timestamp{}; 38 s64 timestamp{};
39 s32 is_auto_timestamp{}; 39 s32 is_auto_timestamp{};
40 Common::Rectangle<s32> crop{}; 40 Common::Rectangle<s32> crop{};
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp
index 21f31f7a0..a07c621d9 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.cpp
+++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp
@@ -17,6 +17,7 @@
17#include "core/hle/service/nvdrv/nvdrv.h" 17#include "core/hle/service/nvdrv/nvdrv.h"
18#include "core/hle/service/nvnflinger/buffer_item_consumer.h" 18#include "core/hle/service/nvnflinger/buffer_item_consumer.h"
19#include "core/hle/service/nvnflinger/buffer_queue_core.h" 19#include "core/hle/service/nvnflinger/buffer_queue_core.h"
20#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
20#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" 21#include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
21#include "core/hle/service/nvnflinger/nvnflinger.h" 22#include "core/hle/service/nvnflinger/nvnflinger.h"
22#include "core/hle/service/nvnflinger/ui/graphic_buffer.h" 23#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
@@ -331,4 +332,14 @@ s64 Nvnflinger::GetNextTicks() const {
331 return static_cast<s64>(speed_scale * (1000000000.f / effective_fps)); 332 return static_cast<s64>(speed_scale * (1000000000.f / effective_fps));
332} 333}
333 334
335FbShareBufferManager& Nvnflinger::GetSystemBufferManager() {
336 const auto lock_guard = Lock();
337
338 if (!system_buffer_manager) {
339 system_buffer_manager = std::make_unique<FbShareBufferManager>(system, *this, nvdrv);
340 }
341
342 return *system_buffer_manager;
343}
344
334} // namespace Service::Nvnflinger 345} // namespace Service::Nvnflinger
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h
index f478c2bc6..14c783582 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.h
+++ b/src/core/hle/service/nvnflinger/nvnflinger.h
@@ -45,6 +45,9 @@ class BufferQueueProducer;
45 45
46namespace Service::Nvnflinger { 46namespace Service::Nvnflinger {
47 47
48class FbShareBufferManager;
49class HosBinderDriverServer;
50
48class Nvnflinger final { 51class Nvnflinger final {
49public: 52public:
50 explicit Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_); 53 explicit Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_);
@@ -90,12 +93,16 @@ public:
90 93
91 [[nodiscard]] s64 GetNextTicks() const; 94 [[nodiscard]] s64 GetNextTicks() const;
92 95
96 FbShareBufferManager& GetSystemBufferManager();
97
93private: 98private:
94 struct Layer { 99 struct Layer {
95 std::unique_ptr<android::BufferQueueCore> core; 100 std::unique_ptr<android::BufferQueueCore> core;
96 std::unique_ptr<android::BufferQueueProducer> producer; 101 std::unique_ptr<android::BufferQueueProducer> producer;
97 }; 102 };
98 103
104 friend class FbShareBufferManager;
105
99private: 106private:
100 [[nodiscard]] std::unique_lock<std::mutex> Lock() const { 107 [[nodiscard]] std::unique_lock<std::mutex> Lock() const {
101 return std::unique_lock{*guard}; 108 return std::unique_lock{*guard};
@@ -140,6 +147,8 @@ private:
140 std::shared_ptr<Core::Timing::EventType> multi_composition_event; 147 std::shared_ptr<Core::Timing::EventType> multi_composition_event;
141 std::shared_ptr<Core::Timing::EventType> single_composition_event; 148 std::shared_ptr<Core::Timing::EventType> single_composition_event;
142 149
150 std::unique_ptr<FbShareBufferManager> system_buffer_manager;
151
143 std::shared_ptr<std::mutex> guard; 152 std::shared_ptr<std::mutex> guard;
144 153
145 Core::System& system; 154 Core::System& system;
diff --git a/src/core/hle/service/nvnflinger/ui/fence.h b/src/core/hle/service/nvnflinger/ui/fence.h
index 536e8156d..177aed758 100644
--- a/src/core/hle/service/nvnflinger/ui/fence.h
+++ b/src/core/hle/service/nvnflinger/ui/fence.h
@@ -20,6 +20,9 @@ public:
20 static constexpr Fence NoFence() { 20 static constexpr Fence NoFence() {
21 Fence fence; 21 Fence fence;
22 fence.fences[0].id = -1; 22 fence.fences[0].id = -1;
23 fence.fences[1].id = -1;
24 fence.fences[2].id = -1;
25 fence.fences[3].id = -1;
23 return fence; 26 return fence;
24 } 27 }
25 28
diff --git a/src/core/hle/service/nvnflinger/ui/graphic_buffer.h b/src/core/hle/service/nvnflinger/ui/graphic_buffer.h
index 75d1705a8..3eac5cedd 100644
--- a/src/core/hle/service/nvnflinger/ui/graphic_buffer.h
+++ b/src/core/hle/service/nvnflinger/ui/graphic_buffer.h
@@ -12,8 +12,7 @@
12 12
13namespace Service::android { 13namespace Service::android {
14 14
15class GraphicBuffer final { 15struct GraphicBuffer final {
16public:
17 constexpr GraphicBuffer() = default; 16 constexpr GraphicBuffer() = default;
18 17
19 constexpr GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_) 18 constexpr GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_)
@@ -77,7 +76,6 @@ public:
77 return false; 76 return false;
78 } 77 }
79 78
80private:
81 u32 magic{}; 79 u32 magic{};
82 s32 width{}; 80 s32 width{};
83 s32 height{}; 81 s32 height{};
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 2eb978379..b1bfb9898 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -20,9 +20,12 @@
20#include "core/hle/kernel/k_readable_event.h" 20#include "core/hle/kernel/k_readable_event.h"
21#include "core/hle/kernel/k_thread.h" 21#include "core/hle/kernel/k_thread.h"
22#include "core/hle/service/ipc_helpers.h" 22#include "core/hle/service/ipc_helpers.h"
23#include "core/hle/service/nvdrv/devices/nvmap.h"
23#include "core/hle/service/nvdrv/nvdata.h" 24#include "core/hle/service/nvdrv/nvdata.h"
25#include "core/hle/service/nvdrv/nvdrv.h"
24#include "core/hle/service/nvnflinger/binder.h" 26#include "core/hle/service/nvnflinger/binder.h"
25#include "core/hle/service/nvnflinger/buffer_queue_producer.h" 27#include "core/hle/service/nvnflinger/buffer_queue_producer.h"
28#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
26#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" 29#include "core/hle/service/nvnflinger/hos_binder_driver_server.h"
27#include "core/hle/service/nvnflinger/nvnflinger.h" 30#include "core/hle/service/nvnflinger/nvnflinger.h"
28#include "core/hle/service/nvnflinger/parcel.h" 31#include "core/hle/service/nvnflinger/parcel.h"
@@ -131,8 +134,9 @@ private:
131 134
132class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { 135class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> {
133public: 136public:
134 explicit ISystemDisplayService(Core::System& system_) 137 explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_)
135 : ServiceFramework{system_, "ISystemDisplayService"} { 138 : ServiceFramework{system_, "ISystemDisplayService"}, nvnflinger{nvnflinger_} {
139 // clang-format off
136 static const FunctionInfo functions[] = { 140 static const FunctionInfo functions[] = {
137 {1200, nullptr, "GetZOrderCountMin"}, 141 {1200, nullptr, "GetZOrderCountMin"},
138 {1202, nullptr, "GetZOrderCountMax"}, 142 {1202, nullptr, "GetZOrderCountMax"},
@@ -170,22 +174,126 @@ public:
170 {3217, nullptr, "SetDisplayCmuLuma"}, 174 {3217, nullptr, "SetDisplayCmuLuma"},
171 {3218, nullptr, "SetDisplayCrcMode"}, 175 {3218, nullptr, "SetDisplayCrcMode"},
172 {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"}, 176 {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"},
173 {8225, nullptr, "GetSharedBufferMemoryHandleId"}, 177 {8225, &ISystemDisplayService::GetSharedBufferMemoryHandleId, "GetSharedBufferMemoryHandleId"},
174 {8250, nullptr, "OpenSharedLayer"}, 178 {8250, &ISystemDisplayService::OpenSharedLayer, "OpenSharedLayer"},
175 {8251, nullptr, "CloseSharedLayer"}, 179 {8251, nullptr, "CloseSharedLayer"},
176 {8252, nullptr, "ConnectSharedLayer"}, 180 {8252, &ISystemDisplayService::ConnectSharedLayer, "ConnectSharedLayer"},
177 {8253, nullptr, "DisconnectSharedLayer"}, 181 {8253, nullptr, "DisconnectSharedLayer"},
178 {8254, nullptr, "AcquireSharedFrameBuffer"}, 182 {8254, &ISystemDisplayService::AcquireSharedFrameBuffer, "AcquireSharedFrameBuffer"},
179 {8255, nullptr, "PresentSharedFrameBuffer"}, 183 {8255, &ISystemDisplayService::PresentSharedFrameBuffer, "PresentSharedFrameBuffer"},
180 {8256, nullptr, "GetSharedFrameBufferAcquirableEvent"}, 184 {8256, &ISystemDisplayService::GetSharedFrameBufferAcquirableEvent, "GetSharedFrameBufferAcquirableEvent"},
181 {8257, nullptr, "FillSharedFrameBufferColor"}, 185 {8257, nullptr, "FillSharedFrameBufferColor"},
182 {8258, nullptr, "CancelSharedFrameBuffer"}, 186 {8258, nullptr, "CancelSharedFrameBuffer"},
183 {9000, nullptr, "GetDp2hdmiController"}, 187 {9000, nullptr, "GetDp2hdmiController"},
184 }; 188 };
189 // clang-format on
185 RegisterHandlers(functions); 190 RegisterHandlers(functions);
186 } 191 }
187 192
188private: 193private:
194 void GetSharedBufferMemoryHandleId(HLERequestContext& ctx) {
195 IPC::RequestParser rp{ctx};
196 const u64 buffer_id = rp.PopRaw<u64>();
197
198 LOG_INFO(Service_VI, "called. buffer_id={:#x}", buffer_id);
199
200 struct OutputParameters {
201 s32 nvmap_handle;
202 u64 size;
203 };
204
205 OutputParameters out{};
206 Nvnflinger::SharedMemoryPoolLayout layout{};
207 const auto result = nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId(
208 &out.size, &out.nvmap_handle, &layout, buffer_id, 0);
209
210 ctx.WriteBuffer(&layout, sizeof(layout));
211
212 IPC::ResponseBuilder rb{ctx, 6};
213 rb.Push(result);
214 rb.PushRaw(out);
215 }
216
217 void OpenSharedLayer(HLERequestContext& ctx) {
218 IPC::RequestParser rp{ctx};
219 const u64 layer_id = rp.PopRaw<u64>();
220
221 LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id);
222
223 IPC::ResponseBuilder rb{ctx, 2};
224 rb.Push(ResultSuccess);
225 }
226
227 void ConnectSharedLayer(HLERequestContext& ctx) {
228 IPC::RequestParser rp{ctx};
229 const u64 layer_id = rp.PopRaw<u64>();
230
231 LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id);
232
233 IPC::ResponseBuilder rb{ctx, 2};
234 rb.Push(ResultSuccess);
235 }
236
237 void GetSharedFrameBufferAcquirableEvent(HLERequestContext& ctx) {
238 LOG_DEBUG(Service_VI, "called");
239
240 IPC::RequestParser rp{ctx};
241 const u64 layer_id = rp.PopRaw<u64>();
242
243 Kernel::KReadableEvent* event{};
244 const auto result = nvnflinger.GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent(
245 &event, layer_id);
246
247 IPC::ResponseBuilder rb{ctx, 2, 1};
248 rb.Push(result);
249 rb.PushCopyObjects(event);
250 }
251
252 void AcquireSharedFrameBuffer(HLERequestContext& ctx) {
253 LOG_DEBUG(Service_VI, "called");
254
255 IPC::RequestParser rp{ctx};
256 const u64 layer_id = rp.PopRaw<u64>();
257
258 struct OutputParameters {
259 android::Fence fence;
260 std::array<s32, 4> slots;
261 s64 target_slot;
262 };
263 static_assert(sizeof(OutputParameters) == 0x40, "OutputParameters has wrong size");
264
265 OutputParameters out{};
266 const auto result = nvnflinger.GetSystemBufferManager().AcquireSharedFrameBuffer(
267 &out.fence, out.slots, &out.target_slot, layer_id);
268
269 IPC::ResponseBuilder rb{ctx, 18};
270 rb.Push(result);
271 rb.PushRaw(out);
272 }
273
274 void PresentSharedFrameBuffer(HLERequestContext& ctx) {
275 LOG_DEBUG(Service_VI, "called");
276
277 struct InputParameters {
278 android::Fence fence;
279 Common::Rectangle<s32> crop_region;
280 u32 window_transform;
281 s32 swap_interval;
282 u64 layer_id;
283 s64 surface_id;
284 };
285 static_assert(sizeof(InputParameters) == 0x50, "InputParameters has wrong size");
286
287 IPC::RequestParser rp{ctx};
288 auto input = rp.PopRaw<InputParameters>();
289
290 const auto result = nvnflinger.GetSystemBufferManager().PresentSharedFrameBuffer(
291 input.fence, input.crop_region, input.window_transform, input.swap_interval,
292 input.layer_id, input.surface_id);
293 IPC::ResponseBuilder rb{ctx, 2};
294 rb.Push(result);
295 }
296
189 void SetLayerZ(HLERequestContext& ctx) { 297 void SetLayerZ(HLERequestContext& ctx) {
190 IPC::RequestParser rp{ctx}; 298 IPC::RequestParser rp{ctx};
191 const u64 layer_id = rp.Pop<u64>(); 299 const u64 layer_id = rp.Pop<u64>();
@@ -228,6 +336,9 @@ private:
228 rb.PushRaw<float>(60.0f); // This wouldn't seem to be correct for 30 fps games. 336 rb.PushRaw<float>(60.0f); // This wouldn't seem to be correct for 30 fps games.
229 rb.Push<u32>(0); 337 rb.Push<u32>(0);
230 } 338 }
339
340private:
341 Nvnflinger::Nvnflinger& nvnflinger;
231}; 342};
232 343
233class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { 344class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> {
@@ -453,7 +564,7 @@ private:
453 564
454 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 565 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
455 rb.Push(ResultSuccess); 566 rb.Push(ResultSuccess);
456 rb.PushIpcInterface<ISystemDisplayService>(system); 567 rb.PushIpcInterface<ISystemDisplayService>(system, nv_flinger);
457 } 568 }
458 569
459 void GetManagerDisplayService(HLERequestContext& ctx) { 570 void GetManagerDisplayService(HLERequestContext& ctx) {
diff --git a/src/input_common/drivers/virtual_gamepad.h b/src/input_common/drivers/virtual_gamepad.h
index dfbc45a28..3a40e3fd3 100644
--- a/src/input_common/drivers/virtual_gamepad.h
+++ b/src/input_common/drivers/virtual_gamepad.h
@@ -67,7 +67,7 @@ public:
67 * @param player_index the player number that will take this action 67 * @param player_index the player number that will take this action
68 * @param delta_timestamp time passed since last reading 68 * @param delta_timestamp time passed since last reading
69 * @param gyro_x,gyro_y,gyro_z the gyro sensor readings 69 * @param gyro_x,gyro_y,gyro_z the gyro sensor readings
70 * @param accel_x,accel_y,accel_z the acelerometer reading 70 * @param accel_x,accel_y,accel_z the accelerometer reading
71 */ 71 */
72 void SetMotionState(std::size_t player_index, u64 delta_timestamp, float gyro_x, float gyro_y, 72 void SetMotionState(std::size_t player_index, u64 delta_timestamp, float gyro_x, float gyro_y,
73 float gyro_z, float accel_x, float accel_y, float accel_z); 73 float gyro_z, float accel_x, float accel_y, float accel_z);
diff --git a/src/input_common/helpers/joycon_protocol/generic_functions.h b/src/input_common/helpers/joycon_protocol/generic_functions.h
index 90fcd17f6..b94567f82 100644
--- a/src/input_common/helpers/joycon_protocol/generic_functions.h
+++ b/src/input_common/helpers/joycon_protocol/generic_functions.h
@@ -55,7 +55,7 @@ public:
55 55
56 /** 56 /**
57 * Configures the motion sensor with the specified parameters 57 * Configures the motion sensor with the specified parameters
58 * @param gsen gyroscope sensor sensitvity in degrees per second 58 * @param gsen gyroscope sensor sensitivity in degrees per second
59 * @param gfrec gyroscope sensor frequency in hertz 59 * @param gfrec gyroscope sensor frequency in hertz
60 * @param asen accelerometer sensitivity in G force 60 * @param asen accelerometer sensitivity in G force
61 * @param afrec accelerometer frequency in hertz 61 * @param afrec accelerometer frequency in hertz
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp
index d508ee567..4e8ba4ae6 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_composite.cpp
@@ -55,7 +55,7 @@ void CompositeInsert(EmitContext& ctx, IR::Inst& inst, Register composite, Objec
55 "MOV.{} {}.{},{};", 55 "MOV.{} {}.{},{};",
56 type, ret, composite, type, ret, swizzle, object); 56 type, ret, composite, type, ret, swizzle, object);
57 } else { 57 } else {
58 // The return value is alised so we can just insert the object, it doesn't matter if it's 58 // The return value is aliased so we can just insert the object, it doesn't matter if it's
59 // aliased 59 // aliased
60 ctx.Add("MOV.{} {}.{},{};", type, ret, swizzle, object); 60 ctx.Add("MOV.{} {}.{},{};", type, ret, swizzle, object);
61 } 61 }
diff --git a/src/video_core/dma_pusher.h b/src/video_core/dma_pusher.h
index c9fab2d90..e46a8fa5c 100644
--- a/src/video_core/dma_pusher.h
+++ b/src/video_core/dma_pusher.h
@@ -161,7 +161,7 @@ private:
161 u32 method_count; ///< Current method count 161 u32 method_count; ///< Current method count
162 u32 length_pending; ///< Large NI command length pending 162 u32 length_pending; ///< Large NI command length pending
163 GPUVAddr dma_get; ///< Currently read segment 163 GPUVAddr dma_get; ///< Currently read segment
164 u64 dma_word_offset; ///< Current word ofset from address 164 u64 dma_word_offset; ///< Current word offset from address
165 bool non_incrementing; ///< Current command's NI flag 165 bool non_incrementing; ///< Current command's NI flag
166 bool is_last_call; 166 bool is_last_call;
167 }; 167 };
diff --git a/src/video_core/query_cache/bank_base.h b/src/video_core/query_cache/bank_base.h
index 420927091..44769ea97 100644
--- a/src/video_core/query_cache/bank_base.h
+++ b/src/video_core/query_cache/bank_base.h
@@ -82,6 +82,7 @@ public:
82 size_t new_index = bank_indices.front(); 82 size_t new_index = bank_indices.front();
83 bank_indices.pop_front(); 83 bank_indices.pop_front();
84 bank_pool[new_index].Reset(); 84 bank_pool[new_index].Reset();
85 bank_indices.push_back(new_index);
85 return new_index; 86 return new_index;
86 } 87 }
87 size_t new_index = bank_pool.size(); 88 size_t new_index = bank_pool.size();
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h
index c7dc7e0a1..5ea9e2378 100644
--- a/src/video_core/renderer_opengl/maxwell_to_gl.h
+++ b/src/video_core/renderer_opengl/maxwell_to_gl.h
@@ -116,6 +116,7 @@ constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> FORMAT_TAB
116 {GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, // E5B9G9R9_FLOAT 116 {GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, // E5B9G9R9_FLOAT
117 {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT}, // D32_FLOAT 117 {GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT}, // D32_FLOAT
118 {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, // D16_UNORM 118 {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, // D16_UNORM
119 {GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8}, // X8_D24_UNORM
119 {GL_STENCIL_INDEX8, GL_STENCIL, GL_UNSIGNED_BYTE}, // S8_UINT 120 {GL_STENCIL_INDEX8, GL_STENCIL, GL_UNSIGNED_BYTE}, // S8_UINT
120 {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // D24_UNORM_S8_UINT 121 {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // D24_UNORM_S8_UINT
121 {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // S8_UINT_D24_UNORM 122 {GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // S8_UINT_D24_UNORM
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
index 208e88533..a08f2f67f 100644
--- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
+++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp
@@ -214,8 +214,9 @@ struct FormatTuple {
214 {VK_FORMAT_E5B9G9R9_UFLOAT_PACK32}, // E5B9G9R9_FLOAT 214 {VK_FORMAT_E5B9G9R9_UFLOAT_PACK32}, // E5B9G9R9_FLOAT
215 215
216 // Depth formats 216 // Depth formats
217 {VK_FORMAT_D32_SFLOAT, Attachable}, // D32_FLOAT 217 {VK_FORMAT_D32_SFLOAT, Attachable}, // D32_FLOAT
218 {VK_FORMAT_D16_UNORM, Attachable}, // D16_UNORM 218 {VK_FORMAT_D16_UNORM, Attachable}, // D16_UNORM
219 {VK_FORMAT_X8_D24_UNORM_PACK32, Attachable}, // X8_D24_UNORM
219 220
220 // Stencil formats 221 // Stencil formats
221 {VK_FORMAT_S8_UINT, Attachable}, // S8_UINT 222 {VK_FORMAT_S8_UINT, Attachable}, // S8_UINT
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index 31928bb94..52fc142d1 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -96,6 +96,7 @@ std::size_t GetSizeInBytes(const Tegra::FramebufferConfig& framebuffer) {
96VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) { 96VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) {
97 switch (framebuffer.pixel_format) { 97 switch (framebuffer.pixel_format) {
98 case Service::android::PixelFormat::Rgba8888: 98 case Service::android::PixelFormat::Rgba8888:
99 case Service::android::PixelFormat::Rgbx8888:
99 return VK_FORMAT_A8B8G8R8_UNORM_PACK32; 100 return VK_FORMAT_A8B8G8R8_UNORM_PACK32;
100 case Service::android::PixelFormat::Rgb565: 101 case Service::android::PixelFormat::Rgb565:
101 return VK_FORMAT_R5G6B5_UNORM_PACK16; 102 return VK_FORMAT_R5G6B5_UNORM_PACK16;
diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp
index 17b2587ad..2edaafa7e 100644
--- a/src/video_core/renderer_vulkan/vk_query_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp
@@ -506,6 +506,7 @@ private:
506 SetAccumulationValue(query->value); 506 SetAccumulationValue(query->value);
507 Free(index); 507 Free(index);
508 }); 508 });
509 rasterizer->SyncOperation(std::move(func));
509 } 510 }
510 511
511 template <bool is_resolve> 512 template <bool is_resolve>
diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
index ce92f66ab..b278614e6 100644
--- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
+++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
@@ -24,25 +24,38 @@ using namespace Common::Literals;
24 24
25// Maximum potential alignment of a Vulkan buffer 25// Maximum potential alignment of a Vulkan buffer
26constexpr VkDeviceSize MAX_ALIGNMENT = 256; 26constexpr VkDeviceSize MAX_ALIGNMENT = 256;
27// Maximum size to put elements in the stream buffer
28constexpr VkDeviceSize MAX_STREAM_BUFFER_REQUEST_SIZE = 8_MiB;
29// Stream buffer size in bytes 27// Stream buffer size in bytes
30constexpr VkDeviceSize STREAM_BUFFER_SIZE = 128_MiB; 28constexpr VkDeviceSize MAX_STREAM_BUFFER_SIZE = 128_MiB;
31constexpr VkDeviceSize REGION_SIZE = STREAM_BUFFER_SIZE / StagingBufferPool::NUM_SYNCS;
32 29
33size_t Region(size_t iterator) noexcept { 30size_t GetStreamBufferSize(const Device& device) {
34 return iterator / REGION_SIZE; 31 VkDeviceSize size{0};
32 if (device.HasDebuggingToolAttached()) {
33 ForEachDeviceLocalHostVisibleHeap(device, [&size](size_t index, VkMemoryHeap& heap) {
34 size = std::max(size, heap.size);
35 });
36 // If rebar is not supported, cut the max heap size to 40%. This will allow 2 captures to be
37 // loaded at the same time in RenderDoc. If rebar is supported, this shouldn't be an issue
38 // as the heap will be much larger.
39 if (size <= 256_MiB) {
40 size = size * 40 / 100;
41 }
42 } else {
43 size = MAX_STREAM_BUFFER_SIZE;
44 }
45 return std::min(Common::AlignUp(size, MAX_ALIGNMENT), MAX_STREAM_BUFFER_SIZE);
35} 46}
36} // Anonymous namespace 47} // Anonymous namespace
37 48
38StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& memory_allocator_, 49StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& memory_allocator_,
39 Scheduler& scheduler_) 50 Scheduler& scheduler_)
40 : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_} { 51 : device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_},
52 stream_buffer_size{GetStreamBufferSize(device)}, region_size{stream_buffer_size /
53 StagingBufferPool::NUM_SYNCS} {
41 VkBufferCreateInfo stream_ci = { 54 VkBufferCreateInfo stream_ci = {
42 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 55 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
43 .pNext = nullptr, 56 .pNext = nullptr,
44 .flags = 0, 57 .flags = 0,
45 .size = STREAM_BUFFER_SIZE, 58 .size = stream_buffer_size,
46 .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | 59 .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT |
47 VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, 60 VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
48 .sharingMode = VK_SHARING_MODE_EXCLUSIVE, 61 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
@@ -63,7 +76,7 @@ StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& mem
63StagingBufferPool::~StagingBufferPool() = default; 76StagingBufferPool::~StagingBufferPool() = default;
64 77
65StagingBufferRef StagingBufferPool::Request(size_t size, MemoryUsage usage, bool deferred) { 78StagingBufferRef StagingBufferPool::Request(size_t size, MemoryUsage usage, bool deferred) {
66 if (!deferred && usage == MemoryUsage::Upload && size <= MAX_STREAM_BUFFER_REQUEST_SIZE) { 79 if (!deferred && usage == MemoryUsage::Upload && size <= region_size) {
67 return GetStreamBuffer(size); 80 return GetStreamBuffer(size);
68 } 81 }
69 return GetStagingBuffer(size, usage, deferred); 82 return GetStagingBuffer(size, usage, deferred);
@@ -101,7 +114,7 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) {
101 used_iterator = iterator; 114 used_iterator = iterator;
102 free_iterator = std::max(free_iterator, iterator + size); 115 free_iterator = std::max(free_iterator, iterator + size);
103 116
104 if (iterator + size >= STREAM_BUFFER_SIZE) { 117 if (iterator + size >= stream_buffer_size) {
105 std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + NUM_SYNCS, 118 std::fill(sync_ticks.begin() + Region(used_iterator), sync_ticks.begin() + NUM_SYNCS,
106 current_tick); 119 current_tick);
107 used_iterator = 0; 120 used_iterator = 0;
diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
index 5f69f08b1..d3deb9072 100644
--- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
+++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
@@ -90,6 +90,9 @@ private:
90 void ReleaseCache(MemoryUsage usage); 90 void ReleaseCache(MemoryUsage usage);
91 91
92 void ReleaseLevel(StagingBuffersCache& cache, size_t log2); 92 void ReleaseLevel(StagingBuffersCache& cache, size_t log2);
93 size_t Region(size_t iter) const noexcept {
94 return iter / region_size;
95 }
93 96
94 const Device& device; 97 const Device& device;
95 MemoryAllocator& memory_allocator; 98 MemoryAllocator& memory_allocator;
@@ -97,6 +100,8 @@ private:
97 100
98 vk::Buffer stream_buffer; 101 vk::Buffer stream_buffer;
99 std::span<u8> stream_pointer; 102 std::span<u8> stream_pointer;
103 VkDeviceSize stream_buffer_size;
104 VkDeviceSize region_size;
100 105
101 size_t iterator = 0; 106 size_t iterator = 0;
102 size_t used_iterator = 0; 107 size_t used_iterator = 0;
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 71fdec809..e266c1dbe 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -238,6 +238,7 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
238 return any_r ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT; 238 return any_r ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT;
239 case PixelFormat::D16_UNORM: 239 case PixelFormat::D16_UNORM:
240 case PixelFormat::D32_FLOAT: 240 case PixelFormat::D32_FLOAT:
241 case PixelFormat::X8_D24_UNORM:
241 return VK_IMAGE_ASPECT_DEPTH_BIT; 242 return VK_IMAGE_ASPECT_DEPTH_BIT;
242 case PixelFormat::S8_UINT: 243 case PixelFormat::S8_UINT:
243 return VK_IMAGE_ASPECT_STENCIL_BIT; 244 return VK_IMAGE_ASPECT_STENCIL_BIT;
diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp
index e16cd5e73..5b3c7aa5a 100644
--- a/src/video_core/surface.cpp
+++ b/src/video_core/surface.cpp
@@ -85,6 +85,8 @@ PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) {
85 return PixelFormat::S8_UINT; 85 return PixelFormat::S8_UINT;
86 case Tegra::DepthFormat::Z32_FLOAT_X24S8_UINT: 86 case Tegra::DepthFormat::Z32_FLOAT_X24S8_UINT:
87 return PixelFormat::D32_FLOAT_S8_UINT; 87 return PixelFormat::D32_FLOAT_S8_UINT;
88 case Tegra::DepthFormat::X8Z24_UNORM:
89 return PixelFormat::X8_D24_UNORM;
88 default: 90 default:
89 UNIMPLEMENTED_MSG("Unimplemented format={}", format); 91 UNIMPLEMENTED_MSG("Unimplemented format={}", format);
90 return PixelFormat::S8_UINT_D24_UNORM; 92 return PixelFormat::S8_UINT_D24_UNORM;
@@ -202,6 +204,7 @@ PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format)
202PixelFormat PixelFormatFromGPUPixelFormat(Service::android::PixelFormat format) { 204PixelFormat PixelFormatFromGPUPixelFormat(Service::android::PixelFormat format) {
203 switch (format) { 205 switch (format) {
204 case Service::android::PixelFormat::Rgba8888: 206 case Service::android::PixelFormat::Rgba8888:
207 case Service::android::PixelFormat::Rgbx8888:
205 return PixelFormat::A8B8G8R8_UNORM; 208 return PixelFormat::A8B8G8R8_UNORM;
206 case Service::android::PixelFormat::Rgb565: 209 case Service::android::PixelFormat::Rgb565:
207 return PixelFormat::R5G6B5_UNORM; 210 return PixelFormat::R5G6B5_UNORM;
diff --git a/src/video_core/surface.h b/src/video_core/surface.h
index 9b9c4d9bc..a5e8e2f62 100644
--- a/src/video_core/surface.h
+++ b/src/video_core/surface.h
@@ -115,6 +115,7 @@ enum class PixelFormat {
115 // Depth formats 115 // Depth formats
116 D32_FLOAT = MaxColorFormat, 116 D32_FLOAT = MaxColorFormat,
117 D16_UNORM, 117 D16_UNORM,
118 X8_D24_UNORM,
118 119
119 MaxDepthFormat, 120 MaxDepthFormat,
120 121
@@ -251,6 +252,7 @@ constexpr std::array<u8, MaxPixelFormat> BLOCK_WIDTH_TABLE = {{
251 1, // E5B9G9R9_FLOAT 252 1, // E5B9G9R9_FLOAT
252 1, // D32_FLOAT 253 1, // D32_FLOAT
253 1, // D16_UNORM 254 1, // D16_UNORM
255 1, // X8_D24_UNORM
254 1, // S8_UINT 256 1, // S8_UINT
255 1, // D24_UNORM_S8_UINT 257 1, // D24_UNORM_S8_UINT
256 1, // S8_UINT_D24_UNORM 258 1, // S8_UINT_D24_UNORM
@@ -360,6 +362,7 @@ constexpr std::array<u8, MaxPixelFormat> BLOCK_HEIGHT_TABLE = {{
360 1, // E5B9G9R9_FLOAT 362 1, // E5B9G9R9_FLOAT
361 1, // D32_FLOAT 363 1, // D32_FLOAT
362 1, // D16_UNORM 364 1, // D16_UNORM
365 1, // X8_D24_UNORM
363 1, // S8_UINT 366 1, // S8_UINT
364 1, // D24_UNORM_S8_UINT 367 1, // D24_UNORM_S8_UINT
365 1, // S8_UINT_D24_UNORM 368 1, // S8_UINT_D24_UNORM
@@ -469,6 +472,7 @@ constexpr std::array<u8, MaxPixelFormat> BITS_PER_BLOCK_TABLE = {{
469 32, // E5B9G9R9_FLOAT 472 32, // E5B9G9R9_FLOAT
470 32, // D32_FLOAT 473 32, // D32_FLOAT
471 16, // D16_UNORM 474 16, // D16_UNORM
475 32, // X8_D24_UNORM
472 8, // S8_UINT 476 8, // S8_UINT
473 32, // D24_UNORM_S8_UINT 477 32, // D24_UNORM_S8_UINT
474 32, // S8_UINT_D24_UNORM 478 32, // S8_UINT_D24_UNORM
diff --git a/src/video_core/texture_cache/format_lookup_table.cpp b/src/video_core/texture_cache/format_lookup_table.cpp
index 56307d030..3162c8f5e 100644
--- a/src/video_core/texture_cache/format_lookup_table.cpp
+++ b/src/video_core/texture_cache/format_lookup_table.cpp
@@ -142,6 +142,10 @@ PixelFormat PixelFormatFromTextureInfo(TextureFormat format, ComponentType red,
142 return PixelFormat::D16_UNORM; 142 return PixelFormat::D16_UNORM;
143 case Hash(TextureFormat::Z16, UNORM, UINT, UINT, UINT, LINEAR): 143 case Hash(TextureFormat::Z16, UNORM, UINT, UINT, UINT, LINEAR):
144 return PixelFormat::D16_UNORM; 144 return PixelFormat::D16_UNORM;
145 case Hash(TextureFormat::X8Z24, UNORM):
146 return PixelFormat::X8_D24_UNORM;
147 case Hash(TextureFormat::X8Z24, UNORM, UINT, UINT, UINT, LINEAR):
148 return PixelFormat::X8_D24_UNORM;
145 case Hash(TextureFormat::Z24S8, UINT, UNORM, UNORM, UNORM, LINEAR): 149 case Hash(TextureFormat::Z24S8, UINT, UNORM, UNORM, UNORM, LINEAR):
146 return PixelFormat::S8_UINT_D24_UNORM; 150 return PixelFormat::S8_UINT_D24_UNORM;
147 case Hash(TextureFormat::Z24S8, UINT, UNORM, UINT, UINT, LINEAR): 151 case Hash(TextureFormat::Z24S8, UINT, UNORM, UINT, UINT, LINEAR):
diff --git a/src/video_core/texture_cache/formatter.h b/src/video_core/texture_cache/formatter.h
index 9ee57a076..cabbfcb2d 100644
--- a/src/video_core/texture_cache/formatter.h
+++ b/src/video_core/texture_cache/formatter.h
@@ -211,6 +211,8 @@ struct fmt::formatter<VideoCore::Surface::PixelFormat> : fmt::formatter<fmt::str
211 return "D32_FLOAT"; 211 return "D32_FLOAT";
212 case PixelFormat::D16_UNORM: 212 case PixelFormat::D16_UNORM:
213 return "D16_UNORM"; 213 return "D16_UNORM";
214 case PixelFormat::X8_D24_UNORM:
215 return "X8_D24_UNORM";
214 case PixelFormat::S8_UINT: 216 case PixelFormat::S8_UINT:
215 return "S8_UINT"; 217 return "S8_UINT";
216 case PixelFormat::D24_UNORM_S8_UINT: 218 case PixelFormat::D24_UNORM_S8_UINT:
diff --git a/src/video_core/texture_cache/image_base.h b/src/video_core/texture_cache/image_base.h
index 55d49d017..0587d7b72 100644
--- a/src/video_core/texture_cache/image_base.h
+++ b/src/video_core/texture_cache/image_base.h
@@ -41,7 +41,7 @@ enum class ImageFlagBits : u32 {
41 IsRescalable = 1 << 15, 41 IsRescalable = 1 << 15,
42 42
43 AsynchronousDecode = 1 << 16, 43 AsynchronousDecode = 1 << 16,
44 IsDecoding = 1 << 17, ///< Is currently being decoded asynchornously. 44 IsDecoding = 1 << 17, ///< Is currently being decoded asynchronously.
45}; 45};
46DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits) 46DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits)
47 47
diff --git a/src/video_core/texture_cache/image_view_base.cpp b/src/video_core/texture_cache/image_view_base.cpp
index 0c5f4450d..18b9250f9 100644
--- a/src/video_core/texture_cache/image_view_base.cpp
+++ b/src/video_core/texture_cache/image_view_base.cpp
@@ -85,6 +85,7 @@ bool ImageViewBase::SupportsAnisotropy() const noexcept {
85 // Depth formats 85 // Depth formats
86 case PixelFormat::D32_FLOAT: 86 case PixelFormat::D32_FLOAT:
87 case PixelFormat::D16_UNORM: 87 case PixelFormat::D16_UNORM:
88 case PixelFormat::X8_D24_UNORM:
88 // Stencil formats 89 // Stencil formats
89 case PixelFormat::S8_UINT: 90 case PixelFormat::S8_UINT:
90 // DepthStencil formats 91 // DepthStencil formats
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp
index a83f5d41c..0a86ce139 100644
--- a/src/video_core/texture_cache/util.cpp
+++ b/src/video_core/texture_cache/util.cpp
@@ -1195,7 +1195,7 @@ std::optional<SubresourceBase> FindSubresource(const ImageInfo& candidate, const
1195 return std::nullopt; 1195 return std::nullopt;
1196 } 1196 }
1197 } else { 1197 } else {
1198 // Format comaptibility is not relaxed, ensure we are creating a view on a compatible format 1198 // Format compatibility is not relaxed, ensure we are creating a view on a compatible format
1199 if (!IsViewCompatible(existing.format, candidate.format, broken_views, native_bgr)) { 1199 if (!IsViewCompatible(existing.format, candidate.format, broken_views, native_bgr)) {
1200 return std::nullopt; 1200 return std::nullopt;
1201 } 1201 }
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 3960b135a..876cec2e8 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -84,9 +84,12 @@ constexpr std::array VK_FORMAT_A4B4G4R4_UNORM_PACK16{
84} // namespace Alternatives 84} // namespace Alternatives
85 85
86enum class NvidiaArchitecture { 86enum class NvidiaArchitecture {
87 AmpereOrNewer, 87 KeplerOrOlder,
88 Maxwell,
89 Pascal,
90 Volta,
88 Turing, 91 Turing,
89 VoltaOrOlder, 92 AmpereOrNewer,
90}; 93};
91 94
92template <typename T> 95template <typename T>
@@ -200,6 +203,7 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(vk::Physica
200 VK_FORMAT_BC7_UNORM_BLOCK, 203 VK_FORMAT_BC7_UNORM_BLOCK,
201 VK_FORMAT_D16_UNORM, 204 VK_FORMAT_D16_UNORM,
202 VK_FORMAT_D16_UNORM_S8_UINT, 205 VK_FORMAT_D16_UNORM_S8_UINT,
206 VK_FORMAT_X8_D24_UNORM_PACK32,
203 VK_FORMAT_D24_UNORM_S8_UINT, 207 VK_FORMAT_D24_UNORM_S8_UINT,
204 VK_FORMAT_D32_SFLOAT, 208 VK_FORMAT_D32_SFLOAT,
205 VK_FORMAT_D32_SFLOAT_S8_UINT, 209 VK_FORMAT_D32_SFLOAT_S8_UINT,
@@ -321,13 +325,38 @@ NvidiaArchitecture GetNvidiaArchitecture(vk::PhysicalDevice physical,
321 physical.GetProperties2(physical_properties); 325 physical.GetProperties2(physical_properties);
322 if (shading_rate_props.primitiveFragmentShadingRateWithMultipleViewports) { 326 if (shading_rate_props.primitiveFragmentShadingRateWithMultipleViewports) {
323 // Only Ampere and newer support this feature 327 // Only Ampere and newer support this feature
328 // TODO: Find a way to differentiate Ampere and Ada
324 return NvidiaArchitecture::AmpereOrNewer; 329 return NvidiaArchitecture::AmpereOrNewer;
325 } 330 }
326 }
327 if (exts.contains(VK_NV_SHADING_RATE_IMAGE_EXTENSION_NAME)) {
328 return NvidiaArchitecture::Turing; 331 return NvidiaArchitecture::Turing;
329 } 332 }
330 return NvidiaArchitecture::VoltaOrOlder; 333
334 if (exts.contains(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME)) {
335 VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT advanced_blending_props{};
336 advanced_blending_props.sType =
337 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT;
338 VkPhysicalDeviceProperties2 physical_properties{};
339 physical_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
340 physical_properties.pNext = &advanced_blending_props;
341 physical.GetProperties2(physical_properties);
342 if (advanced_blending_props.advancedBlendMaxColorAttachments == 1) {
343 return NvidiaArchitecture::Maxwell;
344 }
345
346 if (exts.contains(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME)) {
347 VkPhysicalDeviceConservativeRasterizationPropertiesEXT conservative_raster_props{};
348 conservative_raster_props.sType =
349 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT;
350 physical_properties.pNext = &conservative_raster_props;
351 physical.GetProperties2(physical_properties);
352 if (conservative_raster_props.degenerateLinesRasterized) {
353 return NvidiaArchitecture::Volta;
354 }
355 return NvidiaArchitecture::Pascal;
356 }
357 }
358
359 return NvidiaArchitecture::KeplerOrOlder;
331} 360}
332 361
333std::vector<const char*> ExtensionListForVulkan( 362std::vector<const char*> ExtensionListForVulkan(
@@ -504,19 +533,14 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
504 if (is_nvidia) { 533 if (is_nvidia) {
505 const u32 nv_major_version = (properties.properties.driverVersion >> 22) & 0x3ff; 534 const u32 nv_major_version = (properties.properties.driverVersion >> 22) & 0x3ff;
506 const auto arch = GetNvidiaArchitecture(physical, supported_extensions); 535 const auto arch = GetNvidiaArchitecture(physical, supported_extensions);
507 switch (arch) { 536 if (arch >= NvidiaArchitecture::AmpereOrNewer) {
508 case NvidiaArchitecture::AmpereOrNewer:
509 LOG_WARNING(Render_Vulkan, "Ampere and newer have broken float16 math"); 537 LOG_WARNING(Render_Vulkan, "Ampere and newer have broken float16 math");
510 features.shader_float16_int8.shaderFloat16 = false; 538 features.shader_float16_int8.shaderFloat16 = false;
511 break; 539 } else if (arch <= NvidiaArchitecture::Volta) {
512 case NvidiaArchitecture::Turing:
513 break;
514 case NvidiaArchitecture::VoltaOrOlder:
515 if (nv_major_version < 527) { 540 if (nv_major_version < 527) {
516 LOG_WARNING(Render_Vulkan, "Volta and older have broken VK_KHR_push_descriptor"); 541 LOG_WARNING(Render_Vulkan, "Volta and older have broken VK_KHR_push_descriptor");
517 RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); 542 RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
518 } 543 }
519 break;
520 } 544 }
521 if (nv_major_version >= 510) { 545 if (nv_major_version >= 510) {
522 LOG_WARNING(Render_Vulkan, "NVIDIA Drivers >= 510 do not support MSAA image blits"); 546 LOG_WARNING(Render_Vulkan, "NVIDIA Drivers >= 510 do not support MSAA image blits");
@@ -661,7 +685,15 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
661 "ANV drivers 22.3.0 to 23.1.0 have broken VK_KHR_push_descriptor"); 685 "ANV drivers 22.3.0 to 23.1.0 have broken VK_KHR_push_descriptor");
662 RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); 686 RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
663 } 687 }
688 } else if (extensions.push_descriptor && is_nvidia) {
689 const auto arch = GetNvidiaArchitecture(physical, supported_extensions);
690 if (arch <= NvidiaArchitecture::Pascal) {
691 LOG_WARNING(Render_Vulkan,
692 "Pascal and older architectures have broken VK_KHR_push_descriptor");
693 RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
694 }
664 } 695 }
696
665 if (is_mvk) { 697 if (is_mvk) {
666 LOG_WARNING(Render_Vulkan, 698 LOG_WARNING(Render_Vulkan,
667 "MVK driver breaks when using more than 16 vertex attributes/bindings"); 699 "MVK driver breaks when using more than 16 vertex attributes/bindings");
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h
index 9be612392..282a2925d 100644
--- a/src/video_core/vulkan_common/vulkan_device.h
+++ b/src/video_core/vulkan_common/vulkan_device.h
@@ -314,7 +314,7 @@ public:
314 return GetDriverID() != VK_DRIVER_ID_QUALCOMM_PROPRIETARY; 314 return GetDriverID() != VK_DRIVER_ID_QUALCOMM_PROPRIETARY;
315 } 315 }
316 316
317 /// Returns true if the device suppors float64 natively. 317 /// Returns true if the device supports float64 natively.
318 bool IsFloat64Supported() const { 318 bool IsFloat64Supported() const {
319 return features.features.shaderFloat64; 319 return features.features.shaderFloat64;
320 } 320 }
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
index 3ef381a38..82767fdf0 100644
--- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
+++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp
@@ -9,6 +9,7 @@
9#include "common/alignment.h" 9#include "common/alignment.h"
10#include "common/assert.h" 10#include "common/assert.h"
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "common/literals.h"
12#include "common/logging/log.h" 13#include "common/logging/log.h"
13#include "common/polyfill_ranges.h" 14#include "common/polyfill_ranges.h"
14#include "video_core/vulkan_common/vma.h" 15#include "video_core/vulkan_common/vma.h"
@@ -69,8 +70,7 @@ struct Range {
69 case MemoryUsage::Download: 70 case MemoryUsage::Download:
70 return VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT; 71 return VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT;
71 case MemoryUsage::DeviceLocal: 72 case MemoryUsage::DeviceLocal:
72 return VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | 73 return {};
73 VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT;
74 } 74 }
75 return {}; 75 return {};
76} 76}
@@ -212,7 +212,20 @@ MemoryAllocator::MemoryAllocator(const Device& device_)
212 : device{device_}, allocator{device.GetAllocator()}, 212 : device{device_}, allocator{device.GetAllocator()},
213 properties{device_.GetPhysical().GetMemoryProperties().memoryProperties}, 213 properties{device_.GetPhysical().GetMemoryProperties().memoryProperties},
214 buffer_image_granularity{ 214 buffer_image_granularity{
215 device_.GetPhysical().GetProperties().limits.bufferImageGranularity} {} 215 device_.GetPhysical().GetProperties().limits.bufferImageGranularity} {
216 // GPUs not supporting rebar may only have a region with less than 256MB host visible/device
217 // local memory. In that case, opening 2 RenderDoc captures side-by-side is not possible due to
218 // the heap running out of memory. With RenderDoc attached and only a small host/device region,
219 // only allow the stream buffer in this memory heap.
220 if (device.HasDebuggingToolAttached()) {
221 using namespace Common::Literals;
222 ForEachDeviceLocalHostVisibleHeap(device, [this](size_t index, VkMemoryHeap& heap) {
223 if (heap.size <= 256_MiB) {
224 valid_memory_types &= ~(1u << index);
225 }
226 });
227 }
228}
216 229
217MemoryAllocator::~MemoryAllocator() = default; 230MemoryAllocator::~MemoryAllocator() = default;
218 231
@@ -244,7 +257,7 @@ vk::Buffer MemoryAllocator::CreateBuffer(const VkBufferCreateInfo& ci, MemoryUsa
244 .usage = MemoryUsageVma(usage), 257 .usage = MemoryUsageVma(usage),
245 .requiredFlags = 0, 258 .requiredFlags = 0,
246 .preferredFlags = MemoryUsagePreferedVmaFlags(usage), 259 .preferredFlags = MemoryUsagePreferedVmaFlags(usage),
247 .memoryTypeBits = 0, 260 .memoryTypeBits = usage == MemoryUsage::Stream ? 0u : valid_memory_types,
248 .pool = VK_NULL_HANDLE, 261 .pool = VK_NULL_HANDLE,
249 .pUserData = nullptr, 262 .pUserData = nullptr,
250 .priority = 0.f, 263 .priority = 0.f,
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.h b/src/video_core/vulkan_common/vulkan_memory_allocator.h
index f449bc8d0..38a182bcb 100644
--- a/src/video_core/vulkan_common/vulkan_memory_allocator.h
+++ b/src/video_core/vulkan_common/vulkan_memory_allocator.h
@@ -7,6 +7,7 @@
7#include <span> 7#include <span>
8#include <vector> 8#include <vector>
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "video_core/vulkan_common/vulkan_device.h"
10#include "video_core/vulkan_common/vulkan_wrapper.h" 11#include "video_core/vulkan_common/vulkan_wrapper.h"
11 12
12VK_DEFINE_HANDLE(VmaAllocator) 13VK_DEFINE_HANDLE(VmaAllocator)
@@ -26,6 +27,18 @@ enum class MemoryUsage {
26 Stream, ///< Requests device local host visible buffer, falling back host memory. 27 Stream, ///< Requests device local host visible buffer, falling back host memory.
27}; 28};
28 29
30template <typename F>
31void ForEachDeviceLocalHostVisibleHeap(const Device& device, F&& f) {
32 auto memory_props = device.GetPhysical().GetMemoryProperties().memoryProperties;
33 for (size_t i = 0; i < memory_props.memoryTypeCount; i++) {
34 auto& memory_type = memory_props.memoryTypes[i];
35 if ((memory_type.propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) &&
36 (memory_type.propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) {
37 f(memory_type.heapIndex, memory_props.memoryHeaps[memory_type.heapIndex]);
38 }
39 }
40}
41
29/// Ownership handle of a memory commitment. 42/// Ownership handle of a memory commitment.
30/// Points to a subregion of a memory allocation. 43/// Points to a subregion of a memory allocation.
31class MemoryCommit { 44class MemoryCommit {
@@ -124,6 +137,7 @@ private:
124 std::vector<std::unique_ptr<MemoryAllocation>> allocations; ///< Current allocations. 137 std::vector<std::unique_ptr<MemoryAllocation>> allocations; ///< Current allocations.
125 VkDeviceSize buffer_image_granularity; // The granularity for adjacent offsets between buffers 138 VkDeviceSize buffer_image_granularity; // The granularity for adjacent offsets between buffers
126 // and optimal images 139 // and optimal images
140 u32 valid_memory_types{~0u};
127}; 141};
128 142
129} // namespace Vulkan 143} // namespace Vulkan
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp
index 9ccfb2435..81dd51ad3 100644
--- a/src/yuzu/configuration/configure_audio.cpp
+++ b/src/yuzu/configuration/configure_audio.cpp
@@ -42,6 +42,9 @@ void ConfigureAudio::Setup(const ConfigurationShared::Builder& builder) {
42 for (auto* setting : Settings::values.linkage.by_category[category]) { 42 for (auto* setting : Settings::values.linkage.by_category[category]) {
43 settings.push_back(setting); 43 settings.push_back(setting);
44 } 44 }
45 for (auto* setting : UISettings::values.linkage.by_category[category]) {
46 settings.push_back(setting);
47 }
45 }; 48 };
46 49
47 push(Settings::Category::Audio); 50 push(Settings::Category::Audio);
diff --git a/src/yuzu/configuration/shared_translation.cpp b/src/yuzu/configuration/shared_translation.cpp
index 276bdbaba..a4e8af1b4 100644
--- a/src/yuzu/configuration/shared_translation.cpp
+++ b/src/yuzu/configuration/shared_translation.cpp
@@ -29,9 +29,10 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
29 INSERT(Settings, sink_id, "Output Engine:", ""); 29 INSERT(Settings, sink_id, "Output Engine:", "");
30 INSERT(Settings, audio_output_device_id, "Output Device:", ""); 30 INSERT(Settings, audio_output_device_id, "Output Device:", "");
31 INSERT(Settings, audio_input_device_id, "Input Device:", ""); 31 INSERT(Settings, audio_input_device_id, "Input Device:", "");
32 INSERT(Settings, audio_muted, "Mute audio when in background", ""); 32 INSERT(Settings, audio_muted, "Mute audio", "");
33 INSERT(Settings, volume, "Volume:", ""); 33 INSERT(Settings, volume, "Volume:", "");
34 INSERT(Settings, dump_audio_commands, "", ""); 34 INSERT(Settings, dump_audio_commands, "", "");
35 INSERT(UISettings, mute_when_in_background, "Mute audio when in background", "");
35 36
36 // Core 37 // Core
37 INSERT(Settings, use_multi_core, "Multicore CPU Emulation", ""); 38 INSERT(Settings, use_multi_core, "Multicore CPU Emulation", "");
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index adb7b332f..1753fec12 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -18,6 +18,8 @@
18#include <sys/socket.h> 18#include <sys/socket.h>
19#endif 19#endif
20 20
21#include <boost/container/flat_set.hpp>
22
21// VFS includes must be before glad as they will conflict with Windows file api, which uses defines. 23// VFS includes must be before glad as they will conflict with Windows file api, which uses defines.
22#include "applets/qt_amiibo_settings.h" 24#include "applets/qt_amiibo_settings.h"
23#include "applets/qt_controller.h" 25#include "applets/qt_controller.h"
@@ -1445,6 +1447,7 @@ void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) {
1445 Settings::values.audio_muted = false; 1447 Settings::values.audio_muted = false;
1446 auto_muted = false; 1448 auto_muted = false;
1447 } 1449 }
1450 UpdateVolumeUI();
1448 } 1451 }
1449} 1452}
1450 1453
@@ -1551,6 +1554,14 @@ void GMainWindow::ConnectMenuEvents() {
1551 // Tools 1554 // Tools
1552 connect_menu(ui->action_Rederive, std::bind(&GMainWindow::OnReinitializeKeys, this, 1555 connect_menu(ui->action_Rederive, std::bind(&GMainWindow::OnReinitializeKeys, this,
1553 ReinitializeKeyBehavior::Warning)); 1556 ReinitializeKeyBehavior::Warning));
1557 connect_menu(ui->action_Load_Cabinet_Nickname_Owner,
1558 [this]() { OnCabinet(Service::NFP::CabinetMode::StartNicknameAndOwnerSettings); });
1559 connect_menu(ui->action_Load_Cabinet_Eraser,
1560 [this]() { OnCabinet(Service::NFP::CabinetMode::StartGameDataEraser); });
1561 connect_menu(ui->action_Load_Cabinet_Restorer,
1562 [this]() { OnCabinet(Service::NFP::CabinetMode::StartRestorer); });
1563 connect_menu(ui->action_Load_Cabinet_Formatter,
1564 [this]() { OnCabinet(Service::NFP::CabinetMode::StartFormatter); });
1554 connect_menu(ui->action_Load_Mii_Edit, &GMainWindow::OnMiiEdit); 1565 connect_menu(ui->action_Load_Mii_Edit, &GMainWindow::OnMiiEdit);
1555 connect_menu(ui->action_Capture_Screenshot, &GMainWindow::OnCaptureScreenshot); 1566 connect_menu(ui->action_Capture_Screenshot, &GMainWindow::OnCaptureScreenshot);
1556 1567
@@ -1568,6 +1579,7 @@ void GMainWindow::ConnectMenuEvents() {
1568 1579
1569void GMainWindow::UpdateMenuState() { 1580void GMainWindow::UpdateMenuState() {
1570 const bool is_paused = emu_thread == nullptr || !emu_thread->IsRunning(); 1581 const bool is_paused = emu_thread == nullptr || !emu_thread->IsRunning();
1582 const bool is_firmware_available = CheckFirmwarePresence();
1571 1583
1572 const std::array running_actions{ 1584 const std::array running_actions{
1573 ui->action_Stop, 1585 ui->action_Stop,
@@ -1578,10 +1590,22 @@ void GMainWindow::UpdateMenuState() {
1578 ui->action_Pause, 1590 ui->action_Pause,
1579 }; 1591 };
1580 1592
1593 const std::array applet_actions{
1594 ui->action_Load_Cabinet_Nickname_Owner,
1595 ui->action_Load_Cabinet_Eraser,
1596 ui->action_Load_Cabinet_Restorer,
1597 ui->action_Load_Cabinet_Formatter,
1598 ui->action_Load_Mii_Edit,
1599 };
1600
1581 for (QAction* action : running_actions) { 1601 for (QAction* action : running_actions) {
1582 action->setEnabled(emulation_running); 1602 action->setEnabled(emulation_running);
1583 } 1603 }
1584 1604
1605 for (QAction* action : applet_actions) {
1606 action->setEnabled(is_firmware_available && !emulation_running);
1607 }
1608
1585 ui->action_Capture_Screenshot->setEnabled(emulation_running && !is_paused); 1609 ui->action_Capture_Screenshot->setEnabled(emulation_running && !is_paused);
1586 1610
1587 if (emulation_running && is_paused) { 1611 if (emulation_running && is_paused) {
@@ -1591,8 +1615,6 @@ void GMainWindow::UpdateMenuState() {
1591 } 1615 }
1592 1616
1593 multiplayer_state->UpdateNotificationStatus(); 1617 multiplayer_state->UpdateNotificationStatus();
1594
1595 ui->action_Load_Mii_Edit->setEnabled(CheckFirmwarePresence());
1596} 1618}
1597 1619
1598void GMainWindow::OnDisplayTitleBars(bool show) { 1620void GMainWindow::OnDisplayTitleBars(bool show) {
@@ -2103,6 +2125,8 @@ void GMainWindow::OnEmulationStopped() {
2103 OnTasStateChanged(); 2125 OnTasStateChanged();
2104 render_window->FinalizeCamera(); 2126 render_window->FinalizeCamera();
2105 2127
2128 system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::None);
2129
2106 // Enable all controllers 2130 // Enable all controllers
2107 system->HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All}); 2131 system->HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All});
2108 2132
@@ -4134,6 +4158,30 @@ void GMainWindow::OnToggleStatusBar() {
4134 statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked()); 4158 statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked());
4135} 4159}
4136 4160
4161void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) {
4162 constexpr u64 CabinetId = 0x0100000000001002ull;
4163 auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
4164 if (!bis_system) {
4165 QMessageBox::warning(this, tr("No firmware available"),
4166 tr("Please install the firmware to use the Cabinet applet."));
4167 return;
4168 }
4169
4170 auto cabinet_nca = bis_system->GetEntry(CabinetId, FileSys::ContentRecordType::Program);
4171 if (!cabinet_nca) {
4172 QMessageBox::warning(this, tr("Cabinet Applet"),
4173 tr("Cabinet applet is not available. Please reinstall firmware."));
4174 return;
4175 }
4176
4177 system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::Cabinet);
4178 system->GetAppletManager().SetCabinetMode(mode);
4179
4180 const auto filename = QString::fromStdString(cabinet_nca->GetFullPath());
4181 UISettings::values.roms_path = QFileInfo(filename).path();
4182 BootGame(filename);
4183}
4184
4137void GMainWindow::OnMiiEdit() { 4185void GMainWindow::OnMiiEdit() {
4138 constexpr u64 MiiEditId = 0x0100000000001009ull; 4186 constexpr u64 MiiEditId = 0x0100000000001009ull;
4139 auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); 4187 auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
@@ -4150,6 +4198,8 @@ void GMainWindow::OnMiiEdit() {
4150 return; 4198 return;
4151 } 4199 }
4152 4200
4201 system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::MiiEdit);
4202
4153 const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath())); 4203 const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath()));
4154 UISettings::values.roms_path = QFileInfo(filename).path(); 4204 UISettings::values.roms_path = QFileInfo(filename).path();
4155 BootGame(filename); 4205 BootGame(filename);
@@ -4602,8 +4652,8 @@ bool GMainWindow::CheckFirmwarePresence() {
4602 4652
4603bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, u64 program_id, 4653bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed, u64 program_id,
4604 u64* selected_title_id, u8* selected_content_record_type) { 4654 u64* selected_title_id, u8* selected_content_record_type) {
4605 using ContentInfo = std::pair<FileSys::TitleType, FileSys::ContentRecordType>; 4655 using ContentInfo = std::tuple<u64, FileSys::TitleType, FileSys::ContentRecordType>;
4606 boost::container::flat_map<u64, ContentInfo> available_title_ids; 4656 boost::container::flat_set<ContentInfo> available_title_ids;
4607 4657
4608 const auto RetrieveEntries = [&](FileSys::TitleType title_type, 4658 const auto RetrieveEntries = [&](FileSys::TitleType title_type,
4609 FileSys::ContentRecordType record_type) { 4659 FileSys::ContentRecordType record_type) {
@@ -4611,12 +4661,14 @@ bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installe
4611 for (const auto& entry : entries) { 4661 for (const auto& entry : entries) {
4612 if (FileSys::GetBaseTitleID(entry.title_id) == program_id && 4662 if (FileSys::GetBaseTitleID(entry.title_id) == program_id &&
4613 installed.GetEntry(entry)->GetStatus() == Loader::ResultStatus::Success) { 4663 installed.GetEntry(entry)->GetStatus() == Loader::ResultStatus::Success) {
4614 available_title_ids[entry.title_id] = {title_type, record_type}; 4664 available_title_ids.insert({entry.title_id, title_type, record_type});
4615 } 4665 }
4616 } 4666 }
4617 }; 4667 };
4618 4668
4619 RetrieveEntries(FileSys::TitleType::Application, FileSys::ContentRecordType::Program); 4669 RetrieveEntries(FileSys::TitleType::Application, FileSys::ContentRecordType::Program);
4670 RetrieveEntries(FileSys::TitleType::Application, FileSys::ContentRecordType::HtmlDocument);
4671 RetrieveEntries(FileSys::TitleType::Application, FileSys::ContentRecordType::LegalInformation);
4620 RetrieveEntries(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data); 4672 RetrieveEntries(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data);
4621 4673
4622 if (available_title_ids.empty()) { 4674 if (available_title_ids.empty()) {
@@ -4627,10 +4679,14 @@ bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installe
4627 4679
4628 if (available_title_ids.size() > 1) { 4680 if (available_title_ids.size() > 1) {
4629 QStringList list; 4681 QStringList list;
4630 for (auto& [title_id, content_info] : available_title_ids) { 4682 for (auto& [title_id, title_type, record_type] : available_title_ids) {
4631 const auto hex_title_id = QString::fromStdString(fmt::format("{:X}", title_id)); 4683 const auto hex_title_id = QString::fromStdString(fmt::format("{:X}", title_id));
4632 if (content_info.first == FileSys::TitleType::Application) { 4684 if (record_type == FileSys::ContentRecordType::Program) {
4633 list.push_back(QStringLiteral("Application [%1]").arg(hex_title_id)); 4685 list.push_back(QStringLiteral("Program [%1]").arg(hex_title_id));
4686 } else if (record_type == FileSys::ContentRecordType::HtmlDocument) {
4687 list.push_back(QStringLiteral("HTML document [%1]").arg(hex_title_id));
4688 } else if (record_type == FileSys::ContentRecordType::LegalInformation) {
4689 list.push_back(QStringLiteral("Legal information [%1]").arg(hex_title_id));
4634 } else { 4690 } else {
4635 list.push_back( 4691 list.push_back(
4636 QStringLiteral("DLC %1 [%2]").arg(title_id & 0x7FF).arg(hex_title_id)); 4692 QStringLiteral("DLC %1 [%2]").arg(title_id & 0x7FF).arg(hex_title_id));
@@ -4648,9 +4704,9 @@ bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installe
4648 title_index = list.indexOf(res); 4704 title_index = list.indexOf(res);
4649 } 4705 }
4650 4706
4651 const auto selected_info = available_title_ids.nth(title_index); 4707 const auto& [title_id, title_type, record_type] = *available_title_ids.nth(title_index);
4652 *selected_title_id = selected_info->first; 4708 *selected_title_id = title_id;
4653 *selected_content_record_type = static_cast<u8>(selected_info->second.second); 4709 *selected_content_record_type = static_cast<u8>(record_type);
4654 return true; 4710 return true;
4655} 4711}
4656 4712
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index ba318eb11..52028234c 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -102,6 +102,10 @@ namespace Service::NFC {
102class NfcDevice; 102class NfcDevice;
103} // namespace Service::NFC 103} // namespace Service::NFC
104 104
105namespace Service::NFP {
106enum class CabinetMode : u8;
107} // namespace Service::NFP
108
105namespace Ui { 109namespace Ui {
106class MainWindow; 110class MainWindow;
107} 111}
@@ -365,6 +369,7 @@ private slots:
365 void ResetWindowSize720(); 369 void ResetWindowSize720();
366 void ResetWindowSize900(); 370 void ResetWindowSize900();
367 void ResetWindowSize1080(); 371 void ResetWindowSize1080();
372 void OnCabinet(Service::NFP::CabinetMode mode);
368 void OnMiiEdit(); 373 void OnMiiEdit();
369 void OnCaptureScreenshot(); 374 void OnCaptureScreenshot();
370 void OnReinitializeKeys(ReinitializeKeyBehavior behavior); 375 void OnReinitializeKeys(ReinitializeKeyBehavior behavior);
diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui
index 91d6c5ef3..31c3de9ef 100644
--- a/src/yuzu/main.ui
+++ b/src/yuzu/main.ui
@@ -137,6 +137,15 @@
137 <property name="title"> 137 <property name="title">
138 <string>&amp;Tools</string> 138 <string>&amp;Tools</string>
139 </property> 139 </property>
140 <widget class="QMenu" name="menu_cabinet_applet">
141 <property name="title">
142 <string>&amp;Amiibo</string>
143 </property>
144 <addaction name="action_Load_Cabinet_Nickname_Owner"/>
145 <addaction name="action_Load_Cabinet_Eraser"/>
146 <addaction name="action_Load_Cabinet_Restorer"/>
147 <addaction name="action_Load_Cabinet_Formatter"/>
148 </widget>
140 <widget class="QMenu" name="menuTAS"> 149 <widget class="QMenu" name="menuTAS">
141 <property name="title"> 150 <property name="title">
142 <string>&amp;TAS</string> 151 <string>&amp;TAS</string>
@@ -150,6 +159,7 @@
150 <addaction name="action_Rederive"/> 159 <addaction name="action_Rederive"/>
151 <addaction name="action_Verify_installed_contents"/> 160 <addaction name="action_Verify_installed_contents"/>
152 <addaction name="separator"/> 161 <addaction name="separator"/>
162 <addaction name="menu_cabinet_applet"/>
153 <addaction name="action_Load_Mii_Edit"/> 163 <addaction name="action_Load_Mii_Edit"/>
154 <addaction name="separator"/> 164 <addaction name="separator"/>
155 <addaction name="action_Capture_Screenshot"/> 165 <addaction name="action_Capture_Screenshot"/>
@@ -370,6 +380,26 @@
370 <string>&amp;Capture Screenshot</string> 380 <string>&amp;Capture Screenshot</string>
371 </property> 381 </property>
372 </action> 382 </action>
383 <action name="action_Load_Cabinet_Nickname_Owner">
384 <property name="text">
385 <string>&amp;Set Nickname and Owner</string>
386 </property>
387 </action>
388 <action name="action_Load_Cabinet_Eraser">
389 <property name="text">
390 <string>&amp;Delete Game Data</string>
391 </property>
392 </action>
393 <action name="action_Load_Cabinet_Restorer">
394 <property name="text">
395 <string>&amp;Restore Amiibo</string>
396 </property>
397 </action>
398 <action name="action_Load_Cabinet_Formatter">
399 <property name="text">
400 <string>&amp;Format Amiibo</string>
401 </property>
402 </action>
373 <action name="action_Load_Mii_Edit"> 403 <action name="action_Load_Mii_Edit">
374 <property name="text"> 404 <property name="text">
375 <string>Open &amp;Mii Editor</string> 405 <string>Open &amp;Mii Editor</string>
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index 8efd63f31..8a2caa9dd 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -103,7 +103,7 @@ struct Values {
103 true, 103 true,
104 true}; 104 true};
105 Setting<bool> mute_when_in_background{ 105 Setting<bool> mute_when_in_background{
106 linkage, false, "muteWhenInBackground", Category::Ui, Settings::Specialization::Default, 106 linkage, false, "muteWhenInBackground", Category::Audio, Settings::Specialization::Default,
107 true, true}; 107 true, true};
108 Setting<bool> hide_mouse{ 108 Setting<bool> hide_mouse{
109 linkage, true, "hideInactiveMouse", Category::UiGeneral, Settings::Specialization::Default, 109 linkage, true, "hideInactiveMouse", Category::UiGeneral, Settings::Specialization::Default,