summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt2
-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/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/yuzu/main.cpp51
-rw-r--r--src/yuzu/main.h5
-rw-r--r--src/yuzu/main.ui30
23 files changed, 985 insertions, 60 deletions
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/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/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/yuzu/main.cpp b/src/yuzu/main.cpp
index adb7b332f..ec27361d5 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1551,6 +1551,14 @@ void GMainWindow::ConnectMenuEvents() {
1551 // Tools 1551 // Tools
1552 connect_menu(ui->action_Rederive, std::bind(&GMainWindow::OnReinitializeKeys, this, 1552 connect_menu(ui->action_Rederive, std::bind(&GMainWindow::OnReinitializeKeys, this,
1553 ReinitializeKeyBehavior::Warning)); 1553 ReinitializeKeyBehavior::Warning));
1554 connect_menu(ui->action_Load_Cabinet_Nickname_Owner,
1555 [this]() { OnCabinet(Service::NFP::CabinetMode::StartNicknameAndOwnerSettings); });
1556 connect_menu(ui->action_Load_Cabinet_Eraser,
1557 [this]() { OnCabinet(Service::NFP::CabinetMode::StartGameDataEraser); });
1558 connect_menu(ui->action_Load_Cabinet_Restorer,
1559 [this]() { OnCabinet(Service::NFP::CabinetMode::StartRestorer); });
1560 connect_menu(ui->action_Load_Cabinet_Formatter,
1561 [this]() { OnCabinet(Service::NFP::CabinetMode::StartFormatter); });
1554 connect_menu(ui->action_Load_Mii_Edit, &GMainWindow::OnMiiEdit); 1562 connect_menu(ui->action_Load_Mii_Edit, &GMainWindow::OnMiiEdit);
1555 connect_menu(ui->action_Capture_Screenshot, &GMainWindow::OnCaptureScreenshot); 1563 connect_menu(ui->action_Capture_Screenshot, &GMainWindow::OnCaptureScreenshot);
1556 1564
@@ -1568,6 +1576,7 @@ void GMainWindow::ConnectMenuEvents() {
1568 1576
1569void GMainWindow::UpdateMenuState() { 1577void GMainWindow::UpdateMenuState() {
1570 const bool is_paused = emu_thread == nullptr || !emu_thread->IsRunning(); 1578 const bool is_paused = emu_thread == nullptr || !emu_thread->IsRunning();
1579 const bool is_firmware_available = CheckFirmwarePresence();
1571 1580
1572 const std::array running_actions{ 1581 const std::array running_actions{
1573 ui->action_Stop, 1582 ui->action_Stop,
@@ -1578,10 +1587,22 @@ void GMainWindow::UpdateMenuState() {
1578 ui->action_Pause, 1587 ui->action_Pause,
1579 }; 1588 };
1580 1589
1590 const std::array applet_actions{
1591 ui->action_Load_Cabinet_Nickname_Owner,
1592 ui->action_Load_Cabinet_Eraser,
1593 ui->action_Load_Cabinet_Restorer,
1594 ui->action_Load_Cabinet_Formatter,
1595 ui->action_Load_Mii_Edit,
1596 };
1597
1581 for (QAction* action : running_actions) { 1598 for (QAction* action : running_actions) {
1582 action->setEnabled(emulation_running); 1599 action->setEnabled(emulation_running);
1583 } 1600 }
1584 1601
1602 for (QAction* action : applet_actions) {
1603 action->setEnabled(is_firmware_available && !emulation_running);
1604 }
1605
1585 ui->action_Capture_Screenshot->setEnabled(emulation_running && !is_paused); 1606 ui->action_Capture_Screenshot->setEnabled(emulation_running && !is_paused);
1586 1607
1587 if (emulation_running && is_paused) { 1608 if (emulation_running && is_paused) {
@@ -1591,8 +1612,6 @@ void GMainWindow::UpdateMenuState() {
1591 } 1612 }
1592 1613
1593 multiplayer_state->UpdateNotificationStatus(); 1614 multiplayer_state->UpdateNotificationStatus();
1594
1595 ui->action_Load_Mii_Edit->setEnabled(CheckFirmwarePresence());
1596} 1615}
1597 1616
1598void GMainWindow::OnDisplayTitleBars(bool show) { 1617void GMainWindow::OnDisplayTitleBars(bool show) {
@@ -2103,6 +2122,8 @@ void GMainWindow::OnEmulationStopped() {
2103 OnTasStateChanged(); 2122 OnTasStateChanged();
2104 render_window->FinalizeCamera(); 2123 render_window->FinalizeCamera();
2105 2124
2125 system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::None);
2126
2106 // Enable all controllers 2127 // Enable all controllers
2107 system->HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All}); 2128 system->HIDCore().SetSupportedStyleTag({Core::HID::NpadStyleSet::All});
2108 2129
@@ -4134,6 +4155,30 @@ void GMainWindow::OnToggleStatusBar() {
4134 statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked()); 4155 statusBar()->setVisible(ui->action_Show_Status_Bar->isChecked());
4135} 4156}
4136 4157
4158void GMainWindow::OnCabinet(Service::NFP::CabinetMode mode) {
4159 constexpr u64 CabinetId = 0x0100000000001002ull;
4160 auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
4161 if (!bis_system) {
4162 QMessageBox::warning(this, tr("No firmware available"),
4163 tr("Please install the firmware to use the Cabinet applet."));
4164 return;
4165 }
4166
4167 auto cabinet_nca = bis_system->GetEntry(CabinetId, FileSys::ContentRecordType::Program);
4168 if (!cabinet_nca) {
4169 QMessageBox::warning(this, tr("Cabinet Applet"),
4170 tr("Cabinet applet is not available. Please reinstall firmware."));
4171 return;
4172 }
4173
4174 system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::Cabinet);
4175 system->GetAppletManager().SetCabinetMode(mode);
4176
4177 const auto filename = QString::fromStdString(cabinet_nca->GetFullPath());
4178 UISettings::values.roms_path = QFileInfo(filename).path();
4179 BootGame(filename);
4180}
4181
4137void GMainWindow::OnMiiEdit() { 4182void GMainWindow::OnMiiEdit() {
4138 constexpr u64 MiiEditId = 0x0100000000001009ull; 4183 constexpr u64 MiiEditId = 0x0100000000001009ull;
4139 auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); 4184 auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
@@ -4150,6 +4195,8 @@ void GMainWindow::OnMiiEdit() {
4150 return; 4195 return;
4151 } 4196 }
4152 4197
4198 system->GetAppletManager().SetCurrentAppletId(Service::AM::Applets::AppletId::MiiEdit);
4199
4153 const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath())); 4200 const auto filename = QString::fromStdString((mii_applet_nca->GetFullPath()));
4154 UISettings::values.roms_path = QFileInfo(filename).path(); 4201 UISettings::values.roms_path = QFileInfo(filename).path();
4155 BootGame(filename); 4202 BootGame(filename);
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>