summaryrefslogtreecommitdiff
path: root/src/core/hle/applets
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/applets')
-rw-r--r--src/core/hle/applets/applet.cpp130
-rw-r--r--src/core/hle/applets/applet.h83
-rw-r--r--src/core/hle/applets/erreula.cpp72
-rw-r--r--src/core/hle/applets/erreula.h29
-rw-r--r--src/core/hle/applets/mii_selector.cpp86
-rw-r--r--src/core/hle/applets/mii_selector.h78
-rw-r--r--src/core/hle/applets/mint.cpp72
-rw-r--r--src/core/hle/applets/mint.h29
-rw-r--r--src/core/hle/applets/swkbd.cpp118
-rw-r--r--src/core/hle/applets/swkbd.h85
10 files changed, 0 insertions, 782 deletions
diff --git a/src/core/hle/applets/applet.cpp b/src/core/hle/applets/applet.cpp
deleted file mode 100644
index 9c43ed2fd..000000000
--- a/src/core/hle/applets/applet.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <cstddef>
6#include <memory>
7#include <type_traits>
8#include <unordered_map>
9#include "common/assert.h"
10#include "common/common_types.h"
11#include "core/core_timing.h"
12#include "core/hle/applets/applet.h"
13#include "core/hle/applets/erreula.h"
14#include "core/hle/applets/mii_selector.h"
15#include "core/hle/applets/mint.h"
16#include "core/hle/applets/swkbd.h"
17#include "core/hle/result.h"
18#include "core/hle/service/apt/apt.h"
19
20////////////////////////////////////////////////////////////////////////////////////////////////////
21
22// Specializes std::hash for AppletId, so that we can use it in std::unordered_map.
23// Workaround for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970
24namespace std {
25template <>
26struct hash<Service::APT::AppletId> {
27 typedef Service::APT::AppletId argument_type;
28 typedef std::size_t result_type;
29
30 result_type operator()(const argument_type& id_code) const {
31 typedef std::underlying_type<argument_type>::type Type;
32 return std::hash<Type>()(static_cast<Type>(id_code));
33 }
34};
35}
36
37namespace HLE {
38namespace Applets {
39
40static std::unordered_map<Service::APT::AppletId, std::shared_ptr<Applet>> applets;
41static u32 applet_update_event =
42 -1; ///< The CoreTiming event identifier for the Applet update callback.
43/// The interval at which the Applet update callback will be called, 16.6ms
44static const u64 applet_update_interval_us = 16666;
45
46ResultCode Applet::Create(Service::APT::AppletId id) {
47 switch (id) {
48 case Service::APT::AppletId::SoftwareKeyboard1:
49 case Service::APT::AppletId::SoftwareKeyboard2:
50 applets[id] = std::make_shared<SoftwareKeyboard>(id);
51 break;
52 case Service::APT::AppletId::Ed1:
53 case Service::APT::AppletId::Ed2:
54 applets[id] = std::make_shared<MiiSelector>(id);
55 break;
56 case Service::APT::AppletId::Error:
57 case Service::APT::AppletId::Error2:
58 applets[id] = std::make_shared<ErrEula>(id);
59 break;
60 case Service::APT::AppletId::Mint:
61 case Service::APT::AppletId::Mint2:
62 applets[id] = std::make_shared<Mint>(id);
63 break;
64 default:
65 LOG_ERROR(Service_APT, "Could not create applet %u", id);
66 // TODO(Subv): Find the right error code
67 return ResultCode(ErrorDescription::NotFound, ErrorModule::Applet,
68 ErrorSummary::NotSupported, ErrorLevel::Permanent);
69 }
70
71 return RESULT_SUCCESS;
72}
73
74std::shared_ptr<Applet> Applet::Get(Service::APT::AppletId id) {
75 auto itr = applets.find(id);
76 if (itr != applets.end())
77 return itr->second;
78 return nullptr;
79}
80
81/// Handles updating the current Applet every time it's called.
82static void AppletUpdateEvent(u64 applet_id, int cycles_late) {
83 Service::APT::AppletId id = static_cast<Service::APT::AppletId>(applet_id);
84 std::shared_ptr<Applet> applet = Applet::Get(id);
85 ASSERT_MSG(applet != nullptr, "Applet doesn't exist! applet_id=%08X", id);
86
87 applet->Update();
88
89 // If the applet is still running after the last update, reschedule the event
90 if (applet->IsRunning()) {
91 CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us) - cycles_late,
92 applet_update_event, applet_id);
93 } else {
94 // Otherwise the applet has terminated, in which case we should clean it up
95 applets[id] = nullptr;
96 }
97}
98
99ResultCode Applet::Start(const Service::APT::AppletStartupParameter& parameter) {
100 ResultCode result = StartImpl(parameter);
101 if (result.IsError())
102 return result;
103 // Schedule the update event
104 CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us), applet_update_event,
105 static_cast<u64>(id));
106 return result;
107}
108
109bool Applet::IsRunning() const {
110 return is_running;
111}
112
113bool IsLibraryAppletRunning() {
114 // Check the applets map for instances of any applet
115 for (auto itr = applets.begin(); itr != applets.end(); ++itr)
116 if (itr->second != nullptr)
117 return true;
118 return false;
119}
120
121void Init() {
122 // Register the applet update callback
123 applet_update_event = CoreTiming::RegisterEvent("HLE Applet Update Event", AppletUpdateEvent);
124}
125
126void Shutdown() {
127 CoreTiming::RemoveEvent(applet_update_event);
128}
129}
130} // namespace
diff --git a/src/core/hle/applets/applet.h b/src/core/hle/applets/applet.h
deleted file mode 100644
index ebeed9813..000000000
--- a/src/core/hle/applets/applet.h
+++ /dev/null
@@ -1,83 +0,0 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include "core/hle/result.h"
9#include "core/hle/service/apt/apt.h"
10
11namespace HLE {
12namespace Applets {
13
14class Applet {
15public:
16 virtual ~Applet() = default;
17
18 /**
19 * Creates an instance of the Applet subclass identified by the parameter.
20 * and stores it in a global map.
21 * @param id Id of the applet to create.
22 * @returns ResultCode Whether the operation was successful or not.
23 */
24 static ResultCode Create(Service::APT::AppletId id);
25
26 /**
27 * Retrieves the Applet instance identified by the specified id.
28 * @param id Id of the Applet to retrieve.
29 * @returns Requested Applet or nullptr if not found.
30 */
31 static std::shared_ptr<Applet> Get(Service::APT::AppletId id);
32
33 /**
34 * Handles a parameter from the application.
35 * @param parameter Parameter data to handle.
36 * @returns ResultCode Whether the operation was successful or not.
37 */
38 virtual ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) = 0;
39
40 /**
41 * Handles the Applet start event, triggered from the application.
42 * @param parameter Parameter data to handle.
43 * @returns ResultCode Whether the operation was successful or not.
44 */
45 ResultCode Start(const Service::APT::AppletStartupParameter& parameter);
46
47 /**
48 * Whether the applet is currently executing instead of the host application or not.
49 */
50 bool IsRunning() const;
51
52 /**
53 * Handles an update tick for the Applet, lets it update the screen, send commands, etc.
54 */
55 virtual void Update() = 0;
56
57protected:
58 explicit Applet(Service::APT::AppletId id) : id(id) {}
59
60 /**
61 * Handles the Applet start event, triggered from the application.
62 * @param parameter Parameter data to handle.
63 * @returns ResultCode Whether the operation was successful or not.
64 */
65 virtual ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) = 0;
66
67 Service::APT::AppletId id; ///< Id of this Applet
68 std::shared_ptr<std::vector<u8>> heap_memory; ///< Heap memory for this Applet
69
70 /// Whether this applet is currently running instead of the host application or not.
71 bool is_running = false;
72};
73
74/// Returns whether a library applet is currently running
75bool IsLibraryAppletRunning();
76
77/// Initializes the HLE applets
78void Init();
79
80/// Shuts down the HLE applets
81void Shutdown();
82}
83} // namespace
diff --git a/src/core/hle/applets/erreula.cpp b/src/core/hle/applets/erreula.cpp
deleted file mode 100644
index 518f371f5..000000000
--- a/src/core/hle/applets/erreula.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/string_util.h"
6#include "core/hle/applets/erreula.h"
7#include "core/hle/service/apt/apt.h"
8
9namespace HLE {
10namespace Applets {
11
12ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& parameter) {
13 if (parameter.signal != static_cast<u32>(Service::APT::SignalType::Request)) {
14 LOG_ERROR(Service_APT, "unsupported signal %u", parameter.signal);
15 UNIMPLEMENTED();
16 // TODO(Subv): Find the right error code
17 return ResultCode(-1);
18 }
19
20 // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared
21 // memory.
22 // Create the SharedMemory that will hold the framebuffer data
23 Service::APT::CaptureBufferInfo capture_info;
24 ASSERT(sizeof(capture_info) == parameter.buffer.size());
25
26 memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info));
27
28 // TODO: allocated memory never released
29 using Kernel::MemoryPermission;
30 // Allocate a heap block of the required size for this applet.
31 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
32 // Create a SharedMemory that directly points to this heap block.
33 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(
34 heap_memory, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite,
35 "ErrEula Memory");
36
37 // Send the response message with the newly created SharedMemory
38 Service::APT::MessageParameter result;
39 result.signal = static_cast<u32>(Service::APT::SignalType::Response);
40 result.buffer.clear();
41 result.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
42 result.sender_id = static_cast<u32>(id);
43 result.object = framebuffer_memory;
44
45 Service::APT::SendParameter(result);
46 return RESULT_SUCCESS;
47}
48
49ResultCode ErrEula::StartImpl(const Service::APT::AppletStartupParameter& parameter) {
50 is_running = true;
51
52 // TODO(Subv): Set the expected fields in the response buffer before resending it to the
53 // application.
54 // TODO(Subv): Reverse the parameter format for the ErrEula applet
55
56 // Let the application know that we're closing
57 Service::APT::MessageParameter message;
58 message.buffer.resize(parameter.buffer.size());
59 std::fill(message.buffer.begin(), message.buffer.end(), 0);
60 message.signal = static_cast<u32>(Service::APT::SignalType::WakeupByExit);
61 message.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
62 message.sender_id = static_cast<u32>(id);
63 Service::APT::SendParameter(message);
64
65 is_running = false;
66 return RESULT_SUCCESS;
67}
68
69void ErrEula::Update() {}
70
71} // namespace Applets
72} // namespace HLE
diff --git a/src/core/hle/applets/erreula.h b/src/core/hle/applets/erreula.h
deleted file mode 100644
index 681bbea0c..000000000
--- a/src/core/hle/applets/erreula.h
+++ /dev/null
@@ -1,29 +0,0 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/applets/applet.h"
8#include "core/hle/kernel/shared_memory.h"
9
10namespace HLE {
11namespace Applets {
12
13class ErrEula final : public Applet {
14public:
15 explicit ErrEula(Service::APT::AppletId id) : Applet(id) {}
16
17 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override;
18 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override;
19 void Update() override;
20
21private:
22 /// This SharedMemory will be created when we receive the LibAppJustStarted message.
23 /// It holds the framebuffer info retrieved by the application with
24 /// GSPGPU::ImportDisplayCaptureInfo
25 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory;
26};
27
28} // namespace Applets
29} // namespace HLE
diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp
deleted file mode 100644
index f225c23a5..000000000
--- a/src/core/hle/applets/mii_selector.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <cstring>
6#include <string>
7#include "common/assert.h"
8#include "common/logging/log.h"
9#include "common/string_util.h"
10#include "core/hle/applets/mii_selector.h"
11#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/shared_memory.h"
13#include "core/hle/result.h"
14
15////////////////////////////////////////////////////////////////////////////////////////////////////
16
17namespace HLE {
18namespace Applets {
19
20ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& parameter) {
21 if (parameter.signal != static_cast<u32>(Service::APT::SignalType::Request)) {
22 LOG_ERROR(Service_APT, "unsupported signal %u", parameter.signal);
23 UNIMPLEMENTED();
24 // TODO(Subv): Find the right error code
25 return ResultCode(-1);
26 }
27
28 // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared
29 // memory.
30 // Create the SharedMemory that will hold the framebuffer data
31 Service::APT::CaptureBufferInfo capture_info;
32 ASSERT(sizeof(capture_info) == parameter.buffer.size());
33
34 memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info));
35
36 using Kernel::MemoryPermission;
37 // Allocate a heap block of the required size for this applet.
38 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
39 // Create a SharedMemory that directly points to this heap block.
40 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(
41 heap_memory, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite,
42 "MiiSelector Memory");
43
44 // Send the response message with the newly created SharedMemory
45 Service::APT::MessageParameter result;
46 result.signal = static_cast<u32>(Service::APT::SignalType::Response);
47 result.buffer.clear();
48 result.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
49 result.sender_id = static_cast<u32>(id);
50 result.object = framebuffer_memory;
51
52 Service::APT::SendParameter(result);
53 return RESULT_SUCCESS;
54}
55
56ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& parameter) {
57 is_running = true;
58
59 // TODO(Subv): Set the expected fields in the response buffer before resending it to the
60 // application.
61 // TODO(Subv): Reverse the parameter format for the Mii Selector
62
63 memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
64
65 // TODO(Subv): Find more about this structure, result code 0 is enough to let most games
66 // continue.
67 MiiResult result;
68 memset(&result, 0, sizeof(result));
69 result.return_code = 0;
70
71 // Let the application know that we're closing
72 Service::APT::MessageParameter message;
73 message.buffer.resize(sizeof(MiiResult));
74 std::memcpy(message.buffer.data(), &result, message.buffer.size());
75 message.signal = static_cast<u32>(Service::APT::SignalType::WakeupByExit);
76 message.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
77 message.sender_id = static_cast<u32>(id);
78 Service::APT::SendParameter(message);
79
80 is_running = false;
81 return RESULT_SUCCESS;
82}
83
84void MiiSelector::Update() {}
85} // namespace Applets
86} // namespace HLE
diff --git a/src/core/hle/applets/mii_selector.h b/src/core/hle/applets/mii_selector.h
deleted file mode 100644
index 136ce8948..000000000
--- a/src/core/hle/applets/mii_selector.h
+++ /dev/null
@@ -1,78 +0,0 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_funcs.h"
8#include "common/common_types.h"
9#include "core/hle/applets/applet.h"
10#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/shared_memory.h"
12#include "core/hle/result.h"
13#include "core/hle/service/apt/apt.h"
14
15namespace HLE {
16namespace Applets {
17
18struct MiiConfig {
19 u8 enable_cancel_button;
20 u8 enable_guest_mii;
21 u8 show_on_top_screen;
22 INSERT_PADDING_BYTES(5);
23 u16 title[0x40];
24 INSERT_PADDING_BYTES(4);
25 u8 show_guest_miis;
26 INSERT_PADDING_BYTES(3);
27 u32 initially_selected_mii_index;
28 u8 guest_mii_whitelist[6];
29 u8 user_mii_whitelist[0x64];
30 INSERT_PADDING_BYTES(2);
31 u32 magic_value;
32};
33static_assert(sizeof(MiiConfig) == 0x104, "MiiConfig structure has incorrect size");
34#define ASSERT_REG_POSITION(field_name, position) \
35 static_assert(offsetof(MiiConfig, field_name) == position, \
36 "Field " #field_name " has invalid position")
37ASSERT_REG_POSITION(title, 0x08);
38ASSERT_REG_POSITION(show_guest_miis, 0x8C);
39ASSERT_REG_POSITION(initially_selected_mii_index, 0x90);
40ASSERT_REG_POSITION(guest_mii_whitelist, 0x94);
41#undef ASSERT_REG_POSITION
42
43struct MiiResult {
44 u32 return_code;
45 u32 is_guest_mii_selected;
46 u32 selected_guest_mii_index;
47 // TODO(mailwl): expand to Mii Format structure: https://www.3dbrew.org/wiki/Mii
48 u8 selected_mii_data[0x5C];
49 INSERT_PADDING_BYTES(2);
50 u16 mii_data_checksum;
51 u16 guest_mii_name[0xC];
52};
53static_assert(sizeof(MiiResult) == 0x84, "MiiResult structure has incorrect size");
54#define ASSERT_REG_POSITION(field_name, position) \
55 static_assert(offsetof(MiiResult, field_name) == position, \
56 "Field " #field_name " has invalid position")
57ASSERT_REG_POSITION(selected_mii_data, 0x0C);
58ASSERT_REG_POSITION(guest_mii_name, 0x6C);
59#undef ASSERT_REG_POSITION
60
61class MiiSelector final : public Applet {
62public:
63 MiiSelector(Service::APT::AppletId id) : Applet(id) {}
64
65 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override;
66 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override;
67 void Update() override;
68
69private:
70 /// This SharedMemory will be created when we receive the LibAppJustStarted message.
71 /// It holds the framebuffer info retrieved by the application with
72 /// GSPGPU::ImportDisplayCaptureInfo
73 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory;
74
75 MiiConfig config;
76};
77} // namespace Applets
78} // namespace HLE
diff --git a/src/core/hle/applets/mint.cpp b/src/core/hle/applets/mint.cpp
deleted file mode 100644
index 50d79190b..000000000
--- a/src/core/hle/applets/mint.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/string_util.h"
6#include "core/hle/applets/mint.h"
7#include "core/hle/service/apt/apt.h"
8
9namespace HLE {
10namespace Applets {
11
12ResultCode Mint::ReceiveParameter(const Service::APT::MessageParameter& parameter) {
13 if (parameter.signal != static_cast<u32>(Service::APT::SignalType::Request)) {
14 LOG_ERROR(Service_APT, "unsupported signal %u", parameter.signal);
15 UNIMPLEMENTED();
16 // TODO(Subv): Find the right error code
17 return ResultCode(-1);
18 }
19
20 // The Request message contains a buffer with the size of the framebuffer shared
21 // memory.
22 // Create the SharedMemory that will hold the framebuffer data
23 Service::APT::CaptureBufferInfo capture_info;
24 ASSERT(sizeof(capture_info) == parameter.buffer.size());
25
26 memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info));
27
28 // TODO: allocated memory never released
29 using Kernel::MemoryPermission;
30 // Allocate a heap block of the required size for this applet.
31 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
32 // Create a SharedMemory that directly points to this heap block.
33 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(
34 heap_memory, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite,
35 "Mint Memory");
36
37 // Send the response message with the newly created SharedMemory
38 Service::APT::MessageParameter result;
39 result.signal = static_cast<u32>(Service::APT::SignalType::Response);
40 result.buffer.clear();
41 result.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
42 result.sender_id = static_cast<u32>(id);
43 result.object = framebuffer_memory;
44
45 Service::APT::SendParameter(result);
46 return RESULT_SUCCESS;
47}
48
49ResultCode Mint::StartImpl(const Service::APT::AppletStartupParameter& parameter) {
50 is_running = true;
51
52 // TODO(Subv): Set the expected fields in the response buffer before resending it to the
53 // application.
54 // TODO(Subv): Reverse the parameter format for the Mint applet
55
56 // Let the application know that we're closing
57 Service::APT::MessageParameter message;
58 message.buffer.resize(parameter.buffer.size());
59 std::fill(message.buffer.begin(), message.buffer.end(), 0);
60 message.signal = static_cast<u32>(Service::APT::SignalType::WakeupByExit);
61 message.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
62 message.sender_id = static_cast<u32>(id);
63 Service::APT::SendParameter(message);
64
65 is_running = false;
66 return RESULT_SUCCESS;
67}
68
69void Mint::Update() {}
70
71} // namespace Applets
72} // namespace HLE
diff --git a/src/core/hle/applets/mint.h b/src/core/hle/applets/mint.h
deleted file mode 100644
index d23dc40f9..000000000
--- a/src/core/hle/applets/mint.h
+++ /dev/null
@@ -1,29 +0,0 @@
1// Copyright 2016 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/applets/applet.h"
8#include "core/hle/kernel/shared_memory.h"
9
10namespace HLE {
11namespace Applets {
12
13class Mint final : public Applet {
14public:
15 explicit Mint(Service::APT::AppletId id) : Applet(id) {}
16
17 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override;
18 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override;
19 void Update() override;
20
21private:
22 /// This SharedMemory will be created when we receive the Request message.
23 /// It holds the framebuffer info retrieved by the application with
24 /// GSPGPU::ImportDisplayCaptureInfo
25 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory;
26};
27
28} // namespace Applets
29} // namespace HLE
diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp
deleted file mode 100644
index 0bc471a3a..000000000
--- a/src/core/hle/applets/swkbd.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <cstring>
6#include <string>
7#include "common/assert.h"
8#include "common/logging/log.h"
9#include "common/string_util.h"
10#include "core/hle/applets/swkbd.h"
11#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/shared_memory.h"
13#include "core/hle/result.h"
14#include "core/hle/service/gsp_gpu.h"
15#include "core/hle/service/hid/hid.h"
16#include "core/memory.h"
17
18////////////////////////////////////////////////////////////////////////////////////////////////////
19
20namespace HLE {
21namespace Applets {
22
23ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter const& parameter) {
24 if (parameter.signal != static_cast<u32>(Service::APT::SignalType::Request)) {
25 LOG_ERROR(Service_APT, "unsupported signal %u", parameter.signal);
26 UNIMPLEMENTED();
27 // TODO(Subv): Find the right error code
28 return ResultCode(-1);
29 }
30
31 // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared
32 // memory.
33 // Create the SharedMemory that will hold the framebuffer data
34 Service::APT::CaptureBufferInfo capture_info;
35 ASSERT(sizeof(capture_info) == parameter.buffer.size());
36
37 memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info));
38
39 using Kernel::MemoryPermission;
40 // Allocate a heap block of the required size for this applet.
41 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
42 // Create a SharedMemory that directly points to this heap block.
43 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(
44 heap_memory, 0, capture_info.size, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite,
45 "SoftwareKeyboard Memory");
46
47 // Send the response message with the newly created SharedMemory
48 Service::APT::MessageParameter result;
49 result.signal = static_cast<u32>(Service::APT::SignalType::Response);
50 result.buffer.clear();
51 result.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
52 result.sender_id = static_cast<u32>(id);
53 result.object = framebuffer_memory;
54
55 Service::APT::SendParameter(result);
56 return RESULT_SUCCESS;
57}
58
59ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter const& parameter) {
60 ASSERT_MSG(parameter.buffer.size() == sizeof(config),
61 "The size of the parameter (SoftwareKeyboardConfig) is wrong");
62
63 memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
64 text_memory =
65 boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object);
66
67 // TODO(Subv): Verify if this is the correct behavior
68 memset(text_memory->GetPointer(), 0, text_memory->size);
69
70 DrawScreenKeyboard();
71
72 is_running = true;
73 return RESULT_SUCCESS;
74}
75
76void SoftwareKeyboard::Update() {
77 // TODO(Subv): Handle input using the touch events from the HID module
78
79 // TODO(Subv): Remove this hardcoded text
80 std::u16string text = Common::UTF8ToUTF16("Citra");
81 memcpy(text_memory->GetPointer(), text.c_str(), text.length() * sizeof(char16_t));
82
83 // TODO(Subv): Ask for input and write it to the shared memory
84 // TODO(Subv): Find out what are the possible values for the return code,
85 // some games seem to check for a hardcoded 2
86 config.return_code = 2;
87 config.text_length = 6;
88 config.text_offset = 0;
89
90 // TODO(Subv): We're finalizing the applet immediately after it's started,
91 // but we should defer this call until after all the input has been collected.
92 Finalize();
93}
94
95void SoftwareKeyboard::DrawScreenKeyboard() {
96 auto bottom_screen = Service::GSP::GetFrameBufferInfo(0, 1);
97 auto info = bottom_screen->framebuffer_info[bottom_screen->index];
98
99 // TODO(Subv): Draw the HLE keyboard, for now just zero-fill the framebuffer
100 Memory::ZeroBlock(info.address_left, info.stride * 320);
101
102 Service::GSP::SetBufferSwap(1, info);
103}
104
105void SoftwareKeyboard::Finalize() {
106 // Let the application know that we're closing
107 Service::APT::MessageParameter message;
108 message.buffer.resize(sizeof(SoftwareKeyboardConfig));
109 std::memcpy(message.buffer.data(), &config, message.buffer.size());
110 message.signal = static_cast<u32>(Service::APT::SignalType::WakeupByExit);
111 message.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
112 message.sender_id = static_cast<u32>(id);
113 Service::APT::SendParameter(message);
114
115 is_running = false;
116}
117}
118} // namespace
diff --git a/src/core/hle/applets/swkbd.h b/src/core/hle/applets/swkbd.h
deleted file mode 100644
index cc92a8f19..000000000
--- a/src/core/hle/applets/swkbd.h
+++ /dev/null
@@ -1,85 +0,0 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_funcs.h"
8#include "common/common_types.h"
9#include "core/hle/applets/applet.h"
10#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/shared_memory.h"
12#include "core/hle/result.h"
13#include "core/hle/service/apt/apt.h"
14
15namespace HLE {
16namespace Applets {
17
18struct SoftwareKeyboardConfig {
19 INSERT_PADDING_WORDS(0x8);
20
21 u16 max_text_length; ///< Maximum length of the input text
22
23 INSERT_PADDING_BYTES(0x6E);
24
25 char16_t display_text[65]; ///< Text to display when asking the user for input
26
27 INSERT_PADDING_BYTES(0xE);
28
29 u32 default_text_offset; ///< Offset of the default text in the output SharedMemory
30
31 INSERT_PADDING_WORDS(0x3);
32
33 u32 shared_memory_size; ///< Size of the SharedMemory
34
35 INSERT_PADDING_WORDS(0x1);
36
37 u32 return_code; ///< Return code of the SoftwareKeyboard, usually 2, other values are unknown
38
39 INSERT_PADDING_WORDS(0x2);
40
41 u32 text_offset; ///< Offset in the SharedMemory where the output text starts
42 u16 text_length; ///< Length in characters of the output text
43
44 INSERT_PADDING_BYTES(0x2B6);
45};
46
47/**
48 * The size of this structure (0x400) has been verified via reverse engineering of multiple games
49 * that use the software keyboard.
50 */
51static_assert(sizeof(SoftwareKeyboardConfig) == 0x400, "Software Keyboard Config size is wrong");
52
53class SoftwareKeyboard final : public Applet {
54public:
55 SoftwareKeyboard(Service::APT::AppletId id) : Applet(id) {}
56
57 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override;
58 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override;
59 void Update() override;
60
61 /**
62 * Draws a keyboard to the current bottom screen framebuffer.
63 */
64 void DrawScreenKeyboard();
65
66 /**
67 * Sends the LibAppletClosing signal to the application,
68 * along with the relevant data buffers.
69 */
70 void Finalize();
71
72private:
73 /// This SharedMemory will be created when we receive the LibAppJustStarted message.
74 /// It holds the framebuffer info retrieved by the application with
75 /// GSPGPU::ImportDisplayCaptureInfo
76 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory;
77
78 /// SharedMemory where the output text will be stored
79 Kernel::SharedPtr<Kernel::SharedMemory> text_memory;
80
81 /// Configuration of this instance of the SoftwareKeyboard, as received from the application
82 SoftwareKeyboardConfig config;
83};
84}
85} // namespace