mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	am: Implement text check software keyboard mode
Allows the game to verify and send a message to the frontend.
This commit is contained in:
		
							parent
							
								
									e696ed1f4d
								
							
						
					
					
						commit
						fed6ab14c3
					
				@ -18,4 +18,10 @@ bool DefaultSoftwareKeyboardApplet::GetText(SoftwareKeyboardParameters parameter
 | 
				
			|||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void DefaultSoftwareKeyboardApplet::SendTextCheckDialog(std::u16string error_message) const {
 | 
				
			||||||
 | 
					    LOG_WARNING(Service_AM,
 | 
				
			||||||
 | 
					                "(STUBBED) called - Default fallback software keyboard does not support text "
 | 
				
			||||||
 | 
					                "check! (error_message={})",
 | 
				
			||||||
 | 
					                Common::UTF16ToUTF8(error_message));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
} // namespace Core::Frontend
 | 
					} // namespace Core::Frontend
 | 
				
			||||||
 | 
				
			|||||||
@ -36,11 +36,13 @@ public:
 | 
				
			|||||||
    virtual ~SoftwareKeyboardApplet();
 | 
					    virtual ~SoftwareKeyboardApplet();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    virtual bool GetText(SoftwareKeyboardParameters parameters, std::u16string& text) const = 0;
 | 
					    virtual bool GetText(SoftwareKeyboardParameters parameters, std::u16string& text) const = 0;
 | 
				
			||||||
 | 
					    virtual void SendTextCheckDialog(std::u16string error_message) const = 0;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet {
 | 
					class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    bool GetText(SoftwareKeyboardParameters parameters, std::u16string& text) const override;
 | 
					    bool GetText(SoftwareKeyboardParameters parameters, std::u16string& text) const override;
 | 
				
			||||||
 | 
					    void SendTextCheckDialog(std::u16string error_message) const override;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Core::Frontend
 | 
					} // namespace Core::Frontend
 | 
				
			||||||
 | 
				
			|||||||
@ -544,7 +544,7 @@ public:
 | 
				
			|||||||
            {102, nullptr, "PushExtraStorage"},
 | 
					            {102, nullptr, "PushExtraStorage"},
 | 
				
			||||||
            {103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"},
 | 
					            {103, &ILibraryAppletAccessor::PushInteractiveInData, "PushInteractiveInData"},
 | 
				
			||||||
            {104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"},
 | 
					            {104, &ILibraryAppletAccessor::PopInteractiveOutData, "PopInteractiveOutData"},
 | 
				
			||||||
            {105, nullptr, "GetPopOutDataEvent"},
 | 
					            {105, &ILibraryAppletAccessor::GetPopOutDataEvent, "GetPopOutDataEvent"},
 | 
				
			||||||
            {106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"},
 | 
					            {106, &ILibraryAppletAccessor::GetPopInteractiveOutDataEvent, "GetPopInteractiveOutDataEvent"},
 | 
				
			||||||
            {110, nullptr, "NeedsToExitProcess"},
 | 
					            {110, nullptr, "NeedsToExitProcess"},
 | 
				
			||||||
            {120, nullptr, "GetLibraryAppletInfo"},
 | 
					            {120, nullptr, "GetLibraryAppletInfo"},
 | 
				
			||||||
@ -558,6 +558,8 @@ public:
 | 
				
			|||||||
        auto& kernel = Core::System::GetInstance().Kernel();
 | 
					        auto& kernel = Core::System::GetInstance().Kernel();
 | 
				
			||||||
        state_changed_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
 | 
					        state_changed_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
 | 
				
			||||||
                                                    "ILibraryAppletAccessor:StateChangedEvent");
 | 
					                                                    "ILibraryAppletAccessor:StateChangedEvent");
 | 
				
			||||||
 | 
					        pop_out_data_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
 | 
				
			||||||
 | 
					                                                   "ILibraryAppletAccessor:PopDataOutEvent");
 | 
				
			||||||
        pop_interactive_out_data_event =
 | 
					        pop_interactive_out_data_event =
 | 
				
			||||||
            Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
 | 
					            Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
 | 
				
			||||||
                                  "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
 | 
					                                  "ILibraryAppletAccessor:PopInteractiveDataOutEvent");
 | 
				
			||||||
