summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service/am/frontend/applets.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service/am/frontend/applets.cpp')
-rw-r--r--src/core/hle/service/am/frontend/applets.cpp341
1 files changed, 341 insertions, 0 deletions
diff --git a/src/core/hle/service/am/frontend/applets.cpp b/src/core/hle/service/am/frontend/applets.cpp
new file mode 100644
index 000000000..4e8f806d7
--- /dev/null
+++ b/src/core/hle/service/am/frontend/applets.cpp
@@ -0,0 +1,341 @@
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <cstring>
+
+#include "common/assert.h"
+#include "core/core.h"
+#include "core/frontend/applets/cabinet.h"
+#include "core/frontend/applets/controller.h"
+#include "core/frontend/applets/error.h"
+#include "core/frontend/applets/general.h"
+#include "core/frontend/applets/mii_edit.h"
+#include "core/frontend/applets/profile_select.h"
+#include "core/frontend/applets/software_keyboard.h"
+#include "core/frontend/applets/web_browser.h"
+#include "core/hle/kernel/k_event.h"
+#include "core/hle/service/am/am.h"
+#include "core/hle/service/am/applet_ae.h"
+#include "core/hle/service/am/applet_message_queue.h"
+#include "core/hle/service/am/applet_oe.h"
+#include "core/hle/service/am/frontend/applet_cabinet.h"
+#include "core/hle/service/am/frontend/applet_controller.h"
+#include "core/hle/service/am/frontend/applet_error.h"
+#include "core/hle/service/am/frontend/applet_general.h"
+#include "core/hle/service/am/frontend/applet_mii_edit.h"
+#include "core/hle/service/am/frontend/applet_profile_select.h"
+#include "core/hle/service/am/frontend/applet_software_keyboard.h"
+#include "core/hle/service/am/frontend/applet_web_browser.h"
+#include "core/hle/service/am/frontend/applets.h"
+#include "core/hle/service/am/storage.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::AM::Frontend {
+
+AppletDataBroker::AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_)
+ : system{system_}, applet_mode{applet_mode_},
+ service_context{system, "ILibraryAppletAccessor"} {
+ state_changed_event = service_context.CreateEvent("ILibraryAppletAccessor:StateChangedEvent");
+ pop_out_data_event = service_context.CreateEvent("ILibraryAppletAccessor:PopDataOutEvent");
+ pop_interactive_out_data_event =
+ service_context.CreateEvent("ILibraryAppletAccessor:PopInteractiveDataOutEvent");
+}
+
+AppletDataBroker::~AppletDataBroker() {
+ service_context.CloseEvent(state_changed_event);
+ service_context.CloseEvent(pop_out_data_event);
+ service_context.CloseEvent(pop_interactive_out_data_event);
+}
+
+AppletDataBroker::RawChannelData AppletDataBroker::PeekDataToAppletForDebug() const {
+ std::vector<std::vector<u8>> out_normal;
+
+ for (const auto& storage : in_channel) {
+ out_normal.push_back(storage->GetData());
+ }
+
+ std::vector<std::vector<u8>> out_interactive;
+
+ for (const auto& storage : in_interactive_channel) {
+ out_interactive.push_back(storage->GetData());
+ }
+
+ return {std::move(out_normal), std::move(out_interactive)};
+}
+
+std::shared_ptr<IStorage> AppletDataBroker::PopNormalDataToGame() {
+ if (out_channel.empty())
+ return nullptr;
+
+ auto out = std::move(out_channel.front());
+ out_channel.pop_front();
+ pop_out_data_event->Clear();
+ return out;
+}
+
+std::shared_ptr<IStorage> AppletDataBroker::PopNormalDataToApplet() {
+ if (in_channel.empty())
+ return nullptr;
+
+ auto out = std::move(in_channel.front());
+ in_channel.pop_front();
+ return out;
+}
+
+std::shared_ptr<IStorage> AppletDataBroker::PopInteractiveDataToGame() {
+ if (out_interactive_channel.empty())
+ return nullptr;
+
+ auto out = std::move(out_interactive_channel.front());
+ out_interactive_channel.pop_front();
+ pop_interactive_out_data_event->Clear();
+ return out;
+}
+
+std::shared_ptr<IStorage> AppletDataBroker::PopInteractiveDataToApplet() {
+ if (in_interactive_channel.empty())
+ return nullptr;
+
+ auto out = std::move(in_interactive_channel.front());
+ in_interactive_channel.pop_front();
+ return out;
+}
+
+void AppletDataBroker::PushNormalDataFromGame(std::shared_ptr<IStorage>&& storage) {
+ in_channel.emplace_back(std::move(storage));
+}
+
+void AppletDataBroker::PushNormalDataFromApplet(std::shared_ptr<IStorage>&& storage) {
+ out_channel.emplace_back(std::move(storage));
+ pop_out_data_event->Signal();
+}
+
+void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& storage) {
+ in_interactive_channel.emplace_back(std::move(storage));
+}
+
+void AppletDataBroker::PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&& storage) {
+ out_interactive_channel.emplace_back(std::move(storage));
+ pop_interactive_out_data_event->Signal();
+}
+
+void AppletDataBroker::SignalStateChanged() {
+ state_changed_event->Signal();
+
+ switch (applet_mode) {
+ case LibraryAppletMode::AllForeground:
+ case LibraryAppletMode::AllForegroundInitiallyHidden: {
+ auto applet_oe = system.ServiceManager().GetService<AppletOE>("appletOE");
+ auto applet_ae = system.ServiceManager().GetService<AppletAE>("appletAE");
+
+ if (applet_oe) {
+ applet_oe->GetMessageQueue()->FocusStateChanged();
+ break;
+ }
+
+ if (applet_ae) {
+ applet_ae->GetMessageQueue()->FocusStateChanged();
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+Kernel::KReadableEvent& AppletDataBroker::GetNormalDataEvent() {
+ return pop_out_data_event->GetReadableEvent();
+}
+
+Kernel::KReadableEvent& AppletDataBroker::GetInteractiveDataEvent() {
+ return pop_interactive_out_data_event->GetReadableEvent();
+}
+
+Kernel::KReadableEvent& AppletDataBroker::GetStateChangedEvent() {
+ return state_changed_event->GetReadableEvent();
+}
+
+FrontendApplet::FrontendApplet(Core::System& system_, LibraryAppletMode applet_mode_)
+ : broker{system_, applet_mode_}, applet_mode{applet_mode_} {}
+
+FrontendApplet::~FrontendApplet() = default;
+
+void FrontendApplet::Initialize() {
+ const auto common = broker.PopNormalDataToApplet();
+ ASSERT(common != nullptr);
+
+ const auto common_data = common->GetData();
+
+ ASSERT(common_data.size() >= sizeof(CommonArguments));
+ std::memcpy(&common_args, common_data.data(), sizeof(CommonArguments));
+
+ initialized = true;
+}
+
+FrontendAppletSet::FrontendAppletSet() = default;
+
+FrontendAppletSet::FrontendAppletSet(CabinetApplet cabinet_applet,
+ ControllerApplet controller_applet, ErrorApplet error_applet,
+ MiiEdit mii_edit_,
+ ParentalControlsApplet parental_controls_applet,
+ PhotoViewer photo_viewer_, ProfileSelect profile_select_,
+ SoftwareKeyboard software_keyboard_, WebBrowser web_browser_)
+ : cabinet{std::move(cabinet_applet)}, controller{std::move(controller_applet)},
+ error{std::move(error_applet)}, mii_edit{std::move(mii_edit_)},
+ parental_controls{std::move(parental_controls_applet)},
+ photo_viewer{std::move(photo_viewer_)}, profile_select{std::move(profile_select_)},
+ software_keyboard{std::move(software_keyboard_)}, web_browser{std::move(web_browser_)} {}
+
+FrontendAppletSet::~FrontendAppletSet() = default;
+
+FrontendAppletSet::FrontendAppletSet(FrontendAppletSet&&) noexcept = default;
+
+FrontendAppletSet& FrontendAppletSet::operator=(FrontendAppletSet&&) noexcept = default;
+
+FrontendAppletHolder::FrontendAppletHolder(Core::System& system_) : system{system_} {}
+
+FrontendAppletHolder::~FrontendAppletHolder() = default;
+
+const FrontendAppletSet& FrontendAppletHolder::GetFrontendAppletSet() const {
+ return frontend;
+}
+
+NFP::CabinetMode FrontendAppletHolder::GetCabinetMode() const {
+ return cabinet_mode;
+}
+
+AppletId FrontendAppletHolder::GetCurrentAppletId() const {
+ return current_applet_id;
+}
+
+void FrontendAppletHolder::SetFrontendAppletSet(FrontendAppletSet set) {
+ if (set.cabinet != nullptr) {
+ frontend.cabinet = std::move(set.cabinet);
+ }
+
+ if (set.controller != nullptr) {
+ frontend.controller = std::move(set.controller);
+ }
+
+ if (set.error != nullptr) {
+ frontend.error = std::move(set.error);
+ }
+
+ if (set.mii_edit != nullptr) {
+ frontend.mii_edit = std::move(set.mii_edit);
+ }
+
+ if (set.parental_controls != nullptr) {
+ frontend.parental_controls = std::move(set.parental_controls);
+ }
+
+ if (set.photo_viewer != nullptr) {
+ frontend.photo_viewer = std::move(set.photo_viewer);
+ }
+
+ if (set.profile_select != nullptr) {
+ frontend.profile_select = std::move(set.profile_select);
+ }
+
+ if (set.software_keyboard != nullptr) {
+ frontend.software_keyboard = std::move(set.software_keyboard);
+ }
+
+ if (set.web_browser != nullptr) {
+ frontend.web_browser = std::move(set.web_browser);
+ }
+}
+
+void FrontendAppletHolder::SetCabinetMode(NFP::CabinetMode mode) {
+ cabinet_mode = mode;
+}
+
+void FrontendAppletHolder::SetCurrentAppletId(AppletId applet_id) {
+ current_applet_id = applet_id;
+}
+
+void FrontendAppletHolder::SetDefaultAppletFrontendSet() {
+ ClearAll();
+ SetDefaultAppletsIfMissing();
+}
+
+void FrontendAppletHolder::SetDefaultAppletsIfMissing() {
+ if (frontend.cabinet == nullptr) {
+ frontend.cabinet = std::make_unique<Core::Frontend::DefaultCabinetApplet>();
+ }
+
+ if (frontend.controller == nullptr) {
+ frontend.controller =
+ std::make_unique<Core::Frontend::DefaultControllerApplet>(system.HIDCore());
+ }
+
+ if (frontend.error == nullptr) {
+ frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>();
+ }
+
+ if (frontend.mii_edit == nullptr) {
+ frontend.mii_edit = std::make_unique<Core::Frontend::DefaultMiiEditApplet>();
+ }
+
+ if (frontend.parental_controls == nullptr) {
+ frontend.parental_controls =
+ std::make_unique<Core::Frontend::DefaultParentalControlsApplet>();
+ }
+
+ if (frontend.photo_viewer == nullptr) {
+ frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>();
+ }
+
+ if (frontend.profile_select == nullptr) {
+ frontend.profile_select = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
+ }
+
+ if (frontend.software_keyboard == nullptr) {
+ frontend.software_keyboard =
+ std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
+ }
+
+ if (frontend.web_browser == nullptr) {
+ frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>();
+ }
+}
+
+void FrontendAppletHolder::ClearAll() {
+ frontend = {};
+}
+
+std::shared_ptr<FrontendApplet> FrontendAppletHolder::GetApplet(AppletId id,
+ LibraryAppletMode mode) const {
+ switch (id) {
+ case AppletId::Auth:
+ return std::make_shared<Auth>(system, mode, *frontend.parental_controls);
+ case AppletId::Cabinet:
+ return std::make_shared<Cabinet>(system, mode, *frontend.cabinet);
+ case AppletId::Controller:
+ return std::make_shared<Controller>(system, mode, *frontend.controller);
+ case AppletId::Error:
+ return std::make_shared<Error>(system, mode, *frontend.error);
+ case AppletId::ProfileSelect:
+ return std::make_shared<ProfileSelect>(system, mode, *frontend.profile_select);
+ case AppletId::SoftwareKeyboard:
+ return std::make_shared<SoftwareKeyboard>(system, mode, *frontend.software_keyboard);
+ case AppletId::MiiEdit:
+ return std::make_shared<MiiEdit>(system, mode, *frontend.mii_edit);
+ case AppletId::Web:
+ case AppletId::Shop:
+ case AppletId::OfflineWeb:
+ case AppletId::LoginShare:
+ case AppletId::WebAuth:
+ return std::make_shared<WebBrowser>(system, mode, *frontend.web_browser);
+ case AppletId::PhotoViewer:
+ return std::make_shared<PhotoViewer>(system, mode, *frontend.photo_viewer);
+ default:
+ UNIMPLEMENTED_MSG(
+ "No backend implementation exists for applet_id={:02X}! Falling back to stub applet.",
+ static_cast<u8>(id));
+ return std::make_shared<StubApplet>(system, id, mode);
+ }
+}
+
+} // namespace Service::AM::Frontend