summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service')
-rw-r--r--src/core/hle/service/acc/acc.cpp4
-rw-r--r--src/core/hle/service/acc/profile_manager.cpp2
-rw-r--r--src/core/hle/service/am/am.cpp101
-rw-r--r--src/core/hle/service/am/am.h5
-rw-r--r--src/core/hle/service/am/applets/applets.cpp57
-rw-r--r--src/core/hle/service/am/applets/applets.h30
-rw-r--r--src/core/hle/service/am/applets/controller.cpp5
-rw-r--r--src/core/hle/service/am/applets/controller.h3
-rw-r--r--src/core/hle/service/am/applets/error.cpp5
-rw-r--r--src/core/hle/service/am/applets/error.h3
-rw-r--r--src/core/hle/service/am/applets/general_backend.cpp14
-rw-r--r--src/core/hle/service/am/applets/general_backend.h8
-rw-r--r--src/core/hle/service/am/applets/profile_select.cpp4
-rw-r--r--src/core/hle/service/am/applets/profile_select.h2
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.cpp1153
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.h186
-rw-r--r--src/core/hle/service/am/applets/software_keyboard_types.h295
-rw-r--r--src/core/hle/service/am/applets/web_browser.cpp5
-rw-r--r--src/core/hle/service/am/applets/web_browser.h3
-rw-r--r--src/core/hle/service/aoc/aoc_u.cpp2
-rw-r--r--src/core/hle/service/apm/controller.cpp2
-rw-r--r--src/core/hle/service/bcat/backend/boxcat.cpp2
-rw-r--r--src/core/hle/service/bcat/module.cpp2
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp2
-rw-r--r--src/core/hle/service/glue/arp.cpp10
-rw-r--r--src/core/hle/service/glue/ectx.cpp22
-rw-r--r--src/core/hle/service/glue/ectx.h21
-rw-r--r--src/core/hle/service/glue/glue.cpp4
-rw-r--r--src/core/hle/service/hid/controllers/debug_pad.cpp2
-rw-r--r--src/core/hle/service/hid/controllers/debug_pad.h2
-rw-r--r--src/core/hle/service/hid/controllers/gesture.cpp2
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.cpp2
-rw-r--r--src/core/hle/service/hid/controllers/keyboard.h2
-rw-r--r--src/core/hle/service/hid/controllers/mouse.h2
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp4
-rw-r--r--src/core/hle/service/hid/controllers/npad.h3
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.cpp2
-rw-r--r--src/core/hle/service/hid/hid.cpp41
-rw-r--r--src/core/hle/service/lbl/lbl.cpp2
-rw-r--r--src/core/hle/service/lm/lm.cpp13
-rw-r--r--src/core/hle/service/nfc/nfc.cpp2
-rw-r--r--src/core/hle/service/nifm/nifm.cpp2
-rw-r--r--src/core/hle/service/ns/ns.cpp2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp14
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_vic.cpp12
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp2
-rw-r--r--src/core/hle/service/service.cpp2
-rw-r--r--src/core/hle/service/set/set.cpp5
-rw-r--r--src/core/hle/service/spl/module.cpp2
-rw-r--r--src/core/hle/service/time/time.cpp8
-rw-r--r--src/core/hle/service/time/time_manager.cpp2
-rw-r--r--src/core/hle/service/time/time_zone_content_manager.cpp2
-rw-r--r--src/core/hle/service/time/time_zone_service.cpp6
-rw-r--r--src/core/hle/service/vi/vi.cpp10
54 files changed, 1780 insertions, 320 deletions
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 52535ecc0..5450dcf0f 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -702,16 +702,12 @@ void Module::Interface::IsUserRegistrationRequestPermitted(Kernel::HLERequestCon
}
void Module::Interface::InitializeApplicationInfo(Kernel::HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
LOG_DEBUG(Service_ACC, "called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(InitializeApplicationInfoBase());
}
void Module::Interface::InitializeApplicationInfoRestricted(Kernel::HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
-
LOG_WARNING(Service_ACC, "(Partial implementation) called");
// TODO(ogniK): We require checking if the user actually owns the title and what not. As of
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp
index 50b2c58e2..de83d82a4 100644
--- a/src/core/hle/service/acc/profile_manager.cpp
+++ b/src/core/hle/service/acc/profile_manager.cpp
@@ -8,8 +8,8 @@
#include <fmt/format.h>
#include "common/file_util.h"
+#include "common/settings.h"
#include "core/hle/service/acc/profile_manager.h"
-#include "core/settings.h"
namespace Service::Account {
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 4374487a3..58c7f2930 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -7,6 +7,7 @@
#include <cinttypes>
#include <cstring>
#include "audio_core/audio_renderer.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/patch_manager.h"
@@ -41,7 +42,6 @@
#include "core/hle/service/set/set.h"
#include "core/hle/service/sm/sm.h"
#include "core/hle/service/vi/vi.h"
-#include "core/settings.h"
namespace Service::AM {
@@ -619,16 +619,20 @@ std::size_t AppletMessageQueue::GetMessageCount() const {
return messages.size();
}
+void AppletMessageQueue::RequestExit() {
+ PushMessage(AppletMessage::ExitRequested);
+}
+
+void AppletMessageQueue::FocusStateChanged() {
+ PushMessage(AppletMessage::FocusStateChanged);
+}
+
void AppletMessageQueue::OperationModeChanged() {
PushMessage(AppletMessage::OperationModeChanged);
PushMessage(AppletMessage::PerformanceModeChanged);
on_operation_mode_changed->GetWritableEvent()->Signal();
}
-void AppletMessageQueue::RequestExit() {
- PushMessage(AppletMessage::ExitRequested);
-}
-
ICommonStateGetter::ICommonStateGetter(Core::System& system_,
std::shared_ptr<AppletMessageQueue> msg_queue_)
: ServiceFramework{system_, "ICommonStateGetter"}, msg_queue{std::move(msg_queue_)} {
@@ -683,7 +687,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system_,
{501, nullptr, "SuppressDisablingSleepTemporarily"},
{502, nullptr, "IsSleepEnabled"},
{503, nullptr, "IsDisablingSleepSuppressed"},
- {900, nullptr, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"},
+ {900, &ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled, "SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled"},
};
// clang-format on
@@ -813,6 +817,14 @@ void ICommonStateGetter::SetCpuBoostMode(Kernel::HLERequestContext& ctx) {
apm_sys->SetCpuBoostMode(ctx);
}
+void ICommonStateGetter::SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(
+ Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+}
+
IStorageImpl::~IStorageImpl() = default;
class StorageDataImpl final : public IStorageImpl {
@@ -971,7 +983,7 @@ private:
auto storage = applet->GetBroker().PopNormalDataToGame();
if (storage == nullptr) {
- LOG_ERROR(Service_AM,
+ LOG_DEBUG(Service_AM,
"storage is a nullptr. There is no data in the current normal channel");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NO_DATA_IN_CHANNEL);
@@ -1002,7 +1014,7 @@ private:
auto storage = applet->GetBroker().PopInteractiveDataToGame();
if (storage == nullptr) {
- LOG_ERROR(Service_AM,
+ LOG_DEBUG(Service_AM,
"storage is a nullptr. There is no data in the current interactive channel");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ERR_NO_DATA_IN_CHANNEL);
@@ -1125,7 +1137,7 @@ ILibraryAppletCreator::ILibraryAppletCreator(Core::System& system_)
{2, nullptr, "AreAnyLibraryAppletsLeft"},
{10, &ILibraryAppletCreator::CreateStorage, "CreateStorage"},
{11, &ILibraryAppletCreator::CreateTransferMemoryStorage, "CreateTransferMemoryStorage"},
- {12, nullptr, "CreateHandleStorage"},
+ {12, &ILibraryAppletCreator::CreateHandleStorage, "CreateHandleStorage"},
};
RegisterHandlers(functions);
}
@@ -1134,14 +1146,15 @@ ILibraryAppletCreator::~ILibraryAppletCreator() = default;
void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
+
const auto applet_id = rp.PopRaw<Applets::AppletId>();
- const auto applet_mode = rp.PopRaw<u32>();
+ const auto applet_mode = rp.PopRaw<Applets::LibraryAppletMode>();
LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}", applet_id,
applet_mode);
const auto& applet_manager{system.GetAppletManager()};
- const auto applet = applet_manager.GetApplet(applet_id);
+ const auto applet = applet_manager.GetApplet(applet_id, applet_mode);
if (applet == nullptr) {
LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", applet_id);
@@ -1159,9 +1172,18 @@ void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx)
void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- const u64 size{rp.Pop<u64>()};
+
+ const s64 size{rp.Pop<s64>()};
+
LOG_DEBUG(Service_AM, "called, size={}", size);
+ if (size <= 0) {
+ LOG_ERROR(Service_AM, "size is less than or equal to 0");
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_UNKNOWN);
+ return;
+ }
+
std::vector<u8> buffer(size);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
@@ -1170,18 +1192,65 @@ void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) {
}
void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx) {
- LOG_DEBUG(Service_AM, "called");
+ IPC::RequestParser rp{ctx};
+
+ struct Parameters {
+ u8 permissions;
+ s64 size;
+ };
+
+ const auto parameters{rp.PopRaw<Parameters>()};
+ const auto handle{ctx.GetCopyHandle(0)};
+ LOG_DEBUG(Service_AM, "called, permissions={}, size={}, handle={:08X}", parameters.permissions,
+ parameters.size, handle);
+
+ if (parameters.size <= 0) {
+ LOG_ERROR(Service_AM, "size is less than or equal to 0");
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_UNKNOWN);
+ return;
+ }
+
+ auto transfer_mem =
+ system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(handle);
+
+ if (transfer_mem == nullptr) {
+ LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_UNKNOWN);
+ return;
+ }
+
+ const u8* const mem_begin = transfer_mem->GetPointer();
+ const u8* const mem_end = mem_begin + transfer_mem->GetSize();
+ std::vector<u8> memory{mem_begin, mem_end};
+
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IStorage>(system, std::move(memory));
+}
+
+void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- rp.SetCurrentOffset(3);
- const auto handle{rp.Pop<Kernel::Handle>()};
+ const s64 size{rp.Pop<s64>()};
+ const auto handle{ctx.GetCopyHandle(0)};
+
+ LOG_DEBUG(Service_AM, "called, size={}, handle={:08X}", size, handle);
+
+ if (size <= 0) {
+ LOG_ERROR(Service_AM, "size is less than or equal to 0");
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_UNKNOWN);
+ return;
+ }
auto transfer_mem =
system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(handle);
if (transfer_mem == nullptr) {
- LOG_ERROR(Service_AM, "shared_mem is a nullpr for handle={:08X}", handle);
+ LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_UNKNOWN);
return;
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index f6a453ab7..5d302e155 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -61,8 +61,9 @@ public:
void PushMessage(AppletMessage msg);
AppletMessage PopMessage();
std::size_t GetMessageCount() const;
- void OperationModeChanged();
void RequestExit();
+ void FocusStateChanged();
+ void OperationModeChanged();
private:
std::queue<AppletMessage> messages;
@@ -195,6 +196,7 @@ private:
void EndVrModeEx(Kernel::HLERequestContext& ctx);
void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx);
void SetCpuBoostMode(Kernel::HLERequestContext& ctx);
+ void SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(Kernel::HLERequestContext& ctx);
std::shared_ptr<AppletMessageQueue> msg_queue;
bool vr_mode_state{};
@@ -254,6 +256,7 @@ private:
void CreateLibraryApplet(Kernel::HLERequestContext& ctx);
void CreateStorage(Kernel::HLERequestContext& ctx);
void CreateTransferMemoryStorage(Kernel::HLERequestContext& ctx);
+ void CreateHandleStorage(Kernel::HLERequestContext& ctx);
};
class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp
index e2f3b7563..a56df6a7e 100644
--- a/src/core/hle/service/am/applets/applets.cpp
+++ b/src/core/hle/service/am/applets/applets.cpp
@@ -17,6 +17,8 @@
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/server_session.h"
#include "core/hle/service/am/am.h"
+#include "core/hle/service/am/applet_ae.h"
+#include "core/hle/service/am/applet_oe.h"
#include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/am/applets/controller.h"
#include "core/hle/service/am/applets/error.h"
@@ -24,17 +26,20 @@
#include "core/hle/service/am/applets/profile_select.h"
#include "core/hle/service/am/applets/software_keyboard.h"
#include "core/hle/service/am/applets/web_browser.h"
+#include "core/hle/service/sm/sm.h"
namespace Service::AM::Applets {
-AppletDataBroker::AppletDataBroker(Kernel::KernelCore& kernel) {
+AppletDataBroker::AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_)
+ : system{system_}, applet_mode{applet_mode_} {
state_changed_event =
- Kernel::KEvent::Create(kernel, "ILibraryAppletAccessor:StateChangedEvent");
+ Kernel::KEvent::Create(system.Kernel(), "ILibraryAppletAccessor:StateChangedEvent");
state_changed_event->Initialize();
- pop_out_data_event = Kernel::KEvent::Create(kernel, "ILibraryAppletAccessor:PopDataOutEvent");
+ pop_out_data_event =
+ Kernel::KEvent::Create(system.Kernel(), "ILibraryAppletAccessor:PopDataOutEvent");
pop_out_data_event->Initialize();
- pop_interactive_out_data_event =
- Kernel::KEvent::Create(kernel, "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
+ pop_interactive_out_data_event = Kernel::KEvent::Create(
+ system.Kernel(), "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
pop_interactive_out_data_event->Initialize();
}
@@ -114,6 +119,27 @@ void AppletDataBroker::PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&&
void AppletDataBroker::SignalStateChanged() const {
state_changed_event->GetWritableEvent()->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;
+ }
}
std::shared_ptr<Kernel::KReadableEvent> AppletDataBroker::GetNormalDataEvent() const {
@@ -128,7 +154,8 @@ std::shared_ptr<Kernel::KReadableEvent> AppletDataBroker::GetStateChangedEvent()
return state_changed_event->GetReadableEvent();
}
-Applet::Applet(Kernel::KernelCore& kernel_) : broker{kernel_} {}
+Applet::Applet(Core::System& system_, LibraryAppletMode applet_mode_)
+ : broker{system_, applet_mode_}, applet_mode{applet_mode_} {}
Applet::~Applet() = default;
@@ -241,31 +268,31 @@ void AppletManager::ClearAll() {
frontend = {};
}
-std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id) const {
+std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id, LibraryAppletMode mode) const {
switch (id) {
case AppletId::Auth:
- return std::make_shared<Auth>(system, *frontend.parental_controls);
+ return std::make_shared<Auth>(system, mode, *frontend.parental_controls);
case AppletId::Controller:
- return std::make_shared<Controller>(system, *frontend.controller);
+ return std::make_shared<Controller>(system, mode, *frontend.controller);
case AppletId::Error:
- return std::make_shared<Error>(system, *frontend.error);
+ return std::make_shared<Error>(system, mode, *frontend.error);
case AppletId::ProfileSelect:
- return std::make_shared<ProfileSelect>(system, *frontend.profile_select);
+ return std::make_shared<ProfileSelect>(system, mode, *frontend.profile_select);
case AppletId::SoftwareKeyboard:
- return std::make_shared<SoftwareKeyboard>(system, *frontend.software_keyboard);
+ return std::make_shared<SoftwareKeyboard>(system, mode, *frontend.software_keyboard);
case AppletId::Web:
case AppletId::Shop:
case AppletId::OfflineWeb:
case AppletId::LoginShare:
case AppletId::WebAuth:
- return std::make_shared<WebBrowser>(system, *frontend.web_browser);
+ return std::make_shared<WebBrowser>(system, mode, *frontend.web_browser);
case AppletId::PhotoViewer:
- return std::make_shared<PhotoViewer>(system, *frontend.photo_viewer);
+ 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);
+ return std::make_shared<StubApplet>(system, id, mode);
}
}
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index b9a006317..4215d2232 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -62,9 +62,17 @@ enum class AppletId : u32 {
MyPage = 0x1A,
};
+enum class LibraryAppletMode : u32 {
+ AllForeground = 0,
+ Background = 1,
+ NoUI = 2,
+ BackgroundIndirectDisplay = 3,
+ AllForegroundInitiallyHidden = 4,
+};
+
class AppletDataBroker final {
public:
- explicit AppletDataBroker(Kernel::KernelCore& kernel_);
+ explicit AppletDataBroker(Core::System& system_, LibraryAppletMode applet_mode_);
~AppletDataBroker();
struct RawChannelData {
@@ -94,6 +102,9 @@ public:
std::shared_ptr<Kernel::KReadableEvent> GetStateChangedEvent() const;
private:
+ Core::System& system;
+ LibraryAppletMode applet_mode;
+
// Queues are named from applet's perspective
// PopNormalDataToApplet and PushNormalDataFromGame
@@ -119,7 +130,7 @@ private:
class Applet {
public:
- explicit Applet(Kernel::KernelCore& kernel_);
+ explicit Applet(Core::System& system_, LibraryAppletMode applet_mode_);
virtual ~Applet();
virtual void Initialize();
@@ -129,10 +140,6 @@ public:
virtual void ExecuteInteractive() = 0;
virtual void Execute() = 0;
- bool IsInitialized() const {
- return initialized;
- }
-
AppletDataBroker& GetBroker() {
return broker;
}
@@ -141,6 +148,14 @@ public:
return broker;
}
+ LibraryAppletMode GetLibraryAppletMode() const {
+ return applet_mode;
+ }
+
+ bool IsInitialized() const {
+ return initialized;
+ }
+
protected:
struct CommonArguments {
u32_le arguments_version;
@@ -154,6 +169,7 @@ protected:
CommonArguments common_args{};
AppletDataBroker broker;
+ LibraryAppletMode applet_mode;
bool initialized = false;
};
@@ -200,7 +216,7 @@ public:
void SetDefaultAppletsIfMissing();
void ClearAll();
- std::shared_ptr<Applet> GetApplet(AppletId id) const;
+ std::shared_ptr<Applet> GetApplet(AppletId id, LibraryAppletMode mode) const;
private:
AppletFrontendSet frontend;
diff --git a/src/core/hle/service/am/applets/controller.cpp b/src/core/hle/service/am/applets/controller.cpp
index c2bfe698f..218c8d1e4 100644
--- a/src/core/hle/service/am/applets/controller.cpp
+++ b/src/core/hle/service/am/applets/controller.cpp
@@ -45,8 +45,9 @@ static Core::Frontend::ControllerParameters ConvertToFrontendParameters(
};
}
-Controller::Controller(Core::System& system_, const Core::Frontend::ControllerApplet& frontend_)
- : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {}
+Controller::Controller(Core::System& system_, LibraryAppletMode applet_mode_,
+ const Core::Frontend::ControllerApplet& frontend_)
+ : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
Controller::~Controller() = default;
diff --git a/src/core/hle/service/am/applets/controller.h b/src/core/hle/service/am/applets/controller.h
index d4c9da7b1..2d4dae0bd 100644
--- a/src/core/hle/service/am/applets/controller.h
+++ b/src/core/hle/service/am/applets/controller.h
@@ -106,7 +106,8 @@ static_assert(sizeof(ControllerSupportResultInfo) == 0xC,
class Controller final : public Applet {
public:
- explicit Controller(Core::System& system_, const Core::Frontend::ControllerApplet& frontend_);
+ explicit Controller(Core::System& system_, LibraryAppletMode applet_mode_,
+ const Core::Frontend::ControllerApplet& frontend_);
~Controller() override;
void Initialize() override;
diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp
index 0c8b632e8..23e30aa45 100644
--- a/src/core/hle/service/am/applets/error.cpp
+++ b/src/core/hle/service/am/applets/error.cpp
@@ -86,8 +86,9 @@ ResultCode Decode64BitError(u64 error) {
} // Anonymous namespace
-Error::Error(Core::System& system_, const Core::Frontend::ErrorApplet& frontend_)
- : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {}
+Error::Error(Core::System& system_, LibraryAppletMode applet_mode_,
+ const Core::Frontend::ErrorApplet& frontend_)
+ : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
Error::~Error() = default;
diff --git a/src/core/hle/service/am/applets/error.h b/src/core/hle/service/am/applets/error.h
index a105cdb0c..e606d12ce 100644
--- a/src/core/hle/service/am/applets/error.h
+++ b/src/core/hle/service/am/applets/error.h
@@ -25,7 +25,8 @@ enum class ErrorAppletMode : u8 {
class Error final : public Applet {
public:
- explicit Error(Core::System& system_, const Core::Frontend::ErrorApplet& frontend_);
+ explicit Error(Core::System& system_, LibraryAppletMode applet_mode_,
+ const Core::Frontend::ErrorApplet& frontend_);
~Error() override;
void Initialize() override;
diff --git a/src/core/hle/service/am/applets/general_backend.cpp b/src/core/hle/service/am/applets/general_backend.cpp
index 4d1df5cbe..b26abad36 100644
--- a/src/core/hle/service/am/applets/general_backend.cpp
+++ b/src/core/hle/service/am/applets/general_backend.cpp
@@ -37,8 +37,9 @@ static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix)
}
}
-Auth::Auth(Core::System& system_, Core::Frontend::ParentalControlsApplet& frontend_)
- : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {}
+Auth::Auth(Core::System& system_, LibraryAppletMode applet_mode_,
+ Core::Frontend::ParentalControlsApplet& frontend_)
+ : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
Auth::~Auth() = default;
@@ -152,8 +153,9 @@ void Auth::AuthFinished(bool is_successful) {
broker.SignalStateChanged();
}
-PhotoViewer::PhotoViewer(Core::System& system_, const Core::Frontend::PhotoViewerApplet& frontend_)
- : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {}
+PhotoViewer::PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_,
+ const Core::Frontend::PhotoViewerApplet& frontend_)
+ : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
PhotoViewer::~PhotoViewer() = default;
@@ -202,8 +204,8 @@ void PhotoViewer::ViewFinished() {
broker.SignalStateChanged();
}
-StubApplet::StubApplet(Core::System& system_, AppletId id_)
- : Applet{system_.Kernel()}, id{id_}, system{system_} {}
+StubApplet::StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_)
+ : Applet{system_, applet_mode_}, id{id_}, system{system_} {}
StubApplet::~StubApplet() = default;
diff --git a/src/core/hle/service/am/applets/general_backend.h b/src/core/hle/service/am/applets/general_backend.h
index ba76ae3d3..7496ded88 100644
--- a/src/core/hle/service/am/applets/general_backend.h
+++ b/src/core/hle/service/am/applets/general_backend.h
@@ -20,7 +20,8 @@ enum class AuthAppletType : u32 {
class Auth final : public Applet {
public:
- explicit Auth(Core::System& system_, Core::Frontend::ParentalControlsApplet& frontend_);
+ explicit Auth(Core::System& system_, LibraryAppletMode applet_mode_,
+ Core::Frontend::ParentalControlsApplet& frontend_);
~Auth() override;
void Initialize() override;
@@ -50,7 +51,8 @@ enum class PhotoViewerAppletMode : u8 {
class PhotoViewer final : public Applet {
public:
- explicit PhotoViewer(Core::System& system_, const Core::Frontend::PhotoViewerApplet& frontend_);
+ explicit PhotoViewer(Core::System& system_, LibraryAppletMode applet_mode_,
+ const Core::Frontend::PhotoViewerApplet& frontend_);
~PhotoViewer() override;
void Initialize() override;
@@ -70,7 +72,7 @@ private:
class StubApplet final : public Applet {
public:
- explicit StubApplet(Core::System& system_, AppletId id_);
+ explicit StubApplet(Core::System& system_, AppletId id_, LibraryAppletMode applet_mode_);
~StubApplet() override;
void Initialize() override;
diff --git a/src/core/hle/service/am/applets/profile_select.cpp b/src/core/hle/service/am/applets/profile_select.cpp
index 77fba16c7..c91a9776a 100644
--- a/src/core/hle/service/am/applets/profile_select.cpp
+++ b/src/core/hle/service/am/applets/profile_select.cpp
@@ -15,9 +15,9 @@ namespace Service::AM::Applets {
constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1};
-ProfileSelect::ProfileSelect(Core::System& system_,
+ProfileSelect::ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_,
const Core::Frontend::ProfileSelectApplet& frontend_)
- : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {}
+ : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
ProfileSelect::~ProfileSelect() = default;
diff --git a/src/core/hle/service/am/applets/profile_select.h b/src/core/hle/service/am/applets/profile_select.h
index 648d33a24..f0dd6c1f3 100644
--- a/src/core/hle/service/am/applets/profile_select.h
+++ b/src/core/hle/service/am/applets/profile_select.h
@@ -33,7 +33,7 @@ static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has inco
class ProfileSelect final : public Applet {
public:
- explicit ProfileSelect(Core::System& system_,
+ explicit ProfileSelect(Core::System& system_, LibraryAppletMode applet_mode_,
const Core::Frontend::ProfileSelectApplet& frontend_);
~ProfileSelect() override;
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp
index 79b209c6b..73a06def1 100644
--- a/src/core/hle/service/am/applets/software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/software_keyboard.cpp
@@ -1,93 +1,80 @@
-// Copyright 2018 yuzu emulator team
+// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <cstring>
-#include "common/assert.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/frontend/applets/software_keyboard.h"
-#include "core/hle/result.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applets/software_keyboard.h"
namespace Service::AM::Applets {
namespace {
-enum class Request : u32 {
- Finalize = 0x4,
- SetUserWordInfo = 0x6,
- SetCustomizeDic = 0x7,
- Calc = 0xa,
- SetCustomizedDictionaries = 0xb,
- UnsetCustomizedDictionaries = 0xc,
- UnknownD = 0xd,
- UnknownE = 0xe,
-};
-constexpr std::size_t SWKBD_INLINE_INIT_SIZE = 0x8;
-constexpr std::size_t SWKBD_OUTPUT_BUFFER_SIZE = 0x7D8;
-constexpr std::size_t SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE = 0x7D4;
-constexpr std::size_t DEFAULT_MAX_LENGTH = 500;
-constexpr bool INTERACTIVE_STATUS_OK = false;
+
+// The maximum number of UTF-16 characters that can be input into the swkbd text field.
+constexpr u32 DEFAULT_MAX_TEXT_LENGTH = 500;
+
+constexpr std::size_t REPLY_BASE_SIZE = sizeof(SwkbdState) + sizeof(SwkbdReplyType);
+constexpr std::size_t REPLY_UTF8_SIZE = 0x7D4;
+constexpr std::size_t REPLY_UTF16_SIZE = 0x3EC;
+
+constexpr const char* GetTextCheckResultName(SwkbdTextCheckResult text_check_result) {
+ switch (text_check_result) {
+ case SwkbdTextCheckResult::Success:
+ return "Success";
+ case SwkbdTextCheckResult::Failure:
+ return "Failure";
+ case SwkbdTextCheckResult::Confirm:
+ return "Confirm";
+ case SwkbdTextCheckResult::Silent:
+ return "Silent";
+ default:
+ UNIMPLEMENTED_MSG("Unknown TextCheckResult={}", text_check_result);
+ return "Unknown";
+ }
+}
+
+void SetReplyBase(std::vector<u8>& reply, SwkbdState state, SwkbdReplyType reply_type) {
+ std::memcpy(reply.data(), &state, sizeof(SwkbdState));
+ std::memcpy(reply.data() + sizeof(SwkbdState), &reply_type, sizeof(SwkbdReplyType));
+}
+
} // Anonymous namespace
-static Core::Frontend::SoftwareKeyboardParameters ConvertToFrontendParameters(
- KeyboardConfig config, std::u16string initial_text) {
- Core::Frontend::SoftwareKeyboardParameters params{};
-
- params.submit_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
- config.submit_text.data(), config.submit_text.size());
- params.header_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
- config.header_text.data(), config.header_text.size());
- params.sub_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(config.sub_text.data(),
- config.sub_text.size());
- params.guide_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(config.guide_text.data(),
- config.guide_text.size());
- params.initial_text = std::move(initial_text);
- params.max_length = config.length_limit == 0 ? DEFAULT_MAX_LENGTH : config.length_limit;
- params.password = static_cast<bool>(config.is_password);
- params.cursor_at_beginning = static_cast<bool>(config.initial_cursor_position);
- params.value = static_cast<u8>(config.keyset_disable_bitmask);
-
- return params;
-}
-
-SoftwareKeyboard::SoftwareKeyboard(Core::System& system_,
- const Core::Frontend::SoftwareKeyboardApplet& frontend_)
- : Applet{system_.Kernel()}, frontend{frontend_}, system{system_} {}
+
+SoftwareKeyboard::SoftwareKeyboard(Core::System& system_, LibraryAppletMode applet_mode_,
+ Core::Frontend::SoftwareKeyboardApplet& frontend_)
+ : Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
SoftwareKeyboard::~SoftwareKeyboard() = default;
void SoftwareKeyboard::Initialize() {
- complete = false;
- is_inline = false;
- initial_text.clear();
- final_data.clear();
-
Applet::Initialize();
- const auto keyboard_config_storage = broker.PopNormalDataToApplet();
- ASSERT(keyboard_config_storage != nullptr);
- const auto& keyboard_config = keyboard_config_storage->GetData();
-
- if (keyboard_config.size() == SWKBD_INLINE_INIT_SIZE) {
- is_inline = true;
- return;
- }
-
- ASSERT(keyboard_config.size() >= sizeof(KeyboardConfig));
- std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig));
+ LOG_INFO(Service_AM, "Initializing Software Keyboard Applet with LibraryAppletMode={}",
+ applet_mode);
- const auto work_buffer_storage = broker.PopNormalDataToApplet();
- ASSERT_OR_EXECUTE(work_buffer_storage != nullptr, { return; });
- const auto& work_buffer = work_buffer_storage->GetData();
+ LOG_DEBUG(Service_AM,
+ "Initializing Applet with common_args: arg_version={}, lib_version={}, "
+ "play_startup_sound={}, size={}, system_tick={}, theme_color={}",
+ common_args.arguments_version, common_args.library_version,
+ common_args.play_startup_sound, common_args.size, common_args.system_tick,
+ common_args.theme_color);
- if (config.initial_string_size == 0)
- return;
+ swkbd_applet_version = SwkbdAppletVersion{common_args.library_version};
- std::vector<char16_t> string(config.initial_string_size);
- std::memcpy(string.data(), work_buffer.data() + config.initial_string_offset,
- string.size() * 2);
- initial_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size());
+ switch (applet_mode) {
+ case LibraryAppletMode::AllForeground:
+ InitializeForeground();
+ break;
+ case LibraryAppletMode::Background:
+ case LibraryAppletMode::BackgroundIndirectDisplay:
+ InitializeBackground(applet_mode);
+ break;
+ default:
+ UNREACHABLE_MSG("Invalid LibraryAppletMode={}", applet_mode);
+ break;
+ }
}
bool SoftwareKeyboard::TransactionComplete() const {
@@ -95,106 +82,996 @@ bool SoftwareKeyboard::TransactionComplete() const {
}
ResultCode SoftwareKeyboard::GetStatus() const {
- return RESULT_SUCCESS;
+ return status;
}
void SoftwareKeyboard::ExecuteInteractive() {
- if (complete)
+ if (complete) {
return;
+ }
- const auto storage = broker.PopInteractiveDataToApplet();
- ASSERT(storage != nullptr);
- const auto data = storage->GetData();
- if (!is_inline) {
- const auto status = static_cast<bool>(data[0]);
- if (status == INTERACTIVE_STATUS_OK) {
- complete = true;
- } else {
- std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string;
- std::memcpy(string.data(), data.data() + 4, string.size() * 2);
- frontend.SendTextCheckDialog(
- Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()),
- [this] { broker.SignalStateChanged(); });
- }
+ if (is_background) {
+ ProcessInlineKeyboardRequest();
} else {
- Request request{};
- std::memcpy(&request, data.data(), sizeof(Request));
+ ProcessTextCheck();
+ }
+}
+
+void SoftwareKeyboard::Execute() {
+ if (complete) {
+ return;
+ }
+
+ if (is_background) {
+ return;
+ }
+
+ ShowNormalKeyboard();
+}
- switch (request) {
- case Request::Finalize:
- complete = true;
- broker.SignalStateChanged();
+void SoftwareKeyboard::SubmitTextNormal(SwkbdResult result, std::u16string submitted_text) {
+ if (complete) {
+ return;
+ }
+
+ if (swkbd_config_common.use_text_check && result == SwkbdResult::Ok) {
+ SubmitForTextCheck(submitted_text);
+ } else {
+ SubmitNormalOutputAndExit(result, submitted_text);
+ }
+}
+
+void SoftwareKeyboard::SubmitTextInline(SwkbdReplyType reply_type, std::u16string submitted_text,
+ s32 cursor_position) {
+ if (complete) {
+ return;
+ }
+
+ current_text = std::move(submitted_text);
+ current_cursor_position = cursor_position;
+
+ if (inline_use_utf8) {
+ switch (reply_type) {
+ case SwkbdReplyType::ChangedString:
+ reply_type = SwkbdReplyType::ChangedStringUtf8;
break;
- case Request::Calc: {
- broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::vector<u8>{1}));
- broker.SignalStateChanged();
+ case SwkbdReplyType::MovedCursor:
+ reply_type = SwkbdReplyType::MovedCursorUtf8;
+ break;
+ case SwkbdReplyType::DecidedEnter:
+ reply_type = SwkbdReplyType::DecidedEnterUtf8;
+ break;
+ default:
break;
}
+ }
+
+ if (use_changed_string_v2) {
+ switch (reply_type) {
+ case SwkbdReplyType::ChangedString:
+ reply_type = SwkbdReplyType::ChangedStringV2;
+ break;
+ case SwkbdReplyType::ChangedStringUtf8:
+ reply_type = SwkbdReplyType::ChangedStringUtf8V2;
+ break;
default:
- UNIMPLEMENTED_MSG("Request {:X} is not implemented", request);
break;
}
}
+
+ if (use_moved_cursor_v2) {
+ switch (reply_type) {
+ case SwkbdReplyType::MovedCursor:
+ reply_type = SwkbdReplyType::MovedCursorV2;
+ break;
+ case SwkbdReplyType::MovedCursorUtf8:
+ reply_type = SwkbdReplyType::MovedCursorUtf8V2;
+ break;
+ default:
+ break;
+ }
+ }
+
+ SendReply(reply_type);
}
-void SoftwareKeyboard::Execute() {
- if (complete) {
- broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(final_data)));
- broker.SignalStateChanged();
+void SoftwareKeyboard::InitializeForeground() {
+ LOG_INFO(Service_AM, "Initializing Normal Software Keyboard Applet.");
+
+ is_background = false;
+
+ const auto swkbd_config_storage = broker.PopNormalDataToApplet();
+ ASSERT(swkbd_config_storage != nullptr);
+
+ const auto& swkbd_config_data = swkbd_config_storage->GetData();
+ ASSERT(swkbd_config_data.size() >= sizeof(SwkbdConfigCommon));
+
+ std::memcpy(&swkbd_config_common, swkbd_config_data.data(), sizeof(SwkbdConfigCommon));
+
+ switch (swkbd_applet_version) {
+ case SwkbdAppletVersion::Version5:
+ case SwkbdAppletVersion::Version65542:
+ ASSERT(swkbd_config_data.size() == sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigOld));
+ std::memcpy(&swkbd_config_old, swkbd_config_data.data() + sizeof(SwkbdConfigCommon),
+ sizeof(SwkbdConfigOld));
+ break;
+ case SwkbdAppletVersion::Version196615:
+ case SwkbdAppletVersion::Version262152:
+ case SwkbdAppletVersion::Version327689:
+ ASSERT(swkbd_config_data.size() == sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigOld2));
+ std::memcpy(&swkbd_config_old2, swkbd_config_data.data() + sizeof(SwkbdConfigCommon),
+ sizeof(SwkbdConfigOld2));
+ break;
+ case SwkbdAppletVersion::Version393227:
+ case SwkbdAppletVersion::Version524301:
+ ASSERT(swkbd_config_data.size() == sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigNew));
+ std::memcpy(&swkbd_config_new, swkbd_config_data.data() + sizeof(SwkbdConfigCommon),
+ sizeof(SwkbdConfigNew));
+ break;
+ default:
+ UNIMPLEMENTED_MSG("Unknown SwkbdConfig revision={} with size={}", swkbd_applet_version,
+ swkbd_config_data.size());
+ ASSERT(swkbd_config_data.size() >= sizeof(SwkbdConfigCommon) + sizeof(SwkbdConfigNew));
+ std::memcpy(&swkbd_config_new, swkbd_config_data.data() + sizeof(SwkbdConfigCommon),
+ sizeof(SwkbdConfigNew));
+ break;
+ }
+
+ const auto work_buffer_storage = broker.PopNormalDataToApplet();
+ ASSERT(work_buffer_storage != nullptr);
+
+ if (swkbd_config_common.initial_string_length == 0) {
+ InitializeFrontendKeyboard();
return;
}
- const auto parameters = ConvertToFrontendParameters(config, initial_text);
- if (!is_inline) {
- frontend.RequestText(
- [this](std::optional<std::u16string> text) { WriteText(std::move(text)); }, parameters);
+ const auto& work_buffer = work_buffer_storage->GetData();
+
+ std::vector<char16_t> initial_string(swkbd_config_common.initial_string_length);
+
+ std::memcpy(initial_string.data(),
+ work_buffer.data() + swkbd_config_common.initial_string_offset,
+ swkbd_config_common.initial_string_length * sizeof(char16_t));
+
+ initial_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(initial_string.data(),
+ initial_string.size());
+
+ LOG_DEBUG(Service_AM, "\nInitial Text: {}", Common::UTF16ToUTF8(initial_text));
+
+ InitializeFrontendKeyboard();
+}
+
+void SoftwareKeyboard::InitializeBackground(LibraryAppletMode applet_mode) {
+ LOG_INFO(Service_AM, "Initializing Inline Software Keyboard Applet.");
+
+ is_background = true;
+
+ const auto swkbd_inline_initialize_arg_storage = broker.PopNormalDataToApplet();
+ ASSERT(swkbd_inline_initialize_arg_storage != nullptr);
+
+ const auto& swkbd_inline_initialize_arg = swkbd_inline_initialize_arg_storage->GetData();
+ ASSERT(swkbd_inline_initialize_arg.size() == sizeof(SwkbdInitializeArg));
+
+ std::memcpy(&swkbd_initialize_arg, swkbd_inline_initialize_arg.data(),
+ swkbd_inline_initialize_arg.size());
+
+ if (swkbd_initialize_arg.library_applet_mode_flag) {
+ ASSERT(applet_mode == LibraryAppletMode::Background);
+ } else {
+ ASSERT(applet_mode == LibraryAppletMode::BackgroundIndirectDisplay);
+ }
+}
+
+void SoftwareKeyboard::ProcessTextCheck() {
+ const auto text_check_storage = broker.PopInteractiveDataToApplet();
+ ASSERT(text_check_storage != nullptr);
+
+ const auto& text_check_data = text_check_storage->GetData();
+ ASSERT(text_check_data.size() == sizeof(SwkbdTextCheck));
+
+ SwkbdTextCheck swkbd_text_check;
+
+ std::memcpy(&swkbd_text_check, text_check_data.data(), sizeof(SwkbdTextCheck));
+
+ std::u16string text_check_message = Common::UTF16StringFromFixedZeroTerminatedBuffer(
+ swkbd_text_check.text_check_message.data(), swkbd_text_check.text_check_message.size());
+
+ LOG_INFO(Service_AM, "\nTextCheckResult: {}\nTextCheckMessage: {}",
+ GetTextCheckResultName(swkbd_text_check.text_check_result),
+ Common::UTF16ToUTF8(text_check_message));
+
+ switch (swkbd_text_check.text_check_result) {
+ case SwkbdTextCheckResult::Success:
+ SubmitNormalOutputAndExit(SwkbdResult::Ok, current_text);
+ break;
+ case SwkbdTextCheckResult::Failure:
+ ShowTextCheckDialog(SwkbdTextCheckResult::Failure, text_check_message);
+ break;
+ case SwkbdTextCheckResult::Confirm:
+ ShowTextCheckDialog(SwkbdTextCheckResult::Confirm, text_check_message);
+ break;
+ case SwkbdTextCheckResult::Silent:
+ default:
+ break;
}
}
-void SoftwareKeyboard::WriteText(std::optional<std::u16string> text) {
- std::vector<u8> output_main(SWKBD_OUTPUT_BUFFER_SIZE);
+void SoftwareKeyboard::ProcessInlineKeyboardRequest() {
+ const auto request_data_storage = broker.PopInteractiveDataToApplet();
+ ASSERT(request_data_storage != nullptr);
+
+ const auto& request_data = request_data_storage->GetData();
+ ASSERT(request_data.size() >= sizeof(SwkbdRequestCommand));
- if (text.has_value()) {
- std::vector<u8> output_sub(SWKBD_OUTPUT_BUFFER_SIZE);
+ SwkbdRequestCommand request_command;
- if (config.utf_8) {
- const u64 size = text->size() + sizeof(u64);
- const auto new_text = Common::UTF16ToUTF8(*text);
+ std::memcpy(&request_command, request_data.data(), sizeof(SwkbdRequestCommand));
- std::memcpy(output_sub.data(), &size, sizeof(u64));
- std::memcpy(output_sub.data() + 8, new_text.data(),
- std::min(new_text.size(), SWKBD_OUTPUT_BUFFER_SIZE - 8));
+ switch (request_command) {
+ case SwkbdRequestCommand::Finalize:
+ RequestFinalize(request_data);
+ break;
+ case SwkbdRequestCommand::SetUserWordInfo:
+ RequestSetUserWordInfo(request_data);
+ break;
+ case SwkbdRequestCommand::SetCustomizeDic:
+ RequestSetCustomizeDic(request_data);
+ break;
+ case SwkbdRequestCommand::Calc:
+ RequestCalc(request_data);
+ break;
+ case SwkbdRequestCommand::SetCustomizedDictionaries:
+ RequestSetCustomizedDictionaries(request_data);
+ break;
+ case SwkbdRequestCommand::UnsetCustomizedDictionaries:
+ RequestUnsetCustomizedDictionaries(request_data);
+ break;
+ case SwkbdRequestCommand::SetChangedStringV2Flag:
+ RequestSetChangedStringV2Flag(request_data);
+ break;
+ case SwkbdRequestCommand::SetMovedCursorV2Flag:
+ RequestSetMovedCursorV2Flag(request_data);
+ break;
+ default:
+ UNIMPLEMENTED_MSG("Unknown SwkbdRequestCommand={}", request_command);
+ break;
+ }
+}
- output_main[0] = INTERACTIVE_STATUS_OK;
- std::memcpy(output_main.data() + 4, new_text.data(),
- std::min(new_text.size(), SWKBD_OUTPUT_BUFFER_SIZE - 4));
- } else {
- const u64 size = text->size() * 2 + sizeof(u64);
- std::memcpy(output_sub.data(), &size, sizeof(u64));
- std::memcpy(output_sub.data() + 8, text->data(),
- std::min(text->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 8));
+void SoftwareKeyboard::SubmitNormalOutputAndExit(SwkbdResult result,
+ std::u16string submitted_text) {
+ std::vector<u8> out_data(sizeof(SwkbdResult) + STRING_BUFFER_SIZE);
- output_main[0] = INTERACTIVE_STATUS_OK;
- std::memcpy(output_main.data() + 4, text->data(),
- std::min(text->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 4));
- }
+ if (swkbd_config_common.use_utf8) {
+ std::string utf8_submitted_text = Common::UTF16ToUTF8(submitted_text);
- complete = !config.text_check;
- final_data = output_main;
+ LOG_DEBUG(Service_AM, "\nSwkbdResult: {}\nUTF-8 Submitted Text: {}", result,
+ utf8_submitted_text);
- if (complete) {
- broker.PushNormalDataFromApplet(
- std::make_shared<IStorage>(system, std::move(output_main)));
- broker.SignalStateChanged();
- } else {
- broker.PushInteractiveDataFromApplet(
- std::make_shared<IStorage>(system, std::move(output_sub)));
- }
+ std::memcpy(out_data.data(), &result, sizeof(SwkbdResult));
+ std::memcpy(out_data.data() + sizeof(SwkbdResult), utf8_submitted_text.data(),
+ utf8_submitted_text.size());
} else {
- output_main[0] = 1;
- complete = true;
- broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(output_main)));
- broker.SignalStateChanged();
+ LOG_DEBUG(Service_AM, "\nSwkbdResult: {}\nUTF-16 Submitted Text: {}", result,
+ Common::UTF16ToUTF8(submitted_text));
+
+ std::memcpy(out_data.data(), &result, sizeof(SwkbdResult));
+ std::memcpy(out_data.data() + sizeof(SwkbdResult), submitted_text.data(),
+ submitted_text.size() * sizeof(char16_t));
+ }
+
+ broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
+
+ ExitKeyboard();
+}
+
+void SoftwareKeyboard::SubmitForTextCheck(std::u16string submitted_text) {
+ current_text = std::move(submitted_text);
+
+ std::vector<u8> out_data(sizeof(u64) + STRING_BUFFER_SIZE);
+
+ if (swkbd_config_common.use_utf8) {
+ std::string utf8_submitted_text = Common::UTF16ToUTF8(current_text);
+ const u64 buffer_size = sizeof(u64) + utf8_submitted_text.size();
+
+ LOG_DEBUG(Service_AM, "\nBuffer Size: {}\nUTF-8 Submitted Text: {}", buffer_size,
+ utf8_submitted_text);
+
+ std::memcpy(out_data.data(), &buffer_size, sizeof(u64));
+ std::memcpy(out_data.data() + sizeof(u64), utf8_submitted_text.data(),
+ utf8_submitted_text.size());
+ } else {
+ const u64 buffer_size = sizeof(u64) + current_text.size() * sizeof(char16_t);
+
+ LOG_DEBUG(Service_AM, "\nBuffer Size: {}\nUTF-16 Submitted Text: {}", buffer_size,
+ Common::UTF16ToUTF8(current_text));
+
+ std::memcpy(out_data.data(), &buffer_size, sizeof(u64));
+ std::memcpy(out_data.data() + sizeof(u64), current_text.data(),
+ current_text.size() * sizeof(char16_t));
+ }
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
+}
+
+void SoftwareKeyboard::SendReply(SwkbdReplyType reply_type) {
+ switch (reply_type) {
+ case SwkbdReplyType::FinishedInitialize:
+ ReplyFinishedInitialize();
+ break;
+ case SwkbdReplyType::Default:
+ ReplyDefault();
+ break;
+ case SwkbdReplyType::ChangedString:
+ ReplyChangedString();
+ break;
+ case SwkbdReplyType::MovedCursor:
+ ReplyMovedCursor();
+ break;
+ case SwkbdReplyType::MovedTab:
+ ReplyMovedTab();
+ break;
+ case SwkbdReplyType::DecidedEnter:
+ ReplyDecidedEnter();
+ break;
+ case SwkbdReplyType::DecidedCancel:
+ ReplyDecidedCancel();
+ break;
+ case SwkbdReplyType::ChangedStringUtf8:
+ ReplyChangedStringUtf8();
+ break;
+ case SwkbdReplyType::MovedCursorUtf8:
+ ReplyMovedCursorUtf8();
+ break;
+ case SwkbdReplyType::DecidedEnterUtf8:
+ ReplyDecidedEnterUtf8();
+ break;
+ case SwkbdReplyType::UnsetCustomizeDic:
+ ReplyUnsetCustomizeDic();
+ break;
+ case SwkbdReplyType::ReleasedUserWordInfo:
+ ReplyReleasedUserWordInfo();
+ break;
+ case SwkbdReplyType::UnsetCustomizedDictionaries:
+ ReplyUnsetCustomizedDictionaries();
+ break;
+ case SwkbdReplyType::ChangedStringV2:
+ ReplyChangedStringV2();
+ break;
+ case SwkbdReplyType::MovedCursorV2:
+ ReplyMovedCursorV2();
+ break;
+ case SwkbdReplyType::ChangedStringUtf8V2:
+ ReplyChangedStringUtf8V2();
+ break;
+ case SwkbdReplyType::MovedCursorUtf8V2:
+ ReplyMovedCursorUtf8V2();
+ break;
+ default:
+ UNIMPLEMENTED_MSG("Unknown SwkbdReplyType={}", reply_type);
+ ReplyDefault();
+ break;
+ }
+}
+
+void SoftwareKeyboard::ChangeState(SwkbdState state) {
+ swkbd_state = state;
+
+ ReplyDefault();
+}
+
+void SoftwareKeyboard::InitializeFrontendKeyboard() {
+ if (is_background) {
+ const auto& appear_arg = swkbd_calc_arg.appear_arg;
+
+ std::u16string ok_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
+ appear_arg.ok_text.data(), appear_arg.ok_text.size());
+
+ const u32 max_text_length =
+ appear_arg.max_text_length > 0 && appear_arg.max_text_length <= DEFAULT_MAX_TEXT_LENGTH
+ ? appear_arg.max_text_length
+ : DEFAULT_MAX_TEXT_LENGTH;
+
+ const u32 min_text_length =
+ appear_arg.min_text_length <= max_text_length ? appear_arg.min_text_length : 0;
+
+ const s32 initial_cursor_position =
+ current_cursor_position > 0 ? current_cursor_position : 0;
+
+ const auto text_draw_type =
+ max_text_length <= 32 ? SwkbdTextDrawType::Line : SwkbdTextDrawType::Box;
+
+ Core::Frontend::KeyboardInitializeParameters initialize_parameters{
+ .ok_text{ok_text},
+ .header_text{},
+ .sub_text{},
+ .guide_text{},
+ .initial_text{current_text},
+ .max_text_length{max_text_length},
+ .min_text_length{min_text_length},
+ .initial_cursor_position{initial_cursor_position},
+ .type{appear_arg.type},
+ .password_mode{SwkbdPasswordMode::Disabled},
+ .text_draw_type{text_draw_type},
+ .key_disable_flags{appear_arg.key_disable_flags},
+ .use_blur_background{false},
+ .enable_backspace_button{swkbd_calc_arg.enable_backspace_button},
+ .enable_return_button{appear_arg.enable_return_button},
+ .disable_cancel_button{appear_arg.disable_cancel_button},
+ };
+
+ frontend.InitializeKeyboard(
+ true, std::move(initialize_parameters), {},
+ [this](SwkbdReplyType reply_type, std::u16string submitted_text, s32 cursor_position) {
+ SubmitTextInline(reply_type, submitted_text, cursor_position);
+ });
+ } else {
+ std::u16string ok_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
+ swkbd_config_common.ok_text.data(), swkbd_config_common.ok_text.size());
+
+ std::u16string header_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
+ swkbd_config_common.header_text.data(), swkbd_config_common.header_text.size());
+
+ std::u16string sub_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
+ swkbd_config_common.sub_text.data(), swkbd_config_common.sub_text.size());
+
+ std::u16string guide_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
+ swkbd_config_common.guide_text.data(), swkbd_config_common.guide_text.size());
+
+ const u32 max_text_length =
+ swkbd_config_common.max_text_length > 0 &&
+ swkbd_config_common.max_text_length <= DEFAULT_MAX_TEXT_LENGTH
+ ? swkbd_config_common.max_text_length
+ : DEFAULT_MAX_TEXT_LENGTH;
+
+ const u32 min_text_length = swkbd_config_common.min_text_length <= max_text_length
+ ? swkbd_config_common.min_text_length
+ : 0;
+
+ const s32 initial_cursor_position = [this] {
+ switch (swkbd_config_common.initial_cursor_position) {
+ case SwkbdInitialCursorPosition::Start:
+ default:
+ return 0;
+ case SwkbdInitialCursorPosition::End:
+ return static_cast<s32>(initial_text.size());
+ }
+ }();
+
+ const auto text_draw_type = [this, max_text_length] {
+ switch (swkbd_config_common.text_draw_type) {
+ case SwkbdTextDrawType::Line:
+ default:
+ return max_text_length <= 32 ? SwkbdTextDrawType::Line : SwkbdTextDrawType::Box;
+ case SwkbdTextDrawType::Box:
+ case SwkbdTextDrawType::DownloadCode:
+ return swkbd_config_common.text_draw_type;
+ }
+ }();
+
+ const auto enable_return_button = text_draw_type == SwkbdTextDrawType::Box
+ ? swkbd_config_common.enable_return_button
+ : false;
+
+ const auto disable_cancel_button = swkbd_applet_version >= SwkbdAppletVersion::Version393227
+ ? swkbd_config_new.disable_cancel_button
+ : false;
+
+ Core::Frontend::KeyboardInitializeParameters initialize_parameters{
+ .ok_text{ok_text},
+ .header_text{header_text},
+ .sub_text{sub_text},
+ .guide_text{guide_text},
+ .initial_text{initial_text},
+ .max_text_length{max_text_length},
+ .min_text_length{min_text_length},
+ .initial_cursor_position{initial_cursor_position},
+ .type{swkbd_config_common.type},
+ .password_mode{swkbd_config_common.password_mode},
+ .text_draw_type{text_draw_type},
+ .key_disable_flags{swkbd_config_common.key_disable_flags},
+ .use_blur_background{swkbd_config_common.use_blur_background},
+ .enable_backspace_button{true},
+ .enable_return_button{enable_return_button},
+ .disable_cancel_button{disable_cancel_button},
+ };
+
+ frontend.InitializeKeyboard(false, std::move(initialize_parameters),
+ [this](SwkbdResult result, std::u16string submitted_text) {
+ SubmitTextNormal(result, submitted_text);
+ },
+ {});
+ }
+}
+
+void SoftwareKeyboard::ShowNormalKeyboard() {
+ frontend.ShowNormalKeyboard();
+}
+
+void SoftwareKeyboard::ShowTextCheckDialog(SwkbdTextCheckResult text_check_result,
+ std::u16string text_check_message) {
+ frontend.ShowTextCheckDialog(text_check_result, text_check_message);
+}
+
+void SoftwareKeyboard::ShowInlineKeyboard() {
+ if (swkbd_state != SwkbdState::InitializedIsHidden) {
+ return;
+ }
+
+ ChangeState(SwkbdState::InitializedIsAppearing);
+
+ const auto& appear_arg = swkbd_calc_arg.appear_arg;
+
+ const u32 max_text_length =
+ appear_arg.max_text_length > 0 && appear_arg.max_text_length <= DEFAULT_MAX_TEXT_LENGTH
+ ? appear_arg.max_text_length
+ : DEFAULT_MAX_TEXT_LENGTH;
+
+ const u32 min_text_length =
+ appear_arg.min_text_length <= max_text_length ? appear_arg.min_text_length : 0;
+
+ Core::Frontend::InlineAppearParameters appear_parameters{
+ .max_text_length{max_text_length},
+ .min_text_length{min_text_length},
+ .key_top_scale_x{swkbd_calc_arg.key_top_scale_x},
+ .key_top_scale_y{swkbd_calc_arg.key_top_scale_y},
+ .key_top_translate_x{swkbd_calc_arg.key_top_translate_x},
+ .key_top_translate_y{swkbd_calc_arg.key_top_translate_y},
+ .type{appear_arg.type},
+ .key_disable_flags{appear_arg.key_disable_flags},
+ .key_top_as_floating{swkbd_calc_arg.key_top_as_floating},
+ .enable_backspace_button{swkbd_calc_arg.enable_backspace_button},
+ .enable_return_button{appear_arg.enable_return_button},
+ .disable_cancel_button{appear_arg.disable_cancel_button},
+ };
+
+ frontend.ShowInlineKeyboard(std::move(appear_parameters));
+
+ ChangeState(SwkbdState::InitializedIsShown);
+}
+
+void SoftwareKeyboard::HideInlineKeyboard() {
+ if (swkbd_state != SwkbdState::InitializedIsShown) {
+ return;
+ }
+
+ ChangeState(SwkbdState::InitializedIsDisappearing);
+
+ frontend.HideInlineKeyboard();
+
+ ChangeState(SwkbdState::InitializedIsHidden);
+}
+
+void SoftwareKeyboard::InlineTextChanged() {
+ Core::Frontend::InlineTextParameters text_parameters{
+ .input_text{current_text},
+ .cursor_position{current_cursor_position},
+ };
+
+ frontend.InlineTextChanged(std::move(text_parameters));
+}
+
+void SoftwareKeyboard::ExitKeyboard() {
+ complete = true;
+ status = RESULT_SUCCESS;
+
+ frontend.ExitKeyboard();
+
+ broker.SignalStateChanged();
+}
+
+// Inline Software Keyboard Requests
+
+void SoftwareKeyboard::RequestFinalize(const std::vector<u8>& request_data) {
+ LOG_DEBUG(Service_AM, "Processing Request: Finalize");
+
+ ChangeState(SwkbdState::NotInitialized);
+
+ ExitKeyboard();
+}
+
+void SoftwareKeyboard::RequestSetUserWordInfo(const std::vector<u8>& request_data) {
+ LOG_WARNING(Service_AM, "SetUserWordInfo is not implemented.");
+}
+
+void SoftwareKeyboard::RequestSetCustomizeDic(const std::vector<u8>& request_data) {
+ LOG_WARNING(Service_AM, "SetCustomizeDic is not implemented.");
+}
+
+void SoftwareKeyboard::RequestCalc(const std::vector<u8>& request_data) {
+ LOG_DEBUG(Service_AM, "Processing Request: Calc");
+
+ ASSERT(request_data.size() == sizeof(SwkbdRequestCommand) + sizeof(SwkbdCalcArg));
+
+ std::memcpy(&swkbd_calc_arg, request_data.data() + sizeof(SwkbdRequestCommand),
+ sizeof(SwkbdCalcArg));
+
+ if (swkbd_calc_arg.flags.set_input_text) {
+ current_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(
+ swkbd_calc_arg.input_text.data(), swkbd_calc_arg.input_text.size());
+ }
+
+ if (swkbd_calc_arg.flags.set_cursor_position) {
+ current_cursor_position = swkbd_calc_arg.cursor_position;
+ }
+
+ if (swkbd_calc_arg.flags.set_utf8_mode) {
+ inline_use_utf8 = swkbd_calc_arg.utf8_mode;
+ }
+
+ if (swkbd_state <= SwkbdState::InitializedIsHidden &&
+ swkbd_calc_arg.flags.unset_customize_dic) {
+ ReplyUnsetCustomizeDic();
}
+
+ if (swkbd_state <= SwkbdState::InitializedIsHidden &&
+ swkbd_calc_arg.flags.unset_user_word_info) {
+ ReplyReleasedUserWordInfo();
+ }
+
+ if (swkbd_state == SwkbdState::NotInitialized && swkbd_calc_arg.flags.set_initialize_arg) {
+ InitializeFrontendKeyboard();
+
+ ChangeState(SwkbdState::InitializedIsHidden);
+
+ ReplyFinishedInitialize();
+ }
+
+ if (!swkbd_calc_arg.flags.set_initialize_arg &&
+ (swkbd_calc_arg.flags.set_input_text || swkbd_calc_arg.flags.set_cursor_position)) {
+ InlineTextChanged();
+ }
+
+ if (swkbd_state == SwkbdState::InitializedIsHidden && swkbd_calc_arg.flags.appear) {
+ ShowInlineKeyboard();
+ return;
+ }
+
+ if (swkbd_state == SwkbdState::InitializedIsShown && swkbd_calc_arg.flags.disappear) {
+ HideInlineKeyboard();
+ return;
+ }
+}
+
+void SoftwareKeyboard::RequestSetCustomizedDictionaries(const std::vector<u8>& request_data) {
+ LOG_WARNING(Service_AM, "SetCustomizedDictionaries is not implemented.");
+}
+
+void SoftwareKeyboard::RequestUnsetCustomizedDictionaries(const std::vector<u8>& request_data) {
+ LOG_WARNING(Service_AM, "(STUBBED) Processing Request: UnsetCustomizedDictionaries");
+
+ ReplyUnsetCustomizedDictionaries();
+}
+
+void SoftwareKeyboard::RequestSetChangedStringV2Flag(const std::vector<u8>& request_data) {
+ LOG_DEBUG(Service_AM, "Processing Request: SetChangedStringV2Flag");
+
+ ASSERT(request_data.size() == sizeof(SwkbdRequestCommand) + 1);
+
+ std::memcpy(&use_changed_string_v2, request_data.data() + sizeof(SwkbdRequestCommand), 1);
+}
+
+void SoftwareKeyboard::RequestSetMovedCursorV2Flag(const std::vector<u8>& request_data) {
+ LOG_DEBUG(Service_AM, "Processing Request: SetMovedCursorV2Flag");
+
+ ASSERT(request_data.size() == sizeof(SwkbdRequestCommand) + 1);
+
+ std::memcpy(&use_moved_cursor_v2, request_data.data() + sizeof(SwkbdRequestCommand), 1);
+}
+
+// Inline Software Keyboard Replies
+
+void SoftwareKeyboard::ReplyFinishedInitialize() {
+ LOG_DEBUG(Service_AM, "Sending Reply: FinishedInitialize");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE + 1);
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::FinishedInitialize);
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyDefault() {
+ LOG_DEBUG(Service_AM, "Sending Reply: Default");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE);
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::Default);
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyChangedString() {
+ LOG_DEBUG(Service_AM, "Sending Reply: ChangedString");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg));
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedString);
+
+ const SwkbdChangedStringArg changed_string_arg{
+ .text_length{static_cast<u32>(current_text.size())},
+ .dictionary_start_cursor_position{-1},
+ .dictionary_end_cursor_position{-1},
+ .cursor_position{current_cursor_position},
+ };
+
+ std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(),
+ current_text.size() * sizeof(char16_t));
+ std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &changed_string_arg,
+ sizeof(SwkbdChangedStringArg));
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyMovedCursor() {
+ LOG_DEBUG(Service_AM, "Sending Reply: MovedCursor");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg));
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursor);
+
+ const SwkbdMovedCursorArg moved_cursor_arg{
+ .text_length{static_cast<u32>(current_text.size())},
+ .cursor_position{current_cursor_position},
+ };
+
+ std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(),
+ current_text.size() * sizeof(char16_t));
+ std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_cursor_arg,
+ sizeof(SwkbdMovedCursorArg));
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyMovedTab() {
+ LOG_DEBUG(Service_AM, "Sending Reply: MovedTab");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedTabArg));
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedTab);
+
+ const SwkbdMovedTabArg moved_tab_arg{
+ .text_length{static_cast<u32>(current_text.size())},
+ .cursor_position{current_cursor_position},
+ };
+
+ std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(),
+ current_text.size() * sizeof(char16_t));
+ std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_tab_arg,
+ sizeof(SwkbdMovedTabArg));
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyDecidedEnter() {
+ LOG_DEBUG(Service_AM, "Sending Reply: DecidedEnter");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdDecidedEnterArg));
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedEnter);
+
+ const SwkbdDecidedEnterArg decided_enter_arg{
+ .text_length{static_cast<u32>(current_text.size())},
+ };
+
+ std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(),
+ current_text.size() * sizeof(char16_t));
+ std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &decided_enter_arg,
+ sizeof(SwkbdDecidedEnterArg));
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+
+ HideInlineKeyboard();
+}
+
+void SoftwareKeyboard::ReplyDecidedCancel() {
+ LOG_DEBUG(Service_AM, "Sending Reply: DecidedCancel");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE);
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedCancel);
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+
+ HideInlineKeyboard();
+}
+
+void SoftwareKeyboard::ReplyChangedStringUtf8() {
+ LOG_DEBUG(Service_AM, "Sending Reply: ChangedStringUtf8");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdChangedStringArg));
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedStringUtf8);
+
+ std::string utf8_current_text = Common::UTF16ToUTF8(current_text);
+
+ const SwkbdChangedStringArg changed_string_arg{
+ .text_length{static_cast<u32>(current_text.size())},
+ .dictionary_start_cursor_position{-1},
+ .dictionary_end_cursor_position{-1},
+ .cursor_position{current_cursor_position},
+ };
+
+ std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size());
+ std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &changed_string_arg,
+ sizeof(SwkbdChangedStringArg));
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
}
+
+void SoftwareKeyboard::ReplyMovedCursorUtf8() {
+ LOG_DEBUG(Service_AM, "Sending Reply: MovedCursorUtf8");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdMovedCursorArg));
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursorUtf8);
+
+ std::string utf8_current_text = Common::UTF16ToUTF8(current_text);
+
+ const SwkbdMovedCursorArg moved_cursor_arg{
+ .text_length{static_cast<u32>(current_text.size())},
+ .cursor_position{current_cursor_position},
+ };
+
+ std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size());
+ std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &moved_cursor_arg,
+ sizeof(SwkbdMovedCursorArg));
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyDecidedEnterUtf8() {
+ LOG_DEBUG(Service_AM, "Sending Reply: DecidedEnterUtf8");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdDecidedEnterArg));
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::DecidedEnterUtf8);
+
+ std::string utf8_current_text = Common::UTF16ToUTF8(current_text);
+
+ const SwkbdDecidedEnterArg decided_enter_arg{
+ .text_length{static_cast<u32>(current_text.size())},
+ };
+
+ std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size());
+ std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &decided_enter_arg,
+ sizeof(SwkbdDecidedEnterArg));
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+
+ HideInlineKeyboard();
+}
+
+void SoftwareKeyboard::ReplyUnsetCustomizeDic() {
+ LOG_DEBUG(Service_AM, "Sending Reply: UnsetCustomizeDic");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE);
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizeDic);
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyReleasedUserWordInfo() {
+ LOG_DEBUG(Service_AM, "Sending Reply: ReleasedUserWordInfo");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE);
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::ReleasedUserWordInfo);
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyUnsetCustomizedDictionaries() {
+ LOG_DEBUG(Service_AM, "Sending Reply: UnsetCustomizedDictionaries");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE);
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::UnsetCustomizedDictionaries);
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyChangedStringV2() {
+ LOG_DEBUG(Service_AM, "Sending Reply: ChangedStringV2");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg) + 1);
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedStringV2);
+
+ const SwkbdChangedStringArg changed_string_arg{
+ .text_length{static_cast<u32>(current_text.size())},
+ .dictionary_start_cursor_position{-1},
+ .dictionary_end_cursor_position{-1},
+ .cursor_position{current_cursor_position},
+ };
+
+ constexpr u8 flag = 0;
+
+ std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(),
+ current_text.size() * sizeof(char16_t));
+ std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &changed_string_arg,
+ sizeof(SwkbdChangedStringArg));
+ std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdChangedStringArg),
+ &flag, 1);
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyMovedCursorV2() {
+ LOG_DEBUG(Service_AM, "Sending Reply: MovedCursorV2");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg) + 1);
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursorV2);
+
+ const SwkbdMovedCursorArg moved_cursor_arg{
+ .text_length{static_cast<u32>(current_text.size())},
+ .cursor_position{current_cursor_position},
+ };
+
+ constexpr u8 flag = 0;
+
+ std::memcpy(reply.data() + REPLY_BASE_SIZE, current_text.data(),
+ current_text.size() * sizeof(char16_t));
+ std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE, &moved_cursor_arg,
+ sizeof(SwkbdMovedCursorArg));
+ std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF16_SIZE + sizeof(SwkbdMovedCursorArg),
+ &flag, 1);
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyChangedStringUtf8V2() {
+ LOG_DEBUG(Service_AM, "Sending Reply: ChangedStringUtf8V2");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdChangedStringArg) + 1);
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::ChangedStringUtf8V2);
+
+ std::string utf8_current_text = Common::UTF16ToUTF8(current_text);
+
+ const SwkbdChangedStringArg changed_string_arg{
+ .text_length{static_cast<u32>(current_text.size())},
+ .dictionary_start_cursor_position{-1},
+ .dictionary_end_cursor_position{-1},
+ .cursor_position{current_cursor_position},
+ };
+
+ constexpr u8 flag = 0;
+
+ std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size());
+ std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &changed_string_arg,
+ sizeof(SwkbdChangedStringArg));
+ std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdChangedStringArg),
+ &flag, 1);
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+}
+
+void SoftwareKeyboard::ReplyMovedCursorUtf8V2() {
+ LOG_DEBUG(Service_AM, "Sending Reply: MovedCursorUtf8V2");
+
+ std::vector<u8> reply(REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdMovedCursorArg) + 1);
+
+ SetReplyBase(reply, swkbd_state, SwkbdReplyType::MovedCursorUtf8V2);
+
+ std::string utf8_current_text = Common::UTF16ToUTF8(current_text);
+
+ const SwkbdMovedCursorArg moved_cursor_arg{
+ .text_length{static_cast<u32>(current_text.size())},
+ .cursor_position{current_cursor_position},
+ };
+
+ constexpr u8 flag = 0;
+
+ std::memcpy(reply.data() + REPLY_BASE_SIZE, utf8_current_text.data(), utf8_current_text.size());
+ std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE, &moved_cursor_arg,
+ sizeof(SwkbdMovedCursorArg));
+ std::memcpy(reply.data() + REPLY_BASE_SIZE + REPLY_UTF8_SIZE + sizeof(SwkbdMovedCursorArg),
+ &flag, 1);
+
+ broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
+}
+
} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/software_keyboard.h b/src/core/hle/service/am/applets/software_keyboard.h
index 1d260fef8..7c67b7574 100644
--- a/src/core/hle/service/am/applets/software_keyboard.h
+++ b/src/core/hle/service/am/applets/software_keyboard.h
@@ -1,20 +1,14 @@
-// Copyright 2018 yuzu emulator team
+// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
-#include <array>
-#include <string>
-#include <vector>
-
#include "common/common_funcs.h"
#include "common/common_types.h"
-#include "common/swap.h"
-#include "core/hle/service/am/am.h"
+#include "core/hle/result.h"
#include "core/hle/service/am/applets/applets.h"
-
-union ResultCode;
+#include "core/hle/service/am/applets/software_keyboard_types.h"
namespace Core {
class System;
@@ -22,45 +16,10 @@ class System;
namespace Service::AM::Applets {
-enum class KeysetDisable : u32 {
- Space = 0x02,
- Address = 0x04,
- Percent = 0x08,
- Slashes = 0x10,
- Numbers = 0x40,
- DownloadCode = 0x80,
-};
-
-struct KeyboardConfig {
- INSERT_PADDING_BYTES(4);
- std::array<char16_t, 9> submit_text;
- u16_le left_symbol_key;
- u16_le right_symbol_key;
- INSERT_PADDING_BYTES(1);
- KeysetDisable keyset_disable_bitmask;
- u32_le initial_cursor_position;
- std::array<char16_t, 65> header_text;
- std::array<char16_t, 129> sub_text;
- std::array<char16_t, 257> guide_text;
- u32_le length_limit;
- INSERT_PADDING_BYTES(4);
- u32_le is_password;
- INSERT_PADDING_BYTES(5);
- bool utf_8;
- bool draw_background;
- u32_le initial_string_offset;
- u32_le initial_string_size;
- u32_le user_dictionary_offset;
- u32_le user_dictionary_size;
- bool text_check;
- u64_le text_check_callback;
-};
-static_assert(sizeof(KeyboardConfig) == 0x3E0, "KeyboardConfig has incorrect size.");
-
class SoftwareKeyboard final : public Applet {
public:
- explicit SoftwareKeyboard(Core::System& system_,
- const Core::Frontend::SoftwareKeyboardApplet& frontend_);
+ explicit SoftwareKeyboard(Core::System& system_, LibraryAppletMode applet_mode_,
+ Core::Frontend::SoftwareKeyboardApplet& frontend_);
~SoftwareKeyboard() override;
void Initialize() override;
@@ -70,17 +29,138 @@ public:
void ExecuteInteractive() override;
void Execute() override;
- void WriteText(std::optional<std::u16string> text);
+ /**
+ * Submits the input text to the application.
+ * If text checking is enabled, the application will verify the input text.
+ * If use_utf8 is enabled, the input text will be converted to UTF-8 prior to being submitted.
+ * This should only be used by the normal software keyboard.
+ *
+ * @param result SwkbdResult enum
+ * @param submitted_text UTF-16 encoded string
+ */
+ void SubmitTextNormal(SwkbdResult result, std::u16string submitted_text);
+
+ /**
+ * Submits the input text to the application.
+ * If utf8_mode is enabled, the input text will be converted to UTF-8 prior to being submitted.
+ * This should only be used by the inline software keyboard.
+ *
+ * @param reply_type SwkbdReplyType enum
+ * @param submitted_text UTF-16 encoded string
+ * @param cursor_position The current position of the text cursor
+ */
+ void SubmitTextInline(SwkbdReplyType reply_type, std::u16string submitted_text,
+ s32 cursor_position);
private:
- const Core::Frontend::SoftwareKeyboardApplet& frontend;
+ /// Initializes the normal software keyboard.
+ void InitializeForeground();
- KeyboardConfig config;
- std::u16string initial_text;
- bool complete = false;
- bool is_inline = false;
- std::vector<u8> final_data;
+ /// Initializes the inline software keyboard.
+ void InitializeBackground(LibraryAppletMode applet_mode);
+
+ /// Processes the text check sent by the application.
+ void ProcessTextCheck();
+
+ /// Processes the inline software keyboard request command sent by the application.
+ void ProcessInlineKeyboardRequest();
+
+ /// Submits the input text and exits the applet.
+ void SubmitNormalOutputAndExit(SwkbdResult result, std::u16string submitted_text);
+
+ /// Submits the input text for text checking.
+ void SubmitForTextCheck(std::u16string submitted_text);
+
+ /// Sends a reply to the application after processing a request command.
+ void SendReply(SwkbdReplyType reply_type);
+
+ /// Changes the inline keyboard state.
+ void ChangeState(SwkbdState state);
+
+ /**
+ * Signals the frontend to initialize the software keyboard with common parameters.
+ * This initializes either the normal software keyboard or the inline software keyboard
+ * depending on the state of is_background.
+ * Note that this does not cause the keyboard to appear.
+ * Use the respective Show*Keyboard() functions to cause the respective keyboards to appear.
+ */
+ void InitializeFrontendKeyboard();
+
+ /// Signals the frontend to show the normal software keyboard.
+ void ShowNormalKeyboard();
+
+ /// Signals the frontend to show the text check dialog.
+ void ShowTextCheckDialog(SwkbdTextCheckResult text_check_result,
+ std::u16string text_check_message);
+
+ /// Signals the frontend to show the inline software keyboard.
+ void ShowInlineKeyboard();
+
+ /// Signals the frontend to hide the inline software keyboard.
+ void HideInlineKeyboard();
+
+ /// Signals the frontend that the current inline keyboard text has changed.
+ void InlineTextChanged();
+
+ /// Signals both the frontend and application that the software keyboard is exiting.
+ void ExitKeyboard();
+
+ // Inline Software Keyboard Requests
+
+ void RequestFinalize(const std::vector<u8>& request_data);
+ void RequestSetUserWordInfo(const std::vector<u8>& request_data);
+ void RequestSetCustomizeDic(const std::vector<u8>& request_data);
+ void RequestCalc(const std::vector<u8>& request_data);
+ void RequestSetCustomizedDictionaries(const std::vector<u8>& request_data);
+ void RequestUnsetCustomizedDictionaries(const std::vector<u8>& request_data);
+ void RequestSetChangedStringV2Flag(const std::vector<u8>& request_data);
+ void RequestSetMovedCursorV2Flag(const std::vector<u8>& request_data);
+
+ // Inline Software Keyboard Replies
+
+ void ReplyFinishedInitialize();
+ void ReplyDefault();
+ void ReplyChangedString();
+ void ReplyMovedCursor();
+ void ReplyMovedTab();
+ void ReplyDecidedEnter();
+ void ReplyDecidedCancel();
+ void ReplyChangedStringUtf8();
+ void ReplyMovedCursorUtf8();
+ void ReplyDecidedEnterUtf8();
+ void ReplyUnsetCustomizeDic();
+ void ReplyReleasedUserWordInfo();
+ void ReplyUnsetCustomizedDictionaries();
+ void ReplyChangedStringV2();
+ void ReplyMovedCursorV2();
+ void ReplyChangedStringUtf8V2();
+ void ReplyMovedCursorUtf8V2();
+
+ Core::Frontend::SoftwareKeyboardApplet& frontend;
Core::System& system;
+
+ SwkbdAppletVersion swkbd_applet_version;
+
+ SwkbdConfigCommon swkbd_config_common;
+ SwkbdConfigOld swkbd_config_old;
+ SwkbdConfigOld2 swkbd_config_old2;
+ SwkbdConfigNew swkbd_config_new;
+ std::u16string initial_text;
+
+ SwkbdState swkbd_state{SwkbdState::NotInitialized};
+ SwkbdInitializeArg swkbd_initialize_arg;
+ SwkbdCalcArg swkbd_calc_arg;
+ bool use_changed_string_v2{false};
+ bool use_moved_cursor_v2{false};
+ bool inline_use_utf8{false};
+ s32 current_cursor_position{};
+
+ std::u16string current_text;
+
+ bool is_background{false};
+
+ bool complete{false};
+ ResultCode status{RESULT_SUCCESS};
};
} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/software_keyboard_types.h b/src/core/hle/service/am/applets/software_keyboard_types.h
new file mode 100644
index 000000000..21aa8e800
--- /dev/null
+++ b/src/core/hle/service/am/applets/software_keyboard_types.h
@@ -0,0 +1,295 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <array>
+
+#include "common/bit_field.h"
+#include "common/common_funcs.h"
+#include "common/common_types.h"
+#include "common/swap.h"
+
+namespace Service::AM::Applets {
+
+constexpr std::size_t MAX_OK_TEXT_LENGTH = 8;
+constexpr std::size_t MAX_HEADER_TEXT_LENGTH = 64;
+constexpr std::size_t MAX_SUB_TEXT_LENGTH = 128;
+constexpr std::size_t MAX_GUIDE_TEXT_LENGTH = 256;
+constexpr std::size_t STRING_BUFFER_SIZE = 0x7D4;
+
+enum class SwkbdAppletVersion : u32_le {
+ Version5 = 0x5, // 1.0.0
+ Version65542 = 0x10006, // 2.0.0 - 2.3.0
+ Version196615 = 0x30007, // 3.0.0 - 3.0.2
+ Version262152 = 0x40008, // 4.0.0 - 4.1.0
+ Version327689 = 0x50009, // 5.0.0 - 5.1.0
+ Version393227 = 0x6000B, // 6.0.0 - 7.0.1
+ Version524301 = 0x8000D, // 8.0.0+
+};
+
+enum class SwkbdType : u32 {
+ Normal,
+ NumberPad,
+ Qwerty,
+ Unknown3,
+ Latin,
+ SimplifiedChinese,
+ TraditionalChinese,
+ Korean,
+};
+
+enum class SwkbdInitialCursorPosition : u32 {
+ Start,
+ End,
+};
+
+enum class SwkbdPasswordMode : u32 {
+ Disabled,
+ Enabled,
+};
+
+enum class SwkbdTextDrawType : u32 {
+ Line,
+ Box,
+ DownloadCode,
+};
+
+enum class SwkbdResult : u32 {
+ Ok,
+ Cancel,
+};
+
+enum class SwkbdTextCheckResult : u32 {
+ Success,
+ Failure,
+ Confirm,
+ Silent,
+};
+
+enum class SwkbdState : u32 {
+ NotInitialized = 0x0,
+ InitializedIsHidden = 0x1,
+ InitializedIsAppearing = 0x2,
+ InitializedIsShown = 0x3,
+ InitializedIsDisappearing = 0x4,
+};
+
+enum class SwkbdRequestCommand : u32 {
+ Finalize = 0x4,
+ SetUserWordInfo = 0x6,
+ SetCustomizeDic = 0x7,
+ Calc = 0xA,
+ SetCustomizedDictionaries = 0xB,
+ UnsetCustomizedDictionaries = 0xC,
+ SetChangedStringV2Flag = 0xD,
+ SetMovedCursorV2Flag = 0xE,
+};
+
+enum class SwkbdReplyType : u32 {
+ FinishedInitialize = 0x0,
+ Default = 0x1,
+ ChangedString = 0x2,
+ MovedCursor = 0x3,
+ MovedTab = 0x4,
+ DecidedEnter = 0x5,
+ DecidedCancel = 0x6,
+ ChangedStringUtf8 = 0x7,
+ MovedCursorUtf8 = 0x8,
+ DecidedEnterUtf8 = 0x9,
+ UnsetCustomizeDic = 0xA,
+ ReleasedUserWordInfo = 0xB,
+ UnsetCustomizedDictionaries = 0xC,
+ ChangedStringV2 = 0xD,
+ MovedCursorV2 = 0xE,
+ ChangedStringUtf8V2 = 0xF,
+ MovedCursorUtf8V2 = 0x10,
+};
+
+struct SwkbdKeyDisableFlags {
+ union {
+ u32 raw{};
+
+ BitField<1, 1, u32> space;
+ BitField<2, 1, u32> at;
+ BitField<3, 1, u32> percent;
+ BitField<4, 1, u32> slash;
+ BitField<5, 1, u32> backslash;
+ BitField<6, 1, u32> numbers;
+ BitField<7, 1, u32> download_code;
+ BitField<8, 1, u32> username;
+ };
+};
+static_assert(sizeof(SwkbdKeyDisableFlags) == 0x4, "SwkbdKeyDisableFlags has incorrect size.");
+
+struct SwkbdConfigCommon {
+ SwkbdType type{};
+ std::array<char16_t, MAX_OK_TEXT_LENGTH + 1> ok_text{};
+ char16_t left_optional_symbol_key{};
+ char16_t right_optional_symbol_key{};
+ bool use_prediction{};
+ INSERT_PADDING_BYTES(1);
+ SwkbdKeyDisableFlags key_disable_flags{};
+ SwkbdInitialCursorPosition initial_cursor_position{};
+ std::array<char16_t, MAX_HEADER_TEXT_LENGTH + 1> header_text{};
+ std::array<char16_t, MAX_SUB_TEXT_LENGTH + 1> sub_text{};
+ std::array<char16_t, MAX_GUIDE_TEXT_LENGTH + 1> guide_text{};
+ u32 max_text_length{};
+ u32 min_text_length{};
+ SwkbdPasswordMode password_mode{};
+ SwkbdTextDrawType text_draw_type{};
+ bool enable_return_button{};
+ bool use_utf8{};
+ bool use_blur_background{};
+ INSERT_PADDING_BYTES(1);
+ u32 initial_string_offset{};
+ u32 initial_string_length{};
+ u32 user_dictionary_offset{};
+ u32 user_dictionary_entries{};
+ bool use_text_check{};
+ INSERT_PADDING_BYTES(3);
+};
+static_assert(sizeof(SwkbdConfigCommon) == 0x3D4, "SwkbdConfigCommon has incorrect size.");
+
+#pragma pack(push, 4)
+// SwkbdAppletVersion 0x5, 0x10006
+struct SwkbdConfigOld {
+ INSERT_PADDING_WORDS(1);
+ VAddr text_check_callback{};
+};
+static_assert(sizeof(SwkbdConfigOld) == 0x3E0 - sizeof(SwkbdConfigCommon),
+ "SwkbdConfigOld has incorrect size.");
+
+// SwkbdAppletVersion 0x30007, 0x40008, 0x50009
+struct SwkbdConfigOld2 {
+ INSERT_PADDING_WORDS(1);
+ VAddr text_check_callback{};
+ std::array<u32, 8> text_grouping{};
+};
+static_assert(sizeof(SwkbdConfigOld2) == 0x400 - sizeof(SwkbdConfigCommon),
+ "SwkbdConfigOld2 has incorrect size.");
+
+// SwkbdAppletVersion 0x6000B, 0x8000D
+struct SwkbdConfigNew {
+ std::array<u32, 8> text_grouping{};
+ std::array<u64, 24> customized_dictionary_set_entries{};
+ u8 total_customized_dictionary_set_entries{};
+ bool disable_cancel_button{};
+ INSERT_PADDING_BYTES(18);
+};
+static_assert(sizeof(SwkbdConfigNew) == 0x4C8 - sizeof(SwkbdConfigCommon),
+ "SwkbdConfigNew has incorrect size.");
+#pragma pack(pop)
+
+struct SwkbdTextCheck {
+ SwkbdTextCheckResult text_check_result{};
+ std::array<char16_t, STRING_BUFFER_SIZE / 2> text_check_message{};
+};
+static_assert(sizeof(SwkbdTextCheck) == 0x7D8, "SwkbdTextCheck has incorrect size.");
+
+struct SwkbdCalcArgFlags {
+ union {
+ u64 raw{};
+
+ BitField<0, 1, u64> set_initialize_arg;
+ BitField<1, 1, u64> set_volume;
+ BitField<2, 1, u64> appear;
+ BitField<3, 1, u64> set_input_text;
+ BitField<4, 1, u64> set_cursor_position;
+ BitField<5, 1, u64> set_utf8_mode;
+ BitField<6, 1, u64> unset_customize_dic;
+ BitField<7, 1, u64> disappear;
+ BitField<8, 1, u64> unknown;
+ BitField<9, 1, u64> set_key_top_translate_scale;
+ BitField<10, 1, u64> unset_user_word_info;
+ BitField<11, 1, u64> set_disable_hardware_keyboard;
+ };
+};
+static_assert(sizeof(SwkbdCalcArgFlags) == 0x8, "SwkbdCalcArgFlags has incorrect size.");
+
+struct SwkbdInitializeArg {
+ u32 unknown{};
+ bool library_applet_mode_flag{};
+ bool is_above_hos_500{};
+ INSERT_PADDING_BYTES(2);
+};
+static_assert(sizeof(SwkbdInitializeArg) == 0x8, "SwkbdInitializeArg has incorrect size.");
+
+struct SwkbdAppearArg {
+ SwkbdType type{};
+ std::array<char16_t, MAX_OK_TEXT_LENGTH + 1> ok_text{};
+ char16_t left_optional_symbol_key{};
+ char16_t right_optional_symbol_key{};
+ bool use_prediction{};
+ bool disable_cancel_button{};
+ SwkbdKeyDisableFlags key_disable_flags{};
+ u32 max_text_length{};
+ u32 min_text_length{};
+ bool enable_return_button{};
+ INSERT_PADDING_BYTES(3);
+ u32 flags{};
+ INSERT_PADDING_WORDS(6);
+};
+static_assert(sizeof(SwkbdAppearArg) == 0x48, "SwkbdAppearArg has incorrect size.");
+
+struct SwkbdCalcArg {
+ u32 unknown{};
+ u16 calc_arg_size{};
+ INSERT_PADDING_BYTES(2);
+ SwkbdCalcArgFlags flags{};
+ SwkbdInitializeArg initialize_arg{};
+ f32 volume{};
+ s32 cursor_position{};
+ SwkbdAppearArg appear_arg{};
+ std::array<char16_t, 0x1FA> input_text{};
+ bool utf8_mode{};
+ INSERT_PADDING_BYTES(1);
+ bool enable_backspace_button{};
+ INSERT_PADDING_BYTES(3);
+ bool key_top_as_floating{};
+ bool footer_scalable{};
+ bool alpha_enabled_in_input_mode{};
+ u8 input_mode_fade_type{};
+ bool disable_touch{};
+ bool disable_hardware_keyboard{};
+ INSERT_PADDING_BYTES(8);
+ f32 key_top_scale_x{};
+ f32 key_top_scale_y{};
+ f32 key_top_translate_x{};
+ f32 key_top_translate_y{};
+ f32 key_top_bg_alpha{};
+ f32 footer_bg_alpha{};
+ f32 balloon_scale{};
+ INSERT_PADDING_WORDS(4);
+ u8 se_group{};
+ INSERT_PADDING_BYTES(3);
+};
+static_assert(sizeof(SwkbdCalcArg) == 0x4A0, "SwkbdCalcArg has incorrect size.");
+
+struct SwkbdChangedStringArg {
+ u32 text_length{};
+ s32 dictionary_start_cursor_position{};
+ s32 dictionary_end_cursor_position{};
+ s32 cursor_position{};
+};
+static_assert(sizeof(SwkbdChangedStringArg) == 0x10, "SwkbdChangedStringArg has incorrect size.");
+
+struct SwkbdMovedCursorArg {
+ u32 text_length{};
+ s32 cursor_position{};
+};
+static_assert(sizeof(SwkbdMovedCursorArg) == 0x8, "SwkbdMovedCursorArg has incorrect size.");
+
+struct SwkbdMovedTabArg {
+ u32 text_length{};
+ s32 cursor_position{};
+};
+static_assert(sizeof(SwkbdMovedTabArg) == 0x8, "SwkbdMovedTabArg has incorrect size.");
+
+struct SwkbdDecidedEnterArg {
+ u32 text_length{};
+};
+static_assert(sizeof(SwkbdDecidedEnterArg) == 0x4, "SwkbdDecidedEnterArg has incorrect size.");
+
+} // namespace Service::AM::Applets
diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp
index 2ab420789..2404921fd 100644
--- a/src/core/hle/service/am/applets/web_browser.cpp
+++ b/src/core/hle/service/am/applets/web_browser.cpp
@@ -208,8 +208,9 @@ void ExtractSharedFonts(Core::System& system) {
} // namespace
-WebBrowser::WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_)
- : Applet{system_.Kernel()}, frontend(frontend_), system{system_} {}
+WebBrowser::WebBrowser(Core::System& system_, LibraryAppletMode applet_mode_,
+ const Core::Frontend::WebBrowserApplet& frontend_)
+ : Applet{system_, applet_mode_}, frontend(frontend_), system{system_} {}
WebBrowser::~WebBrowser() = default;
diff --git a/src/core/hle/service/am/applets/web_browser.h b/src/core/hle/service/am/applets/web_browser.h
index 04c274754..21fd910c2 100644
--- a/src/core/hle/service/am/applets/web_browser.h
+++ b/src/core/hle/service/am/applets/web_browser.h
@@ -25,7 +25,8 @@ namespace Service::AM::Applets {
class WebBrowser final : public Applet {
public:
- WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_);
+ WebBrowser(Core::System& system_, LibraryAppletMode applet_mode_,
+ const Core::Frontend::WebBrowserApplet& frontend_);
~WebBrowser() override;
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp
index 0f51e5871..75867e349 100644
--- a/src/core/hle/service/aoc/aoc_u.cpp
+++ b/src/core/hle/service/aoc/aoc_u.cpp
@@ -7,6 +7,7 @@
#include <vector>
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/file_sys/common_funcs.h"
#include "core/file_sys/content_archive.h"
@@ -21,7 +22,6 @@
#include "core/hle/kernel/process.h"
#include "core/hle/service/aoc/aoc_u.h"
#include "core/loader/loader.h"
-#include "core/settings.h"
namespace Service::AOC {
diff --git a/src/core/hle/service/apm/controller.cpp b/src/core/hle/service/apm/controller.cpp
index 03636642b..00c174bb0 100644
--- a/src/core/hle/service/apm/controller.cpp
+++ b/src/core/hle/service/apm/controller.cpp
@@ -7,9 +7,9 @@
#include <utility>
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core_timing.h"
#include "core/hle/service/apm/controller.h"
-#include "core/settings.h"
namespace Service::APM {
diff --git a/src/core/hle/service/bcat/backend/boxcat.cpp b/src/core/hle/service/bcat/backend/boxcat.cpp
index e43f3f47f..78c047bd2 100644
--- a/src/core/hle/service/bcat/backend/boxcat.cpp
+++ b/src/core/hle/service/bcat/backend/boxcat.cpp
@@ -9,6 +9,7 @@
#include "common/hex_util.h"
#include "common/logging/backend.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs_libzip.h"
@@ -16,7 +17,6 @@
#include "core/frontend/applets/error.h"
#include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/bcat/backend/boxcat.h"
-#include "core/settings.h"
namespace Service::BCAT {
namespace {
diff --git a/src/core/hle/service/bcat/module.cpp b/src/core/hle/service/bcat/module.cpp
index b68e2c345..c7dd04a6e 100644
--- a/src/core/hle/service/bcat/module.cpp
+++ b/src/core/hle/service/bcat/module.cpp
@@ -7,6 +7,7 @@
#include "backend/boxcat.h"
#include "common/hex_util.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/file_sys/vfs.h"
@@ -18,7 +19,6 @@
#include "core/hle/service/bcat/bcat.h"
#include "core/hle/service/bcat/module.h"
#include "core/hle/service/filesystem/filesystem.h"
-#include "core/settings.h"
namespace Service::BCAT {
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index b15c737e1..72ad273b2 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -6,6 +6,7 @@
#include "common/assert.h"
#include "common/file_util.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/file_sys/bis_factory.h"
#include "core/file_sys/card_image.h"
@@ -26,7 +27,6 @@
#include "core/hle/service/filesystem/fsp_pr.h"
#include "core/hle/service/filesystem/fsp_srv.h"
#include "core/loader/loader.h"
-#include "core/settings.h"
namespace Service::FileSystem {
diff --git a/src/core/hle/service/glue/arp.cpp b/src/core/hle/service/glue/arp.cpp
index 322125135..7b1c6677c 100644
--- a/src/core/hle/service/glue/arp.cpp
+++ b/src/core/hle/service/glue/arp.cpp
@@ -157,9 +157,9 @@ class IRegistrar final : public ServiceFramework<IRegistrar> {
friend class ARP_W;
public:
- explicit IRegistrar(
- Core::System& system_,
- std::function<ResultCode(u64, ApplicationLaunchProperty, std::vector<u8>)> issuer)
+ using IssuerFn = std::function<ResultCode(u64, ApplicationLaunchProperty, std::vector<u8>)>;
+
+ explicit IRegistrar(Core::System& system_, IssuerFn&& issuer)
: ServiceFramework{system_, "IRegistrar"}, issue_process_id{std::move(issuer)} {
// clang-format off
static const FunctionInfo functions[] = {
@@ -238,9 +238,9 @@ private:
rb.Push(RESULT_SUCCESS);
}
- std::function<ResultCode(u64, ApplicationLaunchProperty, std::vector<u8>)> issue_process_id;
+ IssuerFn issue_process_id;
bool issued = false;
- ApplicationLaunchProperty launch;
+ ApplicationLaunchProperty launch{};
std::vector<u8> control;
};
diff --git a/src/core/hle/service/glue/ectx.cpp b/src/core/hle/service/glue/ectx.cpp
new file mode 100644
index 000000000..249c6f003
--- /dev/null
+++ b/src/core/hle/service/glue/ectx.cpp
@@ -0,0 +1,22 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/glue/ectx.h"
+
+namespace Service::Glue {
+
+ECTX_AW::ECTX_AW(Core::System& system_) : ServiceFramework{system_, "ectx:aw"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "CreateContextRegistrar"},
+ {1, nullptr, "CommitContext"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+ECTX_AW::~ECTX_AW() = default;
+
+} // namespace Service::Glue
diff --git a/src/core/hle/service/glue/ectx.h b/src/core/hle/service/glue/ectx.h
new file mode 100644
index 000000000..b275e808a
--- /dev/null
+++ b/src/core/hle/service/glue/ectx.h
@@ -0,0 +1,21 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Core {
+class System;
+}
+
+namespace Service::Glue {
+
+class ECTX_AW final : public ServiceFramework<ECTX_AW> {
+public:
+ explicit ECTX_AW(Core::System& system_);
+ ~ECTX_AW() override;
+};
+
+} // namespace Service::Glue
diff --git a/src/core/hle/service/glue/glue.cpp b/src/core/hle/service/glue/glue.cpp
index 4eafbe5fa..a08dc9758 100644
--- a/src/core/hle/service/glue/glue.cpp
+++ b/src/core/hle/service/glue/glue.cpp
@@ -6,6 +6,7 @@
#include "core/core.h"
#include "core/hle/service/glue/arp.h"
#include "core/hle/service/glue/bgtc.h"
+#include "core/hle/service/glue/ectx.h"
#include "core/hle/service/glue/glue.h"
namespace Service::Glue {
@@ -20,6 +21,9 @@ void InstallInterfaces(Core::System& system) {
// BackGround Task Controller
std::make_shared<BGTC_T>(system)->InstallAsService(system.ServiceManager());
std::make_shared<BGTC_SC>(system)->InstallAsService(system.ServiceManager());
+
+ // Error Context
+ std::make_shared<ECTX_AW>(system)->InstallAsService(system.ServiceManager());
}
} // namespace Service::Glue
diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp
index ad251ed4a..a460f2f79 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.cpp
+++ b/src/core/hle/service/hid/controllers/debug_pad.cpp
@@ -4,9 +4,9 @@
#include <cstring>
#include "common/common_types.h"
+#include "common/settings.h"
#include "core/core_timing.h"
#include "core/hle/service/hid/controllers/debug_pad.h"
-#include "core/settings.h"
namespace Service::HID {
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h
index 555b29d76..0593d7d39 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.h
+++ b/src/core/hle/service/hid/controllers/debug_pad.h
@@ -8,10 +8,10 @@
#include "common/bit_field.h"
#include "common/common_funcs.h"
#include "common/common_types.h"
+#include "common/settings.h"
#include "common/swap.h"
#include "core/frontend/input.h"
#include "core/hle/service/hid/controllers/controller_base.h"
-#include "core/settings.h"
namespace Service::HID {
class Controller_DebugPad final : public ControllerBase {
diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp
index 93c43a203..155808f6a 100644
--- a/src/core/hle/service/hid/controllers/gesture.cpp
+++ b/src/core/hle/service/hid/controllers/gesture.cpp
@@ -5,10 +5,10 @@
#include <cstring>
#include "common/common_types.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core_timing.h"
#include "core/frontend/emu_window.h"
#include "core/hle/service/hid/controllers/gesture.h"
-#include "core/settings.h"
namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3BA00;
diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp
index c4a59147d..18b76038f 100644
--- a/src/core/hle/service/hid/controllers/keyboard.cpp
+++ b/src/core/hle/service/hid/controllers/keyboard.cpp
@@ -4,9 +4,9 @@
#include <cstring>
#include "common/common_types.h"
+#include "common/settings.h"
#include "core/core_timing.h"
#include "core/hle/service/hid/controllers/keyboard.h"
-#include "core/settings.h"
namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800;
diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h
index b5b281752..e72948591 100644
--- a/src/core/hle/service/hid/controllers/keyboard.h
+++ b/src/core/hle/service/hid/controllers/keyboard.h
@@ -8,10 +8,10 @@
#include "common/bit_field.h"
#include "common/common_funcs.h"
#include "common/common_types.h"
+#include "common/settings.h"
#include "common/swap.h"
#include "core/frontend/input.h"
#include "core/hle/service/hid/controllers/controller_base.h"
-#include "core/settings.h"
namespace Service::HID {
class Controller_Keyboard final : public ControllerBase {
diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h
index 3b432a36e..0ec0c2b94 100644
--- a/src/core/hle/service/hid/controllers/mouse.h
+++ b/src/core/hle/service/hid/controllers/mouse.h
@@ -7,10 +7,10 @@
#include <array>
#include "common/bit_field.h"
#include "common/common_types.h"
+#include "common/settings.h"
#include "common/swap.h"
#include "core/frontend/input.h"
#include "core/hle/service/hid/controllers/controller_base.h"
-#include "core/settings.h"
namespace Service::HID {
class Controller_Mouse final : public ControllerBase {
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 673db68c7..113a41254 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -9,6 +9,7 @@
#include "common/bit_field.h"
#include "common/common_types.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/frontend/input.h"
@@ -17,7 +18,6 @@
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/service/hid/controllers/npad.h"
-#include "core/settings.h"
namespace Service::HID {
constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
@@ -147,7 +147,7 @@ bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) {
device_handle.device_index < DeviceIndex::MaxDeviceIndex;
}
-Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {
+Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system) {
latest_vibration_values.fill({DEFAULT_VIBRATION_VALUE, DEFAULT_VIBRATION_VALUE});
}
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 873a0a1e2..c3b07bd41 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -8,10 +8,10 @@
#include <atomic>
#include "common/bit_field.h"
#include "common/common_types.h"
+#include "common/settings.h"
#include "core/frontend/input.h"
#include "core/hle/kernel/object.h"
#include "core/hle/service/hid/controllers/controller_base.h"
-#include "core/settings.h"
namespace Kernel {
class KEvent;
@@ -587,6 +587,5 @@ private:
std::array<ControllerPad, 10> npad_pad_states{};
std::array<TriggerState, 10> npad_trigger_states{};
bool is_in_lr_assignment_mode{false};
- Core::System& system;
};
} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp
index be60492a4..b5f8077be 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.cpp
+++ b/src/core/hle/service/hid/controllers/touchscreen.cpp
@@ -6,11 +6,11 @@
#include <cstring>
#include "common/common_types.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core_timing.h"
#include "core/frontend/emu_window.h"
#include "core/frontend/input.h"
#include "core/hle/service/hid/controllers/touchscreen.h"
-#include "core/settings.h"
namespace Service::HID {
constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400;
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index a1a779cc0..2aa1942cb 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -5,6 +5,7 @@
#include <array>
#include "common/common_types.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/core_timing_util.h"
@@ -18,12 +19,12 @@
#include "core/hle/kernel/k_shared_memory.h"
#include "core/hle/kernel/k_writable_event.h"
#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/transfer_memory.h"
#include "core/hle/service/hid/errors.h"
#include "core/hle/service/hid/hid.h"
#include "core/hle/service/hid/irs.h"
#include "core/hle/service/hid/xcd.h"
#include "core/hle/service/service.h"
-#include "core/settings.h"
#include "core/hle/service/hid/controllers/controller_base.h"
#include "core/hle/service/hid/controllers/debug_pad.h"
@@ -1484,7 +1485,43 @@ void Hid::StopSevenSixAxisSensor(Kernel::HLERequestContext& ctx) {
}
void Hid::InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_HID, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+ const auto t_mem_1_size{rp.Pop<u64>()};
+ const auto t_mem_2_size{rp.Pop<u64>()};
+ const auto t_mem_1_handle{ctx.GetCopyHandle(0)};
+ const auto t_mem_2_handle{ctx.GetCopyHandle(1)};
+
+ ASSERT_MSG(t_mem_1_size == 0x1000, "t_mem_1_size is not 0x1000 bytes");
+ ASSERT_MSG(t_mem_2_size == 0x7F000, "t_mem_2_size is not 0x7F000 bytes");
+
+ auto t_mem_1 =
+ system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(t_mem_1_handle);
+
+ if (t_mem_1 == nullptr) {
+ LOG_ERROR(Service_HID, "t_mem_1 is a nullptr for handle=0x{:08X}", t_mem_1_handle);
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_UNKNOWN);
+ return;
+ }
+
+ auto t_mem_2 =
+ system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(t_mem_2_handle);
+
+ if (t_mem_2 == nullptr) {
+ LOG_ERROR(Service_HID, "t_mem_2 is a nullptr for handle=0x{:08X}", t_mem_2_handle);
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_UNKNOWN);
+ return;
+ }
+
+ ASSERT_MSG(t_mem_1->GetSize() == 0x1000, "t_mem_1 has incorrect size");
+ ASSERT_MSG(t_mem_2->GetSize() == 0x7F000, "t_mem_2 has incorrect size");
+
+ LOG_WARNING(Service_HID,
+ "(STUBBED) called, t_mem_1_handle=0x{:08X}, t_mem_2_handle=0x{:08X}, "
+ "applet_resource_user_id={}",
+ t_mem_1_handle, t_mem_2_handle, applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
diff --git a/src/core/hle/service/lbl/lbl.cpp b/src/core/hle/service/lbl/lbl.cpp
index f4490f3d9..e11a0c45a 100644
--- a/src/core/hle/service/lbl/lbl.cpp
+++ b/src/core/hle/service/lbl/lbl.cpp
@@ -79,7 +79,6 @@ private:
}
void GetCurrentBrightnessSetting(Kernel::HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
auto brightness = current_brightness;
if (!std::isfinite(brightness)) {
LOG_ERROR(Service_LBL, "Brightness is infinite!");
@@ -272,7 +271,6 @@ private:
}
void GetCurrentBrightnessSettingForVrMode(Kernel::HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
auto brightness = current_vr_brightness;
if (!std::isfinite(brightness)) {
LOG_ERROR(Service_LBL, "Brightness is infinite!");
diff --git a/src/core/hle/service/lm/lm.cpp b/src/core/hle/service/lm/lm.cpp
index 7d7542fc2..9bcf8870d 100644
--- a/src/core/hle/service/lm/lm.cpp
+++ b/src/core/hle/service/lm/lm.cpp
@@ -46,7 +46,7 @@ struct hash<Service::LM::LogPacketHeaderEntry> {
boost::hash_combine(seed, k.severity);
boost::hash_combine(seed, k.verbosity);
return seed;
- };
+ }
};
} // namespace std
@@ -95,7 +95,7 @@ private:
std::memcpy(&header, data.data(), sizeof(LogPacketHeader));
offset += sizeof(LogPacketHeader);
- LogPacketHeaderEntry entry{
+ const LogPacketHeaderEntry entry{
.pid = header.pid,
.tid = header.tid,
.severity = header.severity,
@@ -105,16 +105,17 @@ private:
if (True(header.flags & LogPacketFlags::Head)) {
std::vector<u8> tmp(data.size() - sizeof(LogPacketHeader));
std::memcpy(tmp.data(), data.data() + offset, tmp.size());
- entries[entry] = std::move(tmp);
+ entries.insert_or_assign(entry, std::move(tmp));
} else {
+ const auto entry_iter = entries.find(entry);
+
// Append to existing entry
- if (!entries.contains(entry)) {
+ if (entry_iter == entries.cend()) {
LOG_ERROR(Service_LM, "Log entry does not exist!");
return;
}
- std::vector<u8> tmp(data.size() - sizeof(LogPacketHeader));
- auto& existing_entry = entries[entry];
+ auto& existing_entry = entry_iter->second;
const auto base = existing_entry.size();
existing_entry.resize(base + (data.size() - sizeof(LogPacketHeader)));
std::memcpy(existing_entry.data() + base, data.data() + offset,
diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp
index 6ab35de47..44a5d5789 100644
--- a/src/core/hle/service/nfc/nfc.cpp
+++ b/src/core/hle/service/nfc/nfc.cpp
@@ -5,12 +5,12 @@
#include <memory>
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/service/nfc/nfc.h"
#include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h"
-#include "core/settings.h"
namespace Service::NFC {
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index afb3342d6..9f110df8e 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "common/settings.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/k_event.h"
@@ -10,7 +11,6 @@
#include "core/hle/service/nifm/nifm.h"
#include "core/hle/service/service.h"
#include "core/network/network.h"
-#include "core/settings.h"
namespace Service::NIFM {
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp
index 5fe7a9189..e373609a1 100644
--- a/src/core/hle/service/ns/ns.cpp
+++ b/src/core/hle/service/ns/ns.cpp
@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/patch_manager.h"
@@ -14,7 +15,6 @@
#include "core/hle/service/ns/ns.h"
#include "core/hle/service/ns/pl_u.h"
#include "core/hle/service/set/set.h"
-#include "core/settings.h"
namespace Service::NS {
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
index c8031970b..e2f671d8e 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
@@ -31,14 +31,8 @@ NvResult nvhost_nvdec::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>&
return SetSubmitTimeout(input, output);
case 0x9:
return MapBuffer(input, output);
- case 0xa: {
- if (command.length == 0x1c) {
- LOG_INFO(Service_NVDRV, "NVDEC video stream ended");
- Tegra::ChCommandHeaderList cmdlist{{0xDEADB33F}};
- system.GPU().PushCommandBuffer(cmdlist);
- }
+ case 0xa:
return UnmapBuffer(input, output);
- }
default:
break;
}
@@ -70,6 +64,10 @@ NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>&
}
void nvhost_nvdec::OnOpen(DeviceFD fd) {}
-void nvhost_nvdec::OnClose(DeviceFD fd) {}
+
+void nvhost_nvdec::OnClose(DeviceFD fd) {
+ LOG_INFO(Service_NVDRV, "NVDEC video stream ended");
+ system.GPU().ClearCdmaInstance();
+}
} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
index 0421fb956..301efe8a1 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
@@ -29,13 +29,8 @@ NvResult nvhost_vic::Ioctl1(DeviceFD fd, Ioctl command, const std::vector<u8>& i
return GetWaitbase(input, output);
case 0x9:
return MapBuffer(input, output);
- case 0xa: {
- if (command.length == 0x1c) {
- Tegra::ChCommandHeaderList cmdlist{{0xDEADB33F}};
- system.GPU().PushCommandBuffer(cmdlist);
- }
+ case 0xa:
return UnmapBuffer(input, output);
- }
default:
break;
}
@@ -69,6 +64,9 @@ NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, const std::vector<u8>& i
}
void nvhost_vic::OnOpen(DeviceFD fd) {}
-void nvhost_vic::OnClose(DeviceFD fd) {}
+
+void nvhost_vic::OnClose(DeviceFD fd) {
+ system.GPU().ClearCdmaInstance();
+}
} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index ac2906e5b..539b02bc4 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -9,6 +9,7 @@
#include "common/logging/log.h"
#include "common/microprofile.h"
#include "common/scope_exit.h"
+#include "common/settings.h"
#include "common/thread.h"
#include "core/core.h"
#include "core/core_timing.h"
@@ -23,7 +24,6 @@
#include "core/hle/service/vi/display/vi_display.h"
#include "core/hle/service/vi/layer/vi_layer.h"
#include "core/perf_stats.h"
-#include "core/settings.h"
#include "video_core/renderer_base.h"
namespace Service::NVFlinger {
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index aec399076..41a502d8d 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -6,6 +6,7 @@
#include <fmt/format.h>
#include "common/assert.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/hle/ipc.h"
@@ -70,7 +71,6 @@
#include "core/hle/service/vi/vi.h"
#include "core/hle/service/wlan/wlan.h"
#include "core/reporter.h"
-#include "core/settings.h"
namespace Service {
diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp
index d953b4303..fbdc4793d 100644
--- a/src/core/hle/service/set/set.cpp
+++ b/src/core/hle/service/set/set.cpp
@@ -6,9 +6,9 @@
#include <array>
#include <chrono>
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/set/set.h"
-#include "core/settings.h"
namespace Service::Set {
namespace {
@@ -104,9 +104,10 @@ void GetKeyCodeMapImpl(Kernel::HLERequestContext& ctx) {
layout = key_code->second;
}
+ ctx.WriteBuffer(layout);
+
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
- ctx.WriteBuffer(layout);
}
} // Anonymous namespace
diff --git a/src/core/hle/service/spl/module.cpp b/src/core/hle/service/spl/module.cpp
index 6903dd534..b1552c3f0 100644
--- a/src/core/hle/service/spl/module.cpp
+++ b/src/core/hle/service/spl/module.cpp
@@ -9,11 +9,11 @@
#include <functional>
#include <vector>
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/spl/csrng.h"
#include "core/hle/service/spl/module.h"
#include "core/hle/service/spl/spl.h"
-#include "core/settings.h"
namespace Service::SPL {
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index 63e0247de..32f372d71 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -294,16 +294,17 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
return;
}
+ ctx.WriteBuffer(clock_snapshot);
+
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
- ctx.WriteBuffer(clock_snapshot);
}
void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto type{rp.PopEnum<Clock::TimeType>()};
- rp.AlignWithPadding();
+ rp.Skip(1, false);
const Clock::SystemClockContext user_context{rp.PopRaw<Clock::SystemClockContext>()};
const Clock::SystemClockContext network_context{rp.PopRaw<Clock::SystemClockContext>()};
@@ -319,9 +320,10 @@ void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLEReques
return;
}
+ ctx.WriteBuffer(clock_snapshot);
+
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
- ctx.WriteBuffer(clock_snapshot);
}
void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser(
diff --git a/src/core/hle/service/time/time_manager.cpp b/src/core/hle/service/time/time_manager.cpp
index 51becd074..f89c5aaad 100644
--- a/src/core/hle/service/time/time_manager.cpp
+++ b/src/core/hle/service/time/time_manager.cpp
@@ -5,12 +5,12 @@
#include <chrono>
#include <ctime>
+#include "common/settings.h"
#include "common/time_zone.h"
#include "core/hle/service/time/ephemeral_network_system_clock_context_writer.h"
#include "core/hle/service/time/local_system_clock_context_writer.h"
#include "core/hle/service/time/network_system_clock_context_writer.h"
#include "core/hle/service/time/time_manager.h"
-#include "core/settings.h"
namespace Service::Time {
diff --git a/src/core/hle/service/time/time_zone_content_manager.cpp b/src/core/hle/service/time/time_zone_content_manager.cpp
index 4177d0a41..3c8e71a3c 100644
--- a/src/core/hle/service/time/time_zone_content_manager.cpp
+++ b/src/core/hle/service/time/time_zone_content_manager.cpp
@@ -5,6 +5,7 @@
#include <sstream>
#include "common/logging/log.h"
+#include "common/settings.h"
#include "common/time_zone.h"
#include "core/core.h"
#include "core/file_sys/content_archive.h"
@@ -15,7 +16,6 @@
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/time/time_manager.h"
#include "core/hle/service/time/time_zone_content_manager.h"
-#include "core/settings.h"
namespace Service::Time::TimeZone {
diff --git a/src/core/hle/service/time/time_zone_service.cpp b/src/core/hle/service/time/time_zone_service.cpp
index 3117627cf..19d7a1a0c 100644
--- a/src/core/hle/service/time/time_zone_service.cpp
+++ b/src/core/hle/service/time/time_zone_service.cpp
@@ -140,11 +140,12 @@ void ITimeZoneService::ToPosixTime(Kernel::HLERequestContext& ctx) {
return;
}
+ ctx.WriteBuffer(posix_time);
+
// TODO(bunnei): Handle multiple times
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.PushRaw<u32>(1); // Number of times we're returning
- ctx.WriteBuffer(posix_time);
}
void ITimeZoneService::ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) {
@@ -163,10 +164,11 @@ void ITimeZoneService::ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) {
return;
}
+ ctx.WriteBuffer(posix_time);
+
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.PushRaw<u32>(1); // Number of times we're returning
- ctx.WriteBuffer(posix_time);
}
} // namespace Service::Time
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index a1a7ac987..7ae07d072 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -15,6 +15,7 @@
#include "common/common_funcs.h"
#include "common/logging/log.h"
#include "common/math_util.h"
+#include "common/settings.h"
#include "common/swap.h"
#include "core/core_timing.h"
#include "core/hle/ipc_helpers.h"
@@ -30,7 +31,6 @@
#include "core/hle/service/vi/vi_m.h"
#include "core/hle/service/vi/vi_s.h"
#include "core/hle/service/vi/vi_u.h"
-#include "core/settings.h"
namespace Service::VI {
@@ -1129,9 +1129,11 @@ private:
}
NativeWindow native_window{*buffer_queue_id};
+ const auto buffer_size = ctx.WriteBuffer(native_window.Serialize());
+
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
- rb.Push<u64>(ctx.WriteBuffer(native_window.Serialize()));
+ rb.Push<u64>(buffer_size);
}
void CloseLayer(Kernel::HLERequestContext& ctx) {
@@ -1173,10 +1175,12 @@ private:
}
NativeWindow native_window{*buffer_queue_id};
+ const auto buffer_size = ctx.WriteBuffer(native_window.Serialize());
+
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS);
rb.Push(*layer_id);
- rb.Push<u64>(ctx.WriteBuffer(native_window.Serialize()));
+ rb.Push<u64>(buffer_size);
}
void DestroyStrayLayer(Kernel::HLERequestContext& ctx) {