@ -585,9 +587,16 @@ private:
 | 
				
			|||||||
        ASSERT(applet != nullptr);
 | 
					        ASSERT(applet != nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        applet->Initialize(storage_stack);
 | 
					        applet->Initialize(storage_stack);
 | 
				
			||||||
        interactive_storage_stack.push_back(std::make_shared<IStorage>(applet->Execute()));
 | 
					        const auto data = std::make_shared<IStorage>(applet->Execute());
 | 
				
			||||||
        state_changed_event->Signal();
 | 
					        state_changed_event->Signal();
 | 
				
			||||||
        pop_interactive_out_data_event->Signal();
 | 
					
 | 
				
			||||||
 | 
					        if (applet->TransactionComplete()) {
 | 
				
			||||||
 | 
					            storage_stack.push_back(data);
 | 
				
			||||||
 | 
					            pop_out_data_event->Signal();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            interactive_storage_stack.push_back(data);
 | 
				
			||||||
 | 
					            pop_interactive_out_data_event->Signal();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					        IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
        rb.Push(RESULT_SUCCESS);
 | 
					        rb.Push(RESULT_SUCCESS);
 | 
				
			||||||
@ -617,6 +626,19 @@ private:
 | 
				
			|||||||
        IPC::RequestParser rp{ctx};
 | 
					        IPC::RequestParser rp{ctx};
 | 
				
			||||||
        interactive_storage_stack.push_back(rp.PopIpcInterface<IStorage>());
 | 
					        interactive_storage_stack.push_back(rp.PopIpcInterface<IStorage>());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ASSERT(applet->IsInitialized());
 | 
				
			||||||
 | 
					        applet->ReceiveInteractiveData(interactive_storage_stack.back());
 | 
				
			||||||
 | 
					        const auto data = std::make_shared<IStorage>(applet->Execute());
 | 
				
			||||||
 | 
					        state_changed_event->Signal();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (applet->TransactionComplete()) {
 | 
				
			||||||
 | 
					            storage_stack.push_back(data);
 | 
				
			||||||
 | 
					            pop_out_data_event->Signal();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            interactive_storage_stack.push_back(data);
 | 
				
			||||||
 | 
					            pop_interactive_out_data_event->Signal();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2};
 | 
					        IPC::ResponseBuilder rb{ctx, 2};
 | 
				
			||||||
        rb.Push(RESULT_SUCCESS);
 | 
					        rb.Push(RESULT_SUCCESS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -633,9 +655,13 @@ private:
 | 
				
			|||||||
        LOG_DEBUG(Service_AM, "called");
 | 
					        LOG_DEBUG(Service_AM, "called");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void GetPopInteractiveOutDataEvent(Kernel::HLERequestContext& ctx) {
 | 
					    void GetPopOutDataEvent(Kernel::HLERequestContext& ctx) {
 | 
				
			||||||
        pop_interactive_out_data_event->Signal();
 | 
					        IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
				
			||||||
 | 
					        rb.Push(RESULT_SUCCESS);
 | 
				
			||||||
 | 
					        rb.PushCopyObjects(pop_out_data_event);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void GetPopInteractiveOutDataEvent(Kernel::HLERequestContext& ctx) {
 | 
				
			||||||
        IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
					        IPC::ResponseBuilder rb{ctx, 2, 1};
 | 
				
			||||||
        rb.Push(RESULT_SUCCESS);
 | 
					        rb.Push(RESULT_SUCCESS);
 | 
				
			||||||
        rb.PushCopyObjects(pop_interactive_out_data_event);
 | 
					        rb.PushCopyObjects(pop_interactive_out_data_event);
 | 
				
			||||||
@ -647,6 +673,7 @@ private:
 | 
				
			|||||||
    std::vector<std::shared_ptr<IStorage>> storage_stack;
 | 
					    std::vector<std::shared_ptr<IStorage>> storage_stack;
 | 
				
			||||||
    std::vector<std::shared_ptr<IStorage>> interactive_storage_stack;
 | 
					    std::vector<std::shared_ptr<IStorage>> interactive_storage_stack;
 | 
				
			||||||
    Kernel::SharedPtr<Kernel::Event> state_changed_event;
 | 
					    Kernel::SharedPtr<Kernel::Event> state_changed_event;
 | 
				
			||||||
 | 
					    Kernel::SharedPtr<Kernel::Event> pop_out_data_event;
 | 
				
			||||||
    Kernel::SharedPtr<Kernel::Event> pop_interactive_out_data_event;
 | 
					    Kernel::SharedPtr<Kernel::Event> pop_interactive_out_data_event;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,8 @@
 | 
				
			|||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
#include "common/swap.h"
 | 
					#include "common/swap.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					union ResultCode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Frontend {
 | 
					namespace Frontend {
 | 
				
			||||||
class SoftwareKeyboardApplet;
 | 
					class SoftwareKeyboardApplet;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -25,6 +27,9 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    virtual void Initialize(std::vector<std::shared_ptr<IStorage>> storage);
 | 
					    virtual void Initialize(std::vector<std::shared_ptr<IStorage>> storage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    virtual bool TransactionComplete() const = 0;
 | 
				
			||||||
 | 
					    virtual ResultCode GetStatus() const = 0;
 | 
				
			||||||
 | 
					    virtual void ReceiveInteractiveData(std::shared_ptr<IStorage> storage) = 0;
 | 
				
			||||||
    virtual IStorage Execute() = 0;
 | 
					    virtual IStorage Execute() = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool IsInitialized() const {
 | 
					    bool IsInitialized() const {
 | 
				
			||||||
 | 
				
			|||||||
@ -50,28 +50,77 @@ void SoftwareKeyboard::Initialize(std::vector<std::shared_ptr<IStorage>> storage
 | 
				
			|||||||
    ASSERT(keyboard_config.size() >= sizeof(KeyboardConfig));
 | 
					    ASSERT(keyboard_config.size() >= sizeof(KeyboardConfig));
 | 
				
			||||||
    std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig));
 | 
					    std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ASSERT_MSG(config.text_check == 0, "Text check software keyboard mode is not implemented!");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const auto& work_buffer = storage_stack[2]->GetData();
 | 
					    const auto& work_buffer = storage_stack[2]->GetData();
 | 
				
			||||||
    std::memcpy(initial_text.data(), work_buffer.data() + config.initial_string_offset,
 | 
					
 | 
				
			||||||
                config.initial_string_size);
 | 
					    if (config.initial_string_size == 0)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::vector<char16_t> string(config.initial_string_size);
 | 
				
			||||||
 | 
					    std::memcpy(string.data(), work_buffer.data() + 4, string.size() * 2);
 | 
				
			||||||
 | 
					    initial_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(string.data(), string.size());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool SoftwareKeyboard::TransactionComplete() const {
 | 
				
			||||||
 | 
					    return complete;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ResultCode SoftwareKeyboard::GetStatus() const {
 | 
				
			||||||
 | 
					    return RESULT_SUCCESS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void SoftwareKeyboard::ReceiveInteractiveData(std::shared_ptr<IStorage> storage) {
 | 
				
			||||||
 | 
					    if (complete)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto data = storage->GetData();
 | 
				
			||||||
 | 
					    const auto status = static_cast<bool>(data[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (status == INTERACTIVE_STATUS_OK) {
 | 
				
			||||||
 | 
					        complete = true;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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()));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
IStorage SoftwareKeyboard::Execute() {
 | 
					IStorage SoftwareKeyboard::Execute() {
 | 
				
			||||||
    const auto frontend{GetSoftwareKeyboard()};
 | 
					    if (complete)
 | 
				
			||||||
    ASSERT(frontend != nullptr);
 | 
					        return IStorage{final_data};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const auto parameters = ConvertToFrontendParameters(config, initial_text);
 | 
					    const auto parameters = ConvertToFrontendParameters(config, initial_text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::u16string text;
 | 
					    std::u16string text;
 | 
				
			||||||
    const auto success = frontend->GetText(parameters, text);
 | 
					    const auto success = frontend.GetText(parameters, text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::vector<u8> output(SWKBD_OUTPUT_BUFFER_SIZE);
 | 
					    std::vector<u8> output(SWKBD_OUTPUT_BUFFER_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (success) {
 | 
					    if (success) {
 | 
				
			||||||
        output[0] = 1;
 | 
					        if (config.text_check) {
 | 
				
			||||||
 | 
					            const auto size = static_cast<u32>(text.size() * 2 + 4);
 | 
				
			||||||
 | 
					            std::memcpy(output.data(), &size, sizeof(u32));
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            output[0] = 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::memcpy(output.data() + 4, text.data(),
 | 
					        std::memcpy(output.data() + 4, text.data(),
 | 
				
			||||||
                    std::min<std::size_t>(text.size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 4));
 | 
					                    std::min(text.size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 4));
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        complete = true;
 | 
				
			||||||
 | 
					        final_data = std::move(output);
 | 
				
			||||||
 | 
					        return IStorage{final_data};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    complete = !config.text_check;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (complete) {
 | 
				
			||||||
 | 
					        final_data = std::move(output);
 | 
				
			||||||
 | 
					        return IStorage{final_data};
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return IStorage{output};
 | 
					    return IStorage{output};
 | 
				
			||||||
 | 
				
			|||||||
@ -61,6 +61,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
 | 
				
			|||||||
#include "core/file_sys/romfs.h"
 | 
					#include "core/file_sys/romfs.h"
 | 
				
			||||||
#include "core/file_sys/savedata_factory.h"
 | 
					#include "core/file_sys/savedata_factory.h"
 | 
				
			||||||
#include "core/file_sys/submission_package.h"
 | 
					#include "core/file_sys/submission_package.h"
 | 
				
			||||||
 | 
					#include "core/frontend/applets/software_keyboard.h"
 | 
				
			||||||
#include "core/hle/kernel/process.h"
 | 
					#include "core/hle/kernel/process.h"
 | 
				
			||||||
#include "core/hle/service/filesystem/filesystem.h"
 | 
					#include "core/hle/service/filesystem/filesystem.h"
 | 
				
			||||||
#include "core/hle/service/filesystem/fsp_ldr.h"
 | 
					#include "core/hle/service/filesystem/fsp_ldr.h"
 | 
				
			||||||
@ -206,6 +207,22 @@ GMainWindow::~GMainWindow() {
 | 
				
			|||||||
        delete render_window;
 | 
					        delete render_window;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool GMainWindow::SoftwareKeyboardGetText(
 | 
				
			||||||
 | 
					    const Core::Frontend::SoftwareKeyboardParameters& parameters, std::u16string& text) {
 | 
				
			||||||
 | 
					    QtSoftwareKeyboardDialog dialog(this, parameters);
 | 
				
			||||||
 | 
					    dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
 | 
				
			||||||
 | 
					                          Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
 | 
				
			||||||
 | 
					    dialog.setWindowModality(Qt::WindowModal);
 | 
				
			||||||
 | 
					    dialog.exec();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    text = dialog.GetText();
 | 
				
			||||||
 | 
					    return dialog.GetStatus();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message) {
 | 
				
			||||||
 | 
					    QMessageBox::warning(this, tr("Text Check Failed"), QString::fromStdU16String(error_message));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void GMainWindow::InitializeWidgets() {
 | 
					void GMainWindow::InitializeWidgets() {
 | 
				
			||||||
#ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING
 | 
					#ifdef YUZU_ENABLE_COMPATIBILITY_REPORTING
 | 
				
			||||||
    ui.action_Report_Compatibility->setVisible(true);
 | 
					    ui.action_Report_Compatibility->setVisible(true);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user