summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Zach Hilman2018-11-11 16:41:31 -0500
committerGravatar Zach Hilman2018-11-18 10:53:47 -0500
commitfed6ab14c37f196f2a2fd378b46d7e5bd0118224 (patch)
tree9e199e88df8e5a35e1f18d7a2f2ca29373d90367 /src
parentam: Deglobalize software keyboard applet (diff)
downloadyuzu-fed6ab14c37f196f2a2fd378b46d7e5bd0118224.tar.gz
yuzu-fed6ab14c37f196f2a2fd378b46d7e5bd0118224.tar.xz
yuzu-fed6ab14c37f196f2a2fd378b46d7e5bd0118224.zip
am: Implement text check software keyboard mode
Allows the game to verify and send a message to the frontend.
Diffstat (limited to 'src')
-rw-r--r--src/core/frontend/applets/software_keyboard.cpp6
-rw-r--r--src/core/frontend/applets/software_keyboard.h2
-rw-r--r--src/core/hle/service/am/am.cpp37
-rw-r--r--src/core/hle/service/am/applets/applets.h5
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.cpp67
-rw-r--r--src/yuzu/main.cpp17
6 files changed, 120 insertions, 14 deletions
diff --git a/src/core/frontend/applets/software_keyboard.cpp b/src/core/frontend/applets/software_keyboard.cpp
index 41d81c293..05e2dc6b7 100644
--- a/src/core/frontend/applets/software_keyboard.cpp
+++ b/src/core/frontend/applets/software_keyboard.cpp
@@ -18,4 +18,10 @@ bool DefaultSoftwareKeyboardApplet::GetText(SoftwareKeyboardParameters parameter
18 return true; 18 return true;
19} 19}
20 20
21void DefaultSoftwareKeyboardApplet::SendTextCheckDialog(std::u16string error_message) const {
22 LOG_WARNING(Service_AM,
23 "(STUBBED) called - Default fallback software keyboard does not support text "
24 "check! (error_message={})",
25 Common::UTF16ToUTF8(error_message));
26}
21} // namespace Core::Frontend 27} // namespace Core::Frontend
diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h
index 2ea9db889..0a82aac0d 100644
--- a/src/core/frontend/applets/software_keyboard.h
+++ b/src/core/frontend/applets/software_keyboard.h
@@ -36,11 +36,13 @@ public:
36 virtual ~SoftwareKeyboardApplet(); 36 virtual ~SoftwareKeyboardApplet();
37 37
38 virtual bool GetText(SoftwareKeyboardParameters parameters, std::u16string& text) const = 0; 38 virtual bool GetText(SoftwareKeyboardParameters parameters, std::u16string& text) const = 0;
39 virtual void SendTextCheckDialog(std::u16string error_message) const = 0;
39}; 40};
40 41
41class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet { 42class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet {
42public: 43public:
43 bool GetText(SoftwareKeyboardParameters parameters, std::u16string& text) const override; 44 bool GetText(SoftwareKeyboardParameters parameters, std::u16string& text) const override;
45 void SendTextCheckDialog(std::u16string error_message) const override;
44}; 46};
45 47
46} // namespace Core::Frontend 48} // namespace Core::Frontend
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index fc464270e..ea00c5c72 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -544,7 +544,7 @@ public:
544 {102, nullptr, "PushExtraStorage"}, 544 {102, nullptr, "PushExtraStorage"},
545 {103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"}, 545 {103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"},
546 {104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"}, 546 {104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"},
547 {105, nullptr, "GetPopOutDataEvent"}, 547 {105, &ILibraryAppletAccessor::GetPopOutDataEvent, "GetPopOutDataEvent"},
548 {106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"}, 548 {106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"},
549 {110, nullptr, "NeedsToExitProcess"}, 549 {110, nullptr, "NeedsToExitProcess"},
550 {120, nullptr, "GetLibraryAppletInfo"}, 550 {120, nullptr, "GetLibraryAppletInfo"},
@@ -558,6 +558,8 @@ public:
558 auto& kernel = Core::System::GetInstance().Kernel(); 558 auto& kernel = Core::System::GetInstance().Kernel();
559 state_changed_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, 559 state_changed_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
560 "ILibraryAppletAccessor:StateChangedEvent"); 560 "ILibraryAppletAccessor:StateChangedEvent");
561 pop_out_data_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
562 "ILibraryAppletAccessor:PopDataOutEvent");
561 pop_interactive_out_data_event = 563 pop_interactive_out_data_event =
562 Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, 564 Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
563 "ILibraryAppletAccessor:PopInteractiveDataOutEvent"); 565 "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
@@ -585,9 +587,16 @@ private:
585 ASSERT(applet != nullptr); 587 ASSERT(applet != nullptr);
586 588
587 applet->Initialize(storage_stack); 589 applet->Initialize(storage_stack);
588 interactive_storage_stack.push_back(std::make_shared<IStorage>(applet->Execute())); 590 const auto data = std::make_shared<IStorage>(applet->Execute());
589 state_changed_event->Signal(); 591 state_changed_event->Signal();
590 pop_interactive_out_data_event->Signal(); 592
593 if (applet->TransactionComplete()) {
594 storage_stack.push_back(data);
595 pop_out_data_event->Signal();
596 } else {
597 interactive_storage_stack.push_back(data);
598 pop_interactive_out_data_event->Signal();
599 }
591 600
592 IPC::ResponseBuilder rb{ctx, 2}; 601 IPC::ResponseBuilder rb{ctx, 2};
593 rb.Push(RESULT_SUCCESS); 602 rb.Push(RESULT_SUCCESS);
@@ -617,6 +626,19 @@ private:
617 IPC::RequestParser rp{ctx}; 626 IPC::RequestParser rp{ctx};
618 interactive_storage_stack.push_back(rp.PopIpcInterface<IStorage>()); 627 interactive_storage_stack.push_back(rp.PopIpcInterface<IStorage>());
619 628
629 ASSERT(applet->IsInitialized());
630 applet->ReceiveInteractiveData(interactive_storage_stack.back());
631 const auto data = std::make_shared<IStorage>(applet->Execute());
632 state_changed_event->Signal();
633
634 if (applet->TransactionComplete()) {
635 storage_stack.push_back(data);
636 pop_out_data_event->Signal();
637 } else {
638 interactive_storage_stack.push_back(data);
639 pop_interactive_out_data_event->Signal();
640 }
641
620 IPC::ResponseBuilder rb{ctx, 2}; 642 IPC::ResponseBuilder rb{ctx, 2};
621 rb.Push(RESULT_SUCCESS); 643 rb.Push(RESULT_SUCCESS);
622 644
@@ -633,9 +655,13 @@ private:
633 LOG_DEBUG(Service_AM, "called"); 655 LOG_DEBUG(Service_AM, "called");
634 } 656 }
635 657
636 void GetPopInteractiveOutDataEvent(Kernel::HLERequestContext& ctx) { 658 void GetPopOutDataEvent(Kernel::HLERequestContext& ctx) {
637 pop_interactive_out_data_event->Signal(); 659 IPC::ResponseBuilder rb{ctx, 2, 1};
660 rb.Push(RESULT_SUCCESS);
661 rb.PushCopyObjects(pop_out_data_event);
662 }
638 663
664 void GetPopInteractiveOutDataEvent(Kernel::HLERequestContext& ctx) {
639 IPC::ResponseBuilder rb{ctx, 2, 1}; 665 IPC::ResponseBuilder rb{ctx, 2, 1};
640 rb.Push(RESULT_SUCCESS); 666 rb.Push(RESULT_SUCCESS);
641 rb.PushCopyObjects(pop_interactive_out_data_event); 667 rb.PushCopyObjects(pop_interactive_out_data_event);
@@ -647,6 +673,7 @@ private:
647 std::vector<std::shared_ptr<IStorage>> storage_stack; 673 std::vector<std::shared_ptr<IStorage>> storage_stack;
648 std::vector<std::shared_ptr<IStorage>> interactive_storage_stack; 674 std::vector<std::shared_ptr<IStorage>> interactive_storage_stack;
649 Kernel::SharedPtr<Kernel::Event> state_changed_event; 675 Kernel::SharedPtr<Kernel::Event> state_changed_event;
676 Kernel::SharedPtr<Kernel::Event> pop_out_data_event;
650 Kernel::SharedPtr<Kernel::Event> pop_interactive_out_data_event; 677 Kernel::SharedPtr<Kernel::Event> pop_interactive_out_data_event;
651}; 678};
652 679
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h
index 47db22fb4..6d90eb608 100644
--- a/src/core/hle/service/am/applets/applets.h
+++ b/src/core/hle/service/am/applets/applets.h
@@ -8,6 +8,8 @@
8#include <vector> 8#include <vector>
9#include "common/swap.h" 9#include "common/swap.h"
10 10
11union ResultCode;
12
11namespace Frontend { 13namespace Frontend {
12class SoftwareKeyboardApplet; 14class SoftwareKeyboardApplet;
13} 15}
@@ -25,6 +27,9 @@ public:
25 27
26 virtual void Initialize(std::vector<std::shared_ptr<IStorage>> storage); 28 virtual void Initialize(std::vector<std::shared_ptr<IStorage>> storage);
27 29
30 virtual bool TransactionComplete() const = 0;
31 virtual ResultCode GetStatus() const = 0;
32 virtual void ReceiveInteractiveData(std::shared_ptr<IStorage> storage) = 0;
28 virtual IStorage Execute() = 0; 33 virtual IStorage Execute() = 0;
29 34
30 bool IsInitialized() const { 35 bool IsInitialized() const {
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp
index 556dea3e4..044a16264 100644
--- a/src/core/hle/service/am/applets/software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/software_keyboard.cpp
@@ -50,28 +50,77 @@ void SoftwareKeyboard::Initialize(std::vector<std::shared_ptr<IStorage>> storage
50 ASSERT(keyboard_config.size() >= sizeof(KeyboardConfig)); 50 ASSERT(keyboard_config.size() >= sizeof(KeyboardConfig));
51 std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig)); 51 std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig));
52 52
53 ASSERT_MSG(config.text_check == 0, "Text check software keyboard mode is not implemented!");
54
55 const auto& work_buffer = storage_stack[2]->GetData(); 53 const auto& work_buffer = storage_stack[2]->GetData();
56 std::memcpy(initial_text.data(), work_buffer.data() + config.initial_string_offset, 54
57 config.initial_string_size); 55 if (config.initial_string_size == 0)
56 return;
57
58 std::vector<char16_t> string(config.initial_string_size);
59 std::memcpy(string.data(), work_buffer.data() + 4, string.size() * 2);
60 initial_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size());
61}
62
63bool SoftwareKeyboard::TransactionComplete() const {
64 return complete;
65}
66
67ResultCode SoftwareKeyboard::GetStatus() const {
68 return RESULT_SUCCESS;
69}
70
71void SoftwareKeyboard::ReceiveInteractiveData(std::shared_ptr<IStorage> storage) {
72 if (complete)
73 return;
74
75 const auto data = storage->GetData();
76 const auto status = static_cast<bool>(data[0]);
77
78 if (status == INTERACTIVE_STATUS_OK) {
79 complete = true;
80 } else {
81 const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()};
82
83 std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string;
84 std::memcpy(string.data(), data.data() + 4, string.size() * 2);
85 frontend.SendTextCheckDialog(
86 Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size()));
87 }
58} 88}
59 89
60IStorage SoftwareKeyboard::Execute() { 90IStorage SoftwareKeyboard::Execute() {
61 const auto frontend{GetSoftwareKeyboard()}; 91 if (complete)
62 ASSERT(frontend != nullptr); 92 return IStorage{final_data};
93
94 const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()};
63 95
64 const auto parameters = ConvertToFrontendParameters(config, initial_text); 96 const auto parameters = ConvertToFrontendParameters(config, initial_text);
65 97
66 std::u16string text; 98 std::u16string text;
67 const auto success = frontend->GetText(parameters, text); 99 const auto success = frontend.GetText(parameters, text);
68 100
69 std::vector<u8> output(SWKBD_OUTPUT_BUFFER_SIZE); 101 std::vector<u8> output(SWKBD_OUTPUT_BUFFER_SIZE);
70 102
71 if (success) { 103 if (success) {
72 output[0] = 1; 104 if (config.text_check) {
105 const auto size = static_cast<u32>(text.size() * 2 + 4);
106 std::memcpy(output.data(), &size, sizeof(u32));
107 } else {
108 output[0] = 1;
109 }
110
73 std::memcpy(output.data() + 4, text.data(), 111 std::memcpy(output.data() + 4, text.data(),
74 std::min<std::size_t>(text.size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 4)); 112 std::min(text.size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 4));
113 } else {
114 complete = true;
115 final_data = std::move(output);
116 return IStorage{final_data};
117 }
118
119 complete = !config.text_check;
120
121 if (complete) {
122 final_data = std::move(output);
123 return IStorage{final_data};
75 } 124 }
76 125
77 return IStorage{output}; 126 return IStorage{output};
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 9b2c09f32..447d9dece 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -61,6 +61,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
61#include "core/file_sys/romfs.h" 61#include "core/file_sys/romfs.h"
62#include "core/file_sys/savedata_factory.h" 62#include "core/file_sys/savedata_factory.h"
63#include "core/file_sys/submission_package.h" 63#include "core/file_sys/submission_package.h"
64#include "core/frontend/applets/software_keyboard.h"
64#include "core/hle/kernel/process.h" 65#include "core/hle/kernel/process.h"
65#include "core/hle/service/filesystem/filesystem.h" 66#include "core/hle/service/filesystem/filesystem.h"
66#include "core/hle/service/filesystem/fsp_ldr.h" 67#include "core/hle/service/filesystem/fsp_ldr.h"
@@ -206,6 +207,22 @@ GMainWindow::~GMainWindow() {
206 delete render_window; 207 delete render_window;
207} 208}
208 209
210bool GMainWindow::SoftwareKeyboardGetText(
211 const Core::Frontend::SoftwareKeyboardParameters& parameters, std::u16string& text) {
212 QtSoftwareKeyboardDialog dialog(this, parameters);
213 dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
214 Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
215 dialog.setWindowModality(Qt::WindowModal);
216 dialog.exec();
217
218 text = dialog.GetText();
219 return dialog.GetStatus();
220}
221
222void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message) {
223 QMessageBox::warning(this, tr("Text Check Failed"), QString::fromStdU16String(error_message));
224}
225
209void GMainWindow::InitializeWidgets() { 226void GMainWindow::InitializeWidgets() {
210#ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING 227#ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING
211 ui.action_Report_Compatibility->setVisible(true); 228 ui.action_Report_Compatibility->setVisible(true);