Browse Source
HLE/APT: Initial HLE support for applets.
HLE/APT: Initial HLE support for applets.
Currently only the SWKBD is emulated, and there's currently no way to ask the user for input, so it always returns "Subv" as the text.pull/15/merge
9 changed files with 410 additions and 50 deletions
-
4src/core/CMakeLists.txt
-
40src/core/hle/applets/applet.cpp
-
53src/core/hle/applets/applet.h
-
73src/core/hle/applets/swkbd.cpp
-
67src/core/hle/applets/swkbd.h
-
139src/core/hle/service/apt/apt.cpp
-
49src/core/hle/service/apt/apt.h
-
31src/core/hle/service/apt/apt_a.cpp
-
4src/core/hle/service/apt/apt_u.cpp
@ -0,0 +1,40 @@ |
|||||
|
// Copyright 2015 Citra Emulator Project
|
||||
|
// Licensed under GPLv2 or any later version
|
||||
|
// Refer to the license.txt file included.
|
||||
|
|
||||
|
#include "common/assert.h"
|
||||
|
#include "common/logging/log.h"
|
||||
|
|
||||
|
#include "core/hle/applets/applet.h"
|
||||
|
#include "core/hle/applets/swkbd.h"
|
||||
|
|
||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
||||
|
namespace HLE { |
||||
|
namespace Applets { |
||||
|
|
||||
|
static std::unordered_map<Service::APT::AppletId, std::shared_ptr<Applet>> applets; |
||||
|
|
||||
|
ResultCode Applet::Create(Service::APT::AppletId id) { |
||||
|
switch (id) { |
||||
|
case Service::APT::AppletId::SoftwareKeyboard1: |
||||
|
case Service::APT::AppletId::SoftwareKeyboard2: |
||||
|
applets[id] = std::make_shared<SoftwareKeyboard>(id); |
||||
|
break; |
||||
|
default: |
||||
|
// TODO(Subv): Find the right error code
|
||||
|
return ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotSupported, ErrorLevel::Permanent); |
||||
|
} |
||||
|
|
||||
|
return RESULT_SUCCESS; |
||||
|
} |
||||
|
|
||||
|
std::shared_ptr<Applet> Applet::Get(Service::APT::AppletId id) { |
||||
|
auto itr = applets.find(id); |
||||
|
if (itr != applets.end()) |
||||
|
return itr->second; |
||||
|
return nullptr; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} // namespace
|
||||
@ -0,0 +1,53 @@ |
|||||
|
// Copyright 2015 Citra Emulator Project |
||||
|
// Licensed under GPLv2 or any later version |
||||
|
// Refer to the license.txt file included. |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include "common/common_types.h" |
||||
|
#include "core/hle/kernel/kernel.h" |
||||
|
#include "core/hle/kernel/shared_memory.h" |
||||
|
#include "core/hle/service/apt/apt.h" |
||||
|
|
||||
|
namespace HLE { |
||||
|
namespace Applets { |
||||
|
|
||||
|
class Applet { |
||||
|
public: |
||||
|
virtual ~Applet() {}; |
||||
|
Applet(Service::APT::AppletId id) : id(id) {}; |
||||
|
|
||||
|
/** |
||||
|
* Creates an instance of the Applet subclass identified by the parameter |
||||
|
* and stores it in a global map. |
||||
|
* @param id Id of the applet to create |
||||
|
* @returns ResultCode Whether the operation was successful or not |
||||
|
*/ |
||||
|
static ResultCode Create(Service::APT::AppletId id); |
||||
|
|
||||
|
/** |
||||
|
* Retrieves the Applet instance identified by the specified id |
||||
|
* @param id Id of the Applet to retrieve |
||||
|
* @returns Requested Applet or nullptr if not found |
||||
|
*/ |
||||
|
static std::shared_ptr<Applet> Get(Service::APT::AppletId id); |
||||
|
|
||||
|
/** |
||||
|
* Handles a parameter from the application |
||||
|
* @param parameter Parameter data to handle |
||||
|
* @returns ResultCode Whether the operation was successful or not |
||||
|
*/ |
||||
|
virtual ResultCode ReceiveParameter(Service::APT::MessageParameter const& parameter) = 0; |
||||
|
|
||||
|
/** |
||||
|
* Handles the Applet start event, triggered from the application |
||||
|
* @param parameter Parameter data to handle |
||||
|
* @returns ResultCode Whether the operation was successful or not |
||||
|
*/ |
||||
|
virtual ResultCode Start(Service::APT::AppletStartupParameter const& parameter) = 0; |
||||
|
|
||||
|
Service::APT::AppletId id; ///< Id of this Applet |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
} // namespace |
||||
@ -0,0 +1,73 @@ |
|||||
|
// Copyright 2015 Citra Emulator Project
|
||||
|
// Licensed under GPLv2 or any later version
|
||||
|
// Refer to the license.txt file included.
|
||||
|
|
||||
|
#include "common/assert.h"
|
||||
|
#include "common/logging/log.h"
|
||||
|
|
||||
|
#include "core/hle/applets/swkbd.h"
|
||||
|
|
||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
||||
|
namespace HLE { |
||||
|
namespace Applets { |
||||
|
|
||||
|
SoftwareKeyboard::SoftwareKeyboard(Service::APT::AppletId id) : Applet(id) { |
||||
|
// Create the SharedMemory that will hold the framebuffer data
|
||||
|
// TODO(Subv): What size should we use here?
|
||||
|
using Kernel::MemoryPermission; |
||||
|
framebuffer_memory = Kernel::SharedMemory::Create(0x1000, MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, "SoftwareKeyboard Memory"); |
||||
|
} |
||||
|
|
||||
|
ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter const& parameter) { |
||||
|
if (parameter.signal != static_cast<u32>(Service::APT::SignalType::LibAppJustStarted)) { |
||||
|
LOG_ERROR(Service_APT, "unsupported signal %u", parameter.signal); |
||||
|
UNIMPLEMENTED(); |
||||
|
// TODO(Subv): Find the right error code
|
||||
|
return ResultCode(-1); |
||||
|
} |
||||
|
|
||||
|
Service::APT::MessageParameter result; |
||||
|
// The buffer passed in parameter contains the data returned by GSPGPU::ImportDisplayCaptureInfo
|
||||
|
result.signal = static_cast<u32>(Service::APT::SignalType::LibAppFinished); |
||||
|
result.data = nullptr; |
||||
|
result.buffer_size = 0; |
||||
|
result.destination_id = static_cast<u32>(Service::APT::AppletId::Application); |
||||
|
result.sender_id = static_cast<u32>(id); |
||||
|
result.object = framebuffer_memory; |
||||
|
|
||||
|
Service::APT::SendParameter(result); |
||||
|
return RESULT_SUCCESS; |
||||
|
} |
||||
|
|
||||
|
ResultCode SoftwareKeyboard::Start(Service::APT::AppletStartupParameter const& parameter) { |
||||
|
memcpy(&config, parameter.data, parameter.buffer_size); |
||||
|
text_memory = boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object); |
||||
|
|
||||
|
// TODO(Subv): Verify if this is the correct behavior
|
||||
|
memset(text_memory->GetPointer(), 0, text_memory->size); |
||||
|
|
||||
|
// TODO(Subv): Remove this hardcoded text
|
||||
|
const wchar_t str[] = L"Subv"; |
||||
|
memcpy(text_memory->GetPointer(), str, 4 * sizeof(wchar_t)); |
||||
|
|
||||
|
// TODO(Subv): Ask for input and write it to the shared memory
|
||||
|
// TODO(Subv): Find out what are the possible values for the return code,
|
||||
|
// some games seem to check for a hardcoded 2
|
||||
|
config.return_code = 2; |
||||
|
config.text_length = 5; |
||||
|
config.text_offset = 0; |
||||
|
|
||||
|
Service::APT::MessageParameter message; |
||||
|
message.buffer_size = sizeof(SoftwareKeyboardConfig); |
||||
|
message.data = reinterpret_cast<u8*>(&config); |
||||
|
message.signal = static_cast<u32>(Service::APT::SignalType::LibAppClosed); |
||||
|
message.destination_id = static_cast<u32>(Service::APT::AppletId::Application); |
||||
|
message.sender_id = static_cast<u32>(id); |
||||
|
Service::APT::SendParameter(message); |
||||
|
|
||||
|
return RESULT_SUCCESS; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} // namespace
|
||||
@ -0,0 +1,67 @@ |
|||||
|
// Copyright 2015 Citra Emulator Project |
||||
|
// Licensed under GPLv2 or any later version |
||||
|
// Refer to the license.txt file included. |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include "common/common_types.h" |
||||
|
#include "core/hle/applets/applet.h" |
||||
|
#include "core/hle/kernel/kernel.h" |
||||
|
#include "core/hle/kernel/shared_memory.h" |
||||
|
#include "core/hle/service/apt/apt.h" |
||||
|
|
||||
|
namespace HLE { |
||||
|
namespace Applets { |
||||
|
|
||||
|
struct SoftwareKeyboardConfig { |
||||
|
INSERT_PADDING_WORDS(0x8); |
||||
|
|
||||
|
u16 max_text_length; ///< Maximum length of the input text |
||||
|
|
||||
|
INSERT_PADDING_BYTES(0x6E); |
||||
|
|
||||
|
char16_t display_text[65]; ///< Text to display when asking the user for input |
||||
|
|
||||
|
INSERT_PADDING_BYTES(0xE); |
||||
|
|
||||
|
u32 default_text_offset; ///< Offset of the default text in the output SharedMemory |
||||
|
|
||||
|
INSERT_PADDING_WORDS(0x3); |
||||
|
|
||||
|
u32 shared_memory_size; ///< Size of the SharedMemory |
||||
|
|
||||
|
INSERT_PADDING_WORDS(0x1); |
||||
|
|
||||
|
u32 return_code; ///< Return code of the SoftwareKeyboard, usually 2, other values are unknown |
||||
|
|
||||
|
INSERT_PADDING_WORDS(0x2); |
||||
|
|
||||
|
u32 text_offset; ///< Offset in the SharedMemory where the output text starts |
||||
|
u16 text_length; ///< Length in characters of the output text |
||||
|
|
||||
|
INSERT_PADDING_BYTES(0x2B6); |
||||
|
}; |
||||
|
|
||||
|
static_assert(sizeof(SoftwareKeyboardConfig) == 0x400, "Software Keyboard Config size is wrong"); |
||||
|
|
||||
|
class SoftwareKeyboard : public Applet { |
||||
|
public: |
||||
|
SoftwareKeyboard(Service::APT::AppletId id); |
||||
|
~SoftwareKeyboard() {} |
||||
|
|
||||
|
ResultCode ReceiveParameter(Service::APT::MessageParameter const& parameter) override; |
||||
|
ResultCode Start(Service::APT::AppletStartupParameter const& parameter) override; |
||||
|
|
||||
|
/// TODO(Subv): Find out what this is actually used for. |
||||
|
// It is believed that the application stores the current screen image here. |
||||
|
Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; |
||||
|
|
||||
|
/// SharedMemory where the output text will be stored |
||||
|
Kernel::SharedPtr<Kernel::SharedMemory> text_memory; |
||||
|
|
||||
|
/// Configuration of this instance of the SoftwareKeyboard, as received from the application |
||||
|
SoftwareKeyboardConfig config; |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
} // namespace |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue