summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/CMakeLists.txt4
-rw-r--r--src/core/hle/applets/applet.cpp40
-rw-r--r--src/core/hle/applets/applet.h53
-rw-r--r--src/core/hle/applets/swkbd.cpp73
-rw-r--r--src/core/hle/applets/swkbd.h67
-rw-r--r--src/core/hle/service/apt/apt.cpp139
-rw-r--r--src/core/hle/service/apt/apt.h49
-rw-r--r--src/core/hle/service/apt/apt_a.cpp31
-rw-r--r--src/core/hle/service/apt/apt_u.cpp4
9 files changed, 410 insertions, 50 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 4fcda4874..9b004440c 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -25,6 +25,8 @@ set(SRCS
25 file_sys/ivfc_archive.cpp 25 file_sys/ivfc_archive.cpp
26 hle/config_mem.cpp 26 hle/config_mem.cpp
27 hle/hle.cpp 27 hle/hle.cpp
28 hle/applets/applet.cpp
29 hle/applets/swkbd.cpp
28 hle/kernel/address_arbiter.cpp 30 hle/kernel/address_arbiter.cpp
29 hle/kernel/event.cpp 31 hle/kernel/event.cpp
30 hle/kernel/kernel.cpp 32 hle/kernel/kernel.cpp
@@ -150,6 +152,8 @@ set(HEADERS
150 hle/config_mem.h 152 hle/config_mem.h
151 hle/function_wrappers.h 153 hle/function_wrappers.h
152 hle/hle.h 154 hle/hle.h
155 hle/applets/applet.h
156 hle/applets/swkbd.h
153 hle/kernel/address_arbiter.h 157 hle/kernel/address_arbiter.h
154 hle/kernel/event.h 158 hle/kernel/event.h
155 hle/kernel/kernel.h 159 hle/kernel/kernel.h
diff --git a/src/core/hle/applets/applet.cpp b/src/core/hle/applets/applet.cpp
new file mode 100644
index 000000000..1f447e5fc
--- /dev/null
+++ b/src/core/hle/applets/applet.cpp
@@ -0,0 +1,40 @@
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 "common/assert.h"
6#include "common/logging/log.h"
7
8#include "core/hle/applets/applet.h"
9#include "core/hle/applets/swkbd.h"
10
11////////////////////////////////////////////////////////////////////////////////////////////////////
12
13namespace HLE {
14namespace Applets {
15
16static std::unordered_map<Service::APT::AppletId, std::shared_ptr<Applet>> applets;
17
18ResultCode Applet::Create(Service::APT::AppletId id) {
19 switch (id) {
20 case Service::APT::AppletId::SoftwareKeyboard1:
21 case Service::APT::AppletId::SoftwareKeyboard2:
22 applets[id] = std::make_shared<SoftwareKeyboard>(id);
23 break;
24 default:
25 // TODO(Subv): Find the right error code
26 return ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotSupported, ErrorLevel::Permanent);
27 }
28
29 return RESULT_SUCCESS;
30}
31
32std::shared_ptr<Applet> Applet::Get(Service::APT::AppletId id) {
33 auto itr = applets.find(id);
34 if (itr != applets.end())
35 return itr->second;
36 return nullptr;
37}
38
39}
40} // namespace
diff --git a/src/core/hle/applets/applet.h b/src/core/hle/applets/applet.h
new file mode 100644
index 000000000..221348d9c
--- /dev/null
+++ b/src/core/hle/applets/applet.h
@@ -0,0 +1,53 @@
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_types.h"
8#include "core/hle/kernel/kernel.h"
9#include "core/hle/kernel/shared_memory.h"
10#include "core/hle/service/apt/apt.h"
11
12namespace HLE {
13namespace Applets {
14
15class Applet {
16public:
17 virtual ~Applet() {};
18 Applet(Service::APT::AppletId id) : id(id) {};
19
20 /**
21 * Creates an instance of the Applet subclass identified by the parameter
22 * and stores it in a global map.
23 * @param id Id of the applet to create
24 * @returns ResultCode Whether the operation was successful or not
25 */
26 static ResultCode Create(Service::APT::AppletId id);
27
28 /**
29 * Retrieves the Applet instance identified by the specified id
30 * @param id Id of the Applet to retrieve
31 * @returns Requested Applet or nullptr if not found
32 */
33 static std::shared_ptr<Applet> Get(Service::APT::AppletId id);
34
35 /**
36 * Handles a parameter from the application
37 * @param parameter Parameter data to handle
38 * @returns ResultCode Whether the operation was successful or not
39 */
40 virtual ResultCode ReceiveParameter(Service::APT::MessageParameter const& parameter) = 0;
41
42 /**
43 * Handles the Applet start event, triggered from the application
44 * @param parameter Parameter data to handle
45 * @returns ResultCode Whether the operation was successful or not
46 */
47 virtual ResultCode Start(Service::APT::AppletStartupParameter const& parameter) = 0;
48
49 Service::APT::AppletId id; ///< Id of this Applet
50};
51
52}
53} // namespace
diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp
new file mode 100644
index 000000000..224aeb096
--- /dev/null
+++ b/src/core/hle/applets/swkbd.cpp
@@ -0,0 +1,73 @@
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 "common/assert.h"
6#include "common/logging/log.h"
7
8#include "core/hle/applets/swkbd.h"
9
10////////////////////////////////////////////////////////////////////////////////////////////////////
11
12namespace HLE {
13namespace Applets {
14
15SoftwareKeyboard::SoftwareKeyboard(Service::APT::AppletId id) : Applet(id) {
16 // Create the SharedMemory that will hold the framebuffer data
17 // TODO(Subv): What size should we use here?
18 using Kernel::MemoryPermission;
19 framebuffer_memory = Kernel::SharedMemory::Create(0x1000, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, "SoftwareKeyboard Memory");
20}
21
22ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter const& parameter) {
23 if (parameter.signal != static_cast<u32>(Service::APT::SignalType::LibAppJustStarted)) {
24 LOG_ERROR(Service_APT, "unsupported signal %u", parameter.signal);
25 UNIMPLEMENTED();
26 // TODO(Subv): Find the right error code
27 return ResultCode(-1);
28 }
29
30 Service::APT::MessageParameter result;
31 // The buffer passed in parameter contains the data returned by GSPGPU::ImportDisplayCaptureInfo
32 result.signal = static_cast<u32>(Service::APT::SignalType::LibAppFinished);
33 result.data = nullptr;
34 result.buffer_size = 0;
35 result.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
36 result.sender_id = static_cast<u32>(id);
37 result.object = framebuffer_memory;
38
39 Service::APT::SendParameter(result);
40 return RESULT_SUCCESS;
41}
42
43ResultCode SoftwareKeyboard::Start(Service::APT::AppletStartupParameter const& parameter) {
44 memcpy(&config, parameter.data, parameter.buffer_size);
45 text_memory = boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object);
46
47 // TODO(Subv): Verify if this is the correct behavior
48 memset(text_memory->GetPointer(), 0, text_memory->size);
49
50 // TODO(Subv): Remove this hardcoded text
51 const wchar_t str[] = L"Subv";
52 memcpy(text_memory->GetPointer(), str, 4 * sizeof(wchar_t));
53
54 // TODO(Subv): Ask for input and write it to the shared memory
55 // TODO(Subv): Find out what are the possible values for the return code,
56 // some games seem to check for a hardcoded 2
57 config.return_code = 2;
58 config.text_length = 5;
59 config.text_offset = 0;
60
61 Service::APT::MessageParameter message;
62 message.buffer_size = sizeof(SoftwareKeyboardConfig);
63 message.data = reinterpret_cast<u8*>(&config);
64 message.signal = static_cast<u32>(Service::APT::SignalType::LibAppClosed);
65 message.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
66 message.sender_id = static_cast<u32>(id);
67 Service::APT::SendParameter(message);
68
69 return RESULT_SUCCESS;
70}
71
72}
73} // namespace
diff --git a/src/core/hle/applets/swkbd.h b/src/core/hle/applets/swkbd.h
new file mode 100644
index 000000000..d7199690c
--- /dev/null
+++ b/src/core/hle/applets/swkbd.h
@@ -0,0 +1,67 @@
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_types.h"
8#include "core/hle/applets/applet.h"
9#include "core/hle/kernel/kernel.h"
10#include "core/hle/kernel/shared_memory.h"
11#include "core/hle/service/apt/apt.h"
12
13namespace HLE {
14namespace Applets {
15
16struct SoftwareKeyboardConfig {
17 INSERT_PADDING_WORDS(0x8);
18
19 u16 max_text_length; ///< Maximum length of the input text
20
21 INSERT_PADDING_BYTES(0x6E);
22
23 char16_t display_text[65]; ///< Text to display when asking the user for input
24
25 INSERT_PADDING_BYTES(0xE);
26
27 u32 default_text_offset; ///< Offset of the default text in the output SharedMemory
28
29 INSERT_PADDING_WORDS(0x3);
30
31 u32 shared_memory_size; ///< Size of the SharedMemory
32
33 INSERT_PADDING_WORDS(0x1);
34
35 u32 return_code; ///< Return code of the SoftwareKeyboard, usually 2, other values are unknown
36
37 INSERT_PADDING_WORDS(0x2);
38
39 u32 text_offset; ///< Offset in the SharedMemory where the output text starts
40 u16 text_length; ///< Length in characters of the output text
41
42 INSERT_PADDING_BYTES(0x2B6);
43};
44
45static_assert(sizeof(SoftwareKeyboardConfig) == 0x400, "Software Keyboard Config size is wrong");
46
47class SoftwareKeyboard : public Applet {
48public:
49 SoftwareKeyboard(Service::APT::AppletId id);
50 ~SoftwareKeyboard() {}
51
52 ResultCode ReceiveParameter(Service::APT::MessageParameter const& parameter) override;
53 ResultCode Start(Service::APT::AppletStartupParameter const& parameter) override;
54
55 /// TODO(Subv): Find out what this is actually used for.
56 // It is believed that the application stores the current screen image here.
57 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory;
58
59 /// SharedMemory where the output text will be stored
60 Kernel::SharedPtr<Kernel::SharedMemory> text_memory;
61
62 /// Configuration of this instance of the SoftwareKeyboard, as received from the application
63 SoftwareKeyboardConfig config;
64};
65
66}
67} // namespace
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index b454a2709..0c3889e83 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -6,6 +6,7 @@
6#include "common/file_util.h" 6#include "common/file_util.h"
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8 8
9#include "core/hle/applets/applet.h"
9#include "core/hle/service/service.h" 10#include "core/hle/service/service.h"
10#include "core/hle/service/apt/apt.h" 11#include "core/hle/service/apt/apt.h"
11#include "core/hle/service/apt/apt_a.h" 12#include "core/hle/service/apt/apt_a.h"
@@ -34,12 +35,21 @@ static Kernel::SharedPtr<Kernel::SharedMemory> shared_font_mem;
34 35
35static Kernel::SharedPtr<Kernel::Mutex> lock; 36static Kernel::SharedPtr<Kernel::Mutex> lock;
36static Kernel::SharedPtr<Kernel::Event> notification_event; ///< APT notification event 37static Kernel::SharedPtr<Kernel::Event> notification_event; ///< APT notification event
37static Kernel::SharedPtr<Kernel::Event> start_event; ///< APT start event 38static Kernel::SharedPtr<Kernel::Event> parameter_event; ///< APT parameter event
38 39
39static std::vector<u8> shared_font; 40static std::vector<u8> shared_font;
40 41
41static u32 cpu_percent; ///< CPU time available to the running application 42static u32 cpu_percent; ///< CPU time available to the running application
42 43
44/// Parameter data to be returned in the next call to Glance/ReceiveParameter
45static MessageParameter next_parameter;
46
47void SendParameter(MessageParameter const& parameter) {
48 next_parameter = parameter;
49 // Signal the event to let the application know that a new parameter is ready to be read
50 parameter_event->Signal();
51}
52
43void Initialize(Service::Interface* self) { 53void Initialize(Service::Interface* self) {
44 u32* cmd_buff = Kernel::GetCommandBuffer(); 54 u32* cmd_buff = Kernel::GetCommandBuffer();
45 u32 app_id = cmd_buff[1]; 55 u32 app_id = cmd_buff[1];
@@ -47,18 +57,18 @@ void Initialize(Service::Interface* self) {
47 57
48 cmd_buff[2] = IPC::MoveHandleDesc(2); 58 cmd_buff[2] = IPC::MoveHandleDesc(2);
49 cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom(); 59 cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom();
50 cmd_buff[4] = Kernel::g_handle_table.Create(start_event).MoveFrom(); 60 cmd_buff[4] = Kernel::g_handle_table.Create(parameter_event).MoveFrom();
51 61
52 // TODO(bunnei): Check if these events are cleared every time Initialize is called. 62 // TODO(bunnei): Check if these events are cleared every time Initialize is called.
53 notification_event->Clear(); 63 notification_event->Clear();
54 start_event->Clear(); 64 parameter_event->Clear();
55 65
56 ASSERT_MSG((nullptr != lock), "Cannot initialize without lock"); 66 ASSERT_MSG((nullptr != lock), "Cannot initialize without lock");
57 lock->Release(); 67 lock->Release();
58 68
59 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 69 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
60 70
61 LOG_TRACE(Service_APT, "called app_id=0x%08X, flags=0x%08X", app_id, flags); 71 LOG_WARNING(Service_APT, "called app_id=0x%08X, flags=0x%08X", app_id, flags);
62} 72}
63 73
64void GetSharedFont(Service::Interface* self) { 74void GetSharedFont(Service::Interface* self) {
@@ -85,9 +95,7 @@ void GetSharedFont(Service::Interface* self) {
85void NotifyToWait(Service::Interface* self) { 95void NotifyToWait(Service::Interface* self) {
86 u32* cmd_buff = Kernel::GetCommandBuffer(); 96 u32* cmd_buff = Kernel::GetCommandBuffer();
87 u32 app_id = cmd_buff[1]; 97 u32 app_id = cmd_buff[1];
88 // TODO(Subv): Verify this, it seems to get SWKBD and Home Menu further. 98
89 start_event->Signal();
90
91 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 99 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
92 LOG_WARNING(Service_APT, "(STUBBED) app_id=%u", app_id); 100 LOG_WARNING(Service_APT, "(STUBBED) app_id=%u", app_id);
93} 101}
@@ -112,6 +120,7 @@ void Enable(Service::Interface* self) {
112 u32* cmd_buff = Kernel::GetCommandBuffer(); 120 u32* cmd_buff = Kernel::GetCommandBuffer();
113 u32 unk = cmd_buff[1]; // TODO(bunnei): What is this field used for? 121 u32 unk = cmd_buff[1]; // TODO(bunnei): What is this field used for?
114 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 122 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
123 parameter_event->Signal(); // Let the application know that it has been started
115 LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk); 124 LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk);
116} 125}
117 126
@@ -121,8 +130,8 @@ void GetAppletManInfo(Service::Interface* self) {
121 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 130 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
122 cmd_buff[2] = 0; 131 cmd_buff[2] = 0;
123 cmd_buff[3] = 0; 132 cmd_buff[3] = 0;
124 cmd_buff[4] = static_cast<u32>(AppID::HomeMenu); // Home menu AppID 133 cmd_buff[4] = static_cast<u32>(AppletId::HomeMenu); // Home menu AppID
125 cmd_buff[5] = static_cast<u32>(AppID::Application); // TODO(purpasmart96): Do this correctly 134 cmd_buff[5] = static_cast<u32>(AppletId::Application); // TODO(purpasmart96): Do this correctly
126 135
127 LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk); 136 LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk);
128} 137}
@@ -131,7 +140,13 @@ void IsRegistered(Service::Interface* self) {
131 u32* cmd_buff = Kernel::GetCommandBuffer(); 140 u32* cmd_buff = Kernel::GetCommandBuffer();
132 u32 app_id = cmd_buff[1]; 141 u32 app_id = cmd_buff[1];
133 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 142 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
134 cmd_buff[2] = 1; // Set to registered 143 /// TODO(Subv): It is currently unknown what this value (0x400) means,
144 /// but i believe it is used as a global "LibraryApplet" id, to verify if there's
145 /// any LibApplet currently running. This is not verified.
146 if (app_id != 0x400)
147 cmd_buff[2] = 1; // Set to registered
148 else
149 cmd_buff[2] = 0; // Set to not registered
135 LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id); 150 LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id);
136} 151}
137 152
@@ -145,50 +160,81 @@ void InquireNotification(Service::Interface* self) {
145 160
146void SendParameter(Service::Interface* self) { 161void SendParameter(Service::Interface* self) {
147 u32* cmd_buff = Kernel::GetCommandBuffer(); 162 u32* cmd_buff = Kernel::GetCommandBuffer();
148 u32 src_app_id = cmd_buff[1]; 163 u32 src_app_id = cmd_buff[1];
149 u32 dst_app_id = cmd_buff[2]; 164 u32 dst_app_id = cmd_buff[2];
150 u32 signal_type = cmd_buff[3]; 165 u32 signal_type = cmd_buff[3];
151 u32 buffer_size = cmd_buff[4]; 166 u32 buffer_size = cmd_buff[4];
152 u32 value = cmd_buff[5]; 167 u32 value = cmd_buff[5];
153 u32 handle = cmd_buff[6]; 168 u32 handle = cmd_buff[6];
154 u32 size = cmd_buff[7]; 169 u32 size = cmd_buff[7];
155 u32 in_param_buffer_ptr = cmd_buff[8]; 170 u32 buffer = cmd_buff[8];
171
172 std::shared_ptr<HLE::Applets::Applet> dest_applet = HLE::Applets::Applet::Get(static_cast<AppletId>(dst_app_id));
173
174 if (dest_applet == nullptr) {
175 LOG_ERROR(Service_APT, "Unknown applet id=0x%08X", dst_app_id);
176 return;
177 }
156 178
157 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 179 MessageParameter param;
180 param.buffer_size = buffer_size;
181 param.destination_id = dst_app_id;
182 param.sender_id = src_app_id;
183 param.object = Kernel::g_handle_table.GetGeneric(handle);
184 param.signal = signal_type;
185 param.data = Memory::GetPointer(buffer);
186
187 cmd_buff[1] = dest_applet->ReceiveParameter(param).raw;
158 188
159 LOG_WARNING(Service_APT, "(STUBBED) called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X," 189 LOG_WARNING(Service_APT, "(STUBBED) called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X,"
160 "buffer_size=0x%08X, value=0x%08X, handle=0x%08X, size=0x%08X, in_param_buffer_ptr=0x%08X", 190 "buffer_size=0x%08X, value=0x%08X, handle=0x%08X, size=0x%08X, in_param_buffer_ptr=0x%08X",
161 src_app_id, dst_app_id, signal_type, buffer_size, value, handle, size, in_param_buffer_ptr); 191 src_app_id, dst_app_id, signal_type, buffer_size, value, handle, size, buffer);
162} 192}
163 193
164void ReceiveParameter(Service::Interface* self) { 194void ReceiveParameter(Service::Interface* self) {
165 u32* cmd_buff = Kernel::GetCommandBuffer(); 195 u32* cmd_buff = Kernel::GetCommandBuffer();
166 u32 app_id = cmd_buff[1]; 196 u32 app_id = cmd_buff[1];
167 u32 buffer_size = cmd_buff[2]; 197 u32 buffer_size = cmd_buff[2];
198 VAddr buffer = cmd_buff[0x104 >> 2];
199
168 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 200 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
169 cmd_buff[2] = 0; 201 cmd_buff[2] = next_parameter.sender_id;
170 cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type 202 cmd_buff[3] = next_parameter.signal; // Signal type
171 cmd_buff[4] = 0x10; // Parameter buffer size (16) 203 cmd_buff[4] = next_parameter.buffer_size; // Parameter buffer size
172 cmd_buff[5] = 0; 204 cmd_buff[5] = 0x10;
173 cmd_buff[6] = 0; 205 cmd_buff[6] = 0;
174 cmd_buff[7] = 0; 206 if (next_parameter.object != nullptr)
175 LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); 207 cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom();
208 cmd_buff[7] = (next_parameter.buffer_size << 14) | 2;
209 cmd_buff[8] = buffer;
210
211 if (next_parameter.data)
212 memcpy(Memory::GetPointer(buffer), next_parameter.data, std::min(buffer_size, next_parameter.buffer_size));
213
214 LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size);
176} 215}
177 216
178void GlanceParameter(Service::Interface* self) { 217void GlanceParameter(Service::Interface* self) {
179 u32* cmd_buff = Kernel::GetCommandBuffer(); 218 u32* cmd_buff = Kernel::GetCommandBuffer();
180 u32 app_id = cmd_buff[1]; 219 u32 app_id = cmd_buff[1];
181 u32 buffer_size = cmd_buff[2]; 220 u32 buffer_size = cmd_buff[2];
221 VAddr buffer = cmd_buff[0x104 >> 2];
182 222
183 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 223 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
184 cmd_buff[2] = 0; 224 cmd_buff[2] = next_parameter.sender_id;
185 cmd_buff[3] = static_cast<u32>(SignalType::AppJustStarted); // Signal type 225 cmd_buff[3] = next_parameter.signal; // Signal type
186 cmd_buff[4] = 0x10; // Parameter buffer size (16) 226 cmd_buff[4] = next_parameter.buffer_size; // Parameter buffer size
187 cmd_buff[5] = 0; 227 cmd_buff[5] = 0x10;
188 cmd_buff[6] = 0; 228 cmd_buff[6] = 0;
189 cmd_buff[7] = 0; 229 if (next_parameter.object != nullptr)
230 cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom();
231 cmd_buff[7] = (next_parameter.buffer_size << 14) | 2;
232 cmd_buff[8] = buffer;
190 233
191 LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); 234 if (next_parameter.data)
235 memcpy(Memory::GetPointer(buffer), next_parameter.data, std::min(buffer_size, next_parameter.buffer_size));
236
237 LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size);
192} 238}
193 239
194void CancelParameter(Service::Interface* self) { 240void CancelParameter(Service::Interface* self) {
@@ -281,6 +327,28 @@ void GetAppCpuTimeLimit(Service::Interface* self) {
281 LOG_WARNING(Service_APT, "(STUBBED) called value=%u", value); 327 LOG_WARNING(Service_APT, "(STUBBED) called value=%u", value);
282} 328}
283 329
330void PrepareToStartLibraryApplet(Service::Interface* self) {
331 u32* cmd_buff = Kernel::GetCommandBuffer();
332 cmd_buff[1] = HLE::Applets::Applet::Create(static_cast<AppletId>(cmd_buff[1])).raw;
333}
334
335void StartLibraryApplet(Service::Interface* self) {
336 u32* cmd_buff = Kernel::GetCommandBuffer();
337 std::shared_ptr<HLE::Applets::Applet> applet = HLE::Applets::Applet::Get(static_cast<AppletId>(cmd_buff[1]));
338
339 if (applet == nullptr) {
340 cmd_buff[1] = -1; // TODO(Subv): Find the right error code
341 return;
342 }
343
344 AppletStartupParameter parameter;
345 parameter.buffer_size = cmd_buff[2];
346 parameter.object = Kernel::g_handle_table.GetGeneric(cmd_buff[4]);
347 parameter.data = Memory::GetPointer(cmd_buff[6]);
348
349 cmd_buff[1] = applet->Start(parameter).raw;
350}
351
284void Init() { 352void Init() {
285 AddService(new APT_A_Interface); 353 AddService(new APT_A_Interface);
286 AddService(new APT_S_Interface); 354 AddService(new APT_S_Interface);
@@ -318,7 +386,10 @@ void Init() {
318 386
319 // TODO(bunnei): Check if these are created in Initialize or on APT process startup. 387 // TODO(bunnei): Check if these are created in Initialize or on APT process startup.
320 notification_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Notification"); 388 notification_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Notification");
321 start_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Start"); 389 parameter_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Start");
390
391 next_parameter.signal = static_cast<u32>(SignalType::AppJustStarted);
392 next_parameter.destination_id = 0x300;
322} 393}
323 394
324void Shutdown() { 395void Shutdown() {
@@ -326,7 +397,7 @@ void Shutdown() {
326 shared_font_mem = nullptr; 397 shared_font_mem = nullptr;
327 lock = nullptr; 398 lock = nullptr;
328 notification_event = nullptr; 399 notification_event = nullptr;
329 start_event = nullptr; 400 parameter_event = nullptr;
330} 401}
331 402
332} // namespace APT 403} // namespace APT
diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h
index a03e1712a..510193cc8 100644
--- a/src/core/hle/service/apt/apt.h
+++ b/src/core/hle/service/apt/apt.h
@@ -11,6 +11,23 @@
11namespace Service { 11namespace Service {
12namespace APT { 12namespace APT {
13 13
14/// Holds information about the parameters used in Send/Glance/ReceiveParameter
15struct MessageParameter {
16 u32 sender_id = 0;
17 u32 destination_id = 0;
18 u32 signal = 0;
19 u32 buffer_size = 0;
20 Kernel::SharedPtr<Kernel::Object> object = nullptr;
21 u8* data = nullptr;
22};
23
24/// Holds information about the parameters used in StartLibraryApplet
25struct AppletStartupParameter {
26 u32 buffer_size = 0;
27 Kernel::SharedPtr<Kernel::Object> object = nullptr;
28 u8* data = nullptr;
29};
30
14/// Signals used by APT functions 31/// Signals used by APT functions
15enum class SignalType : u32 { 32enum class SignalType : u32 {
16 None = 0x0, 33 None = 0x0,
@@ -23,7 +40,7 @@ enum class SignalType : u32 {
23}; 40};
24 41
25/// App Id's used by APT functions 42/// App Id's used by APT functions
26enum class AppID : u32 { 43enum class AppletId : u32 {
27 HomeMenu = 0x101, 44 HomeMenu = 0x101,
28 AlternateMenu = 0x103, 45 AlternateMenu = 0x103,
29 Camera = 0x110, 46 Camera = 0x110,
@@ -45,6 +62,9 @@ enum class AppID : u32 {
45 SoftwareKeyboard2 = 0x401, 62 SoftwareKeyboard2 = 0x401,
46}; 63};
47 64
65/// Send a parameter to the currently-running application, which will read it via ReceiveParameter
66void SendParameter(MessageParameter const& parameter);
67
48/** 68/**
49 * APT::Initialize service function 69 * APT::Initialize service function
50 * Service function that initializes the APT process for the running application 70 * Service function that initializes the APT process for the running application
@@ -249,6 +269,33 @@ void SetAppCpuTimeLimit(Service::Interface* self);
249 */ 269 */
250void GetAppCpuTimeLimit(Service::Interface* self); 270void GetAppCpuTimeLimit(Service::Interface* self);
251 271
272/**
273 * APT::PrepareToStartLibraryApplet service function
274 * Inputs:
275 * 0 : Command header [0x00180040]
276 * 1 : Id of the applet to start
277 * Outputs:
278 * 0 : Return header
279 * 1 : Result of function, 0 on success, otherwise error code
280 */
281void PrepareToStartLibraryApplet(Service::Interface* self);
282
283/**
284 * APT::StartLibraryApplet service function
285 * Inputs:
286 * 0 : Command header [0x001E0084]
287 * 1 : Id of the applet to start
288 * 2 : Buffer size
289 * 3 : Always 0?
290 * 4 : Handle passed to the applet
291 * 5 : (Size << 14) | 2
292 * 6 : Input buffer virtual address
293 * Outputs:
294 * 0 : Return header
295 * 1 : Result of function, 0 on success, otherwise error code
296 */
297void StartLibraryApplet(Service::Interface* self);
298
252/// Initialize the APT service 299/// Initialize the APT service
253void Init(); 300void Init();
254 301
diff --git a/src/core/hle/service/apt/apt_a.cpp b/src/core/hle/service/apt/apt_a.cpp
index 864934245..88de339f9 100644
--- a/src/core/hle/service/apt/apt_a.cpp
+++ b/src/core/hle/service/apt/apt_a.cpp
@@ -10,19 +10,24 @@ namespace Service {
10namespace APT { 10namespace APT {
11 11
12const Interface::FunctionInfo FunctionTable[] = { 12const Interface::FunctionInfo FunctionTable[] = {
13 {0x00010040, GetLockHandle, "GetLockHandle?"}, 13 {0x00010040, GetLockHandle, "GetLockHandle?"},
14 {0x00020080, Initialize, "Initialize?"}, 14 {0x00020080, Initialize, "Initialize?"},
15 {0x00030040, Enable, "Enable?"}, 15 {0x00030040, Enable, "Enable?"},
16 {0x00040040, nullptr, "Finalize?"}, 16 {0x00040040, nullptr, "Finalize?"},
17 {0x00050040, nullptr, "GetAppletManInfo?"}, 17 {0x00050040, nullptr, "GetAppletManInfo?"},
18 {0x00060040, nullptr, "GetAppletInfo?"}, 18 {0x00060040, nullptr, "GetAppletInfo?"},
19 {0x000D0080, ReceiveParameter, "ReceiveParameter?"}, 19 {0x00090040, IsRegistered, "IsRegistered"},
20 {0x000E0080, GlanceParameter, "GlanceParameter?"}, 20 {0x000C0104, SendParameter, "SendParameter"},
21 {0x003B0040, nullptr, "CancelLibraryApplet?"}, 21 {0x000D0080, ReceiveParameter, "ReceiveParameter"},
22 {0x00430040, NotifyToWait, "NotifyToWait?"}, 22 {0x000E0080, GlanceParameter, "GlanceParameter"},
23 {0x00440000, GetSharedFont, "GetSharedFont?"}, 23 {0x000F0100, CancelParameter, "CancelParameter"},
24 {0x004B00C2, AppletUtility, "AppletUtility?"}, 24 {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"},
25 {0x00550040, nullptr, "WriteInputToNsState?"}, 25 {0x001E0084, StartLibraryApplet, "StartLibraryApplet"},
26 {0x003B0040, nullptr, "CancelLibraryApplet?"},
27 {0x00430040, NotifyToWait, "NotifyToWait?"},
28 {0x00440000, GetSharedFont, "GetSharedFont?"},
29 {0x004B00C2, AppletUtility, "AppletUtility?"},
30 {0x00550040, nullptr, "WriteInputToNsState?"},
26}; 31};
27 32
28APT_A_Interface::APT_A_Interface() { 33APT_A_Interface::APT_A_Interface() {
diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp
index d006b5930..b724cd72b 100644
--- a/src/core/hle/service/apt/apt_u.cpp
+++ b/src/core/hle/service/apt/apt_u.cpp
@@ -35,13 +35,13 @@ const Interface::FunctionInfo FunctionTable[] = {
35 {0x00150140, nullptr, "PrepareToStartApplication"}, 35 {0x00150140, nullptr, "PrepareToStartApplication"},
36 {0x00160040, nullptr, "PreloadLibraryApplet"}, 36 {0x00160040, nullptr, "PreloadLibraryApplet"},
37 {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, 37 {0x00170040, nullptr, "FinishPreloadingLibraryApplet"},
38 {0x00180040, nullptr, "PrepareToStartLibraryApplet"}, 38 {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"},
39 {0x00190040, nullptr, "PrepareToStartSystemApplet"}, 39 {0x00190040, nullptr, "PrepareToStartSystemApplet"},
40 {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, 40 {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"},
41 {0x001B00C4, nullptr, "StartApplication"}, 41 {0x001B00C4, nullptr, "StartApplication"},
42 {0x001C0000, nullptr, "WakeupApplication"}, 42 {0x001C0000, nullptr, "WakeupApplication"},
43 {0x001D0000, nullptr, "CancelApplication"}, 43 {0x001D0000, nullptr, "CancelApplication"},
44 {0x001E0084, nullptr, "StartLibraryApplet"}, 44 {0x001E0084, StartLibraryApplet, "StartLibraryApplet"},
45 {0x001F0084, nullptr, "StartSystemApplet"}, 45 {0x001F0084, nullptr, "StartSystemApplet"},
46 {0x00200044, nullptr, "StartNewestHomeMenu"}, 46 {0x00200044, nullptr, "StartNewestHomeMenu"},
47 {0x00210000, nullptr, "OrderToCloseApplication"}, 47 {0x00210000, nullptr, "OrderToCloseApplication"},