summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt4
-rw-r--r--src/core/hle/function_wrappers.h10
-rw-r--r--src/core/hle/kernel/client_port.cpp16
-rw-r--r--src/core/hle/kernel/client_port.h36
-rw-r--r--src/core/hle/kernel/kernel.h7
-rw-r--r--src/core/hle/kernel/server_port.cpp41
-rw-r--r--src/core/hle/kernel/server_port.h46
-rw-r--r--src/core/hle/service/hid/hid.cpp70
-rw-r--r--src/core/hle/service/hid/hid.h3
-rw-r--r--src/core/hle/svc.cpp21
-rw-r--r--src/core/settings.h22
11 files changed, 233 insertions, 43 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index f356e4b48..02d902bb5 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -30,6 +30,7 @@ set(SRCS
hle/applets/mii_selector.cpp
hle/applets/swkbd.cpp
hle/kernel/address_arbiter.cpp
+ hle/kernel/client_port.cpp
hle/kernel/event.cpp
hle/kernel/kernel.cpp
hle/kernel/memory.cpp
@@ -37,6 +38,7 @@ set(SRCS
hle/kernel/process.cpp
hle/kernel/resource_limit.cpp
hle/kernel/semaphore.cpp
+ hle/kernel/server_port.cpp
hle/kernel/session.cpp
hle/kernel/shared_memory.cpp
hle/kernel/thread.cpp
@@ -169,6 +171,7 @@ set(HEADERS
hle/applets/mii_selector.h
hle/applets/swkbd.h
hle/kernel/address_arbiter.h
+ hle/kernel/client_port.h
hle/kernel/event.h
hle/kernel/kernel.h
hle/kernel/memory.h
@@ -176,6 +179,7 @@ set(HEADERS
hle/kernel/process.h
hle/kernel/resource_limit.h
hle/kernel/semaphore.h
+ hle/kernel/server_port.h
hle/kernel/session.h
hle/kernel/shared_memory.h
hle/kernel/thread.h
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h
index bf7f875b6..8839ce482 100644
--- a/src/core/hle/function_wrappers.h
+++ b/src/core/hle/function_wrappers.h
@@ -194,6 +194,16 @@ template<ResultCode func(Handle, u32)> void Wrap() {
FuncReturn(func(PARAM(0), PARAM(1)).raw);
}
+template<ResultCode func(Handle*, Handle*, const char*, u32)> void Wrap() {
+ Handle param_1 = 0;
+ Handle param_2 = 0;
+ u32 retval = func(&param_1, &param_2, reinterpret_cast<const char*>(Memory::GetPointer(PARAM(2))), PARAM(3)).raw;
+ // The first out parameter is moved into R2 and the second is moved into R1.
+ Core::g_app_core->SetReg(1, param_2);
+ Core::g_app_core->SetReg(2, param_1);
+ FuncReturn(retval);
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////////
// Function wrappers that return type u32
diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp
new file mode 100644
index 000000000..444ce8d45
--- /dev/null
+++ b/src/core/hle/kernel/client_port.cpp
@@ -0,0 +1,16 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/assert.h"
+
+#include "core/hle/kernel/client_port.h"
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/server_port.h"
+
+namespace Kernel {
+
+ClientPort::ClientPort() {}
+ClientPort::~ClientPort() {}
+
+} // namespace
diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h
new file mode 100644
index 000000000..480b6ddae
--- /dev/null
+++ b/src/core/hle/kernel/client_port.h
@@ -0,0 +1,36 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <string>
+
+#include "common/common_types.h"
+
+#include "core/hle/kernel/kernel.h"
+
+namespace Kernel {
+
+class ServerPort;
+
+class ClientPort : public Object {
+public:
+ friend class ServerPort;
+ std::string GetTypeName() const override { return "ClientPort"; }
+ std::string GetName() const override { return name; }
+
+ static const HandleType HANDLE_TYPE = HandleType::ClientPort;
+ HandleType GetHandleType() const override { return HANDLE_TYPE; }
+
+ SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
+ u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have
+ u32 active_sessions; ///< Number of currently open sessions to this port
+ std::string name; ///< Name of client port (optional)
+
+protected:
+ ClientPort();
+ ~ClientPort() override;
+};
+
+} // namespace
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 4d4276f7a..27ba3f912 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -35,7 +35,7 @@ enum KernelHandle : Handle {
enum class HandleType : u32 {
Unknown = 0,
- Port = 1,
+
Session = 2,
Event = 3,
Mutex = 4,
@@ -48,6 +48,8 @@ enum class HandleType : u32 {
Timer = 11,
ResourceLimit = 12,
CodeSet = 13,
+ ClientPort = 14,
+ ServerPort = 15,
};
enum {
@@ -72,6 +74,7 @@ public:
bool IsWaitable() const {
switch (GetHandleType()) {
case HandleType::Session:
+ case HandleType::ServerPort:
case HandleType::Event:
case HandleType::Mutex:
case HandleType::Thread:
@@ -80,13 +83,13 @@ public:
return true;
case HandleType::Unknown:
- case HandleType::Port:
case HandleType::SharedMemory:
case HandleType::Redirection:
case HandleType::Process:
case HandleType::AddressArbiter:
case HandleType::ResourceLimit:
case HandleType::CodeSet:
+ case HandleType::ClientPort:
return false;
}
}
diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp
new file mode 100644
index 000000000..fcc684a20
--- /dev/null
+++ b/src/core/hle/kernel/server_port.cpp
@@ -0,0 +1,41 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <tuple>
+
+#include "common/assert.h"
+
+#include "core/hle/kernel/client_port.h"
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/server_port.h"
+#include "core/hle/kernel/thread.h"
+
+namespace Kernel {
+
+ServerPort::ServerPort() {}
+ServerPort::~ServerPort() {}
+
+bool ServerPort::ShouldWait() {
+ // If there are no pending sessions, we wait until a new one is added.
+ return pending_sessions.size() == 0;
+}
+
+void ServerPort::Acquire() {
+ ASSERT_MSG(!ShouldWait(), "object unavailable!");
+}
+
+std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair(u32 max_sessions, std::string name) {
+ SharedPtr<ServerPort> server_port(new ServerPort);
+ SharedPtr<ClientPort> client_port(new ClientPort);
+
+ server_port->name = name + "_Server";
+ client_port->name = name + "_Client";
+ client_port->server_port = server_port;
+ client_port->max_sessions = max_sessions;
+ client_port->active_sessions = 0;
+
+ return std::make_tuple(std::move(server_port), std::move(client_port));
+}
+
+} // namespace
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h
new file mode 100644
index 000000000..e9c972ce6
--- /dev/null
+++ b/src/core/hle/kernel/server_port.h
@@ -0,0 +1,46 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <string>
+#include <tuple>
+
+#include "common/common_types.h"
+
+#include "core/hle/kernel/kernel.h"
+
+namespace Kernel {
+
+class ClientPort;
+
+class ServerPort final : public WaitObject {
+public:
+ /**
+ * Creates a pair of ServerPort and an associated ClientPort.
+ * @param max_sessions Maximum number of sessions to the port
+ * @param name Optional name of the ports
+ * @return The created port tuple
+ */
+ static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(u32 max_sessions, std::string name = "UnknownPort");
+
+ std::string GetTypeName() const override { return "ServerPort"; }
+ std::string GetName() const override { return name; }
+
+ static const HandleType HANDLE_TYPE = HandleType::ServerPort;
+ HandleType GetHandleType() const override { return HANDLE_TYPE; }
+
+ std::string name; ///< Name of port (optional)
+
+ std::vector<SharedPtr<WaitObject>> pending_sessions; ///< ServerSessions waiting to be accepted by the port
+
+ bool ShouldWait() override;
+ void Acquire() override;
+
+private:
+ ServerPort();
+ ~ServerPort() override;
+};
+
+} // namespace
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index d216cecb4..cdec11388 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <cmath>
+
#include "common/logging/log.h"
#include "common/emu_window.h"
@@ -19,8 +21,6 @@
namespace Service {
namespace HID {
-static const int MAX_CIRCLEPAD_POS = 0x9C; ///< Max value for a circle pad position
-
// Handle to shared memory region designated to HID_User service
static Kernel::SharedPtr<Kernel::SharedMemory> shared_mem;
@@ -39,38 +39,48 @@ static u32 next_gyroscope_index;
static int enable_accelerometer_count = 0; // positive means enabled
static int enable_gyroscope_count = 0; // positive means enabled
-const std::array<Service::HID::PadState, Settings::NativeInput::NUM_INPUTS> pad_mapping = {{
- Service::HID::PAD_A, Service::HID::PAD_B, Service::HID::PAD_X, Service::HID::PAD_Y,
- Service::HID::PAD_L, Service::HID::PAD_R, Service::HID::PAD_ZL, Service::HID::PAD_ZR,
- Service::HID::PAD_START, Service::HID::PAD_SELECT, Service::HID::PAD_NONE,
- Service::HID::PAD_UP, Service::HID::PAD_DOWN, Service::HID::PAD_LEFT, Service::HID::PAD_RIGHT,
- Service::HID::PAD_CIRCLE_UP, Service::HID::PAD_CIRCLE_DOWN, Service::HID::PAD_CIRCLE_LEFT, Service::HID::PAD_CIRCLE_RIGHT,
- Service::HID::PAD_C_UP, Service::HID::PAD_C_DOWN, Service::HID::PAD_C_LEFT, Service::HID::PAD_C_RIGHT
-}};
-
-
-// TODO(peachum):
-// Add a method for setting analog input from joystick device for the circle Pad.
-//
-// This method should:
-// * Be called after both PadButton<Press, Release>().
-// * Be called before PadUpdateComplete()
-// * Set current PadEntry.circle_pad_<axis> using analog data
-// * Set PadData.raw_circle_pad_data
-// * Set PadData.current_state.circle_right = 1 if current PadEntry.circle_pad_x >= 41
-// * Set PadData.current_state.circle_up = 1 if current PadEntry.circle_pad_y >= 41
-// * Set PadData.current_state.circle_left = 1 if current PadEntry.circle_pad_x <= -41
-// * Set PadData.current_state.circle_right = 1 if current PadEntry.circle_pad_y <= -41
+static PadState GetCirclePadDirectionState(s16 circle_pad_x, s16 circle_pad_y) {
+ constexpr float TAN30 = 0.577350269, TAN60 = 1 / TAN30; // 30 degree and 60 degree are angular thresholds for directions
+ constexpr int CIRCLE_PAD_THRESHOLD_SQUARE = 40 * 40; // a circle pad radius greater than 40 will trigger circle pad direction
+ PadState state;
+ state.hex = 0;
+
+ if (circle_pad_x * circle_pad_x + circle_pad_y * circle_pad_y > CIRCLE_PAD_THRESHOLD_SQUARE) {
+ float t = std::abs(static_cast<float>(circle_pad_y) / circle_pad_x);
+
+ if (circle_pad_x != 0 && t < TAN60) {
+ if (circle_pad_x > 0)
+ state.circle_right.Assign(1);
+ else
+ state.circle_left.Assign(1);
+ }
+
+ if (circle_pad_x == 0 || t > TAN30) {
+ if (circle_pad_y > 0)
+ state.circle_up.Assign(1);
+ else
+ state.circle_down.Assign(1);
+ }
+ }
+
+ return state;
+}
void Update() {
SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer());
- const PadState state = VideoCore::g_emu_window->GetPadState();
if (mem == nullptr) {
LOG_DEBUG(Service_HID, "Cannot update HID prior to mapping shared memory!");
return;
}
+ PadState state = VideoCore::g_emu_window->GetPadState();
+
+ // Get current circle pad position and update circle pad direction
+ s16 circle_pad_x, circle_pad_y;
+ std::tie(circle_pad_x, circle_pad_y) = VideoCore::g_emu_window->GetCirclePadState();
+ state.hex |= GetCirclePadDirectionState(circle_pad_x, circle_pad_y).hex;
+
mem->pad.current_state.hex = state.hex;
mem->pad.index = next_pad_index;
next_pad_index = (next_pad_index + 1) % mem->pad.entries.size();
@@ -88,13 +98,9 @@ void Update() {
// Update entry properties
pad_entry.current_state.hex = state.hex;
pad_entry.delta_additions.hex = changed.hex & state.hex;
- pad_entry.delta_removals.hex = changed.hex & old_state.hex;;
-
- // Set circle Pad
- pad_entry.circle_pad_x = state.circle_left ? -MAX_CIRCLEPAD_POS :
- state.circle_right ? MAX_CIRCLEPAD_POS : 0x0;
- pad_entry.circle_pad_y = state.circle_down ? -MAX_CIRCLEPAD_POS :
- state.circle_up ? MAX_CIRCLEPAD_POS : 0x0;
+ pad_entry.delta_removals.hex = changed.hex & old_state.hex;
+ pad_entry.circle_pad_x = circle_pad_x;
+ pad_entry.circle_pad_y = circle_pad_y;
// If we just updated index 0, provide a new timestamp
if (mem->pad.index == 0) {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 170d19ea8..669b1f723 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -215,9 +215,6 @@ const PadState PAD_CIRCLE_LEFT = {{1u << 29}};
const PadState PAD_CIRCLE_UP = {{1u << 30}};
const PadState PAD_CIRCLE_DOWN = {{1u << 31}};
-
-extern const std::array<Service::HID::PadState, Settings::NativeInput::NUM_INPUTS> pad_mapping;
-
/**
* HID::GetIPCHandles service function
* Inputs:
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 0ce72de87..5d71d5619 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -14,12 +14,14 @@
#include "core/arm/arm_interface.h"
#include "core/hle/kernel/address_arbiter.h"
+#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/memory.h"
#include "core/hle/kernel/mutex.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/semaphore.h"
+#include "core/hle/kernel/server_port.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/timer.h"
@@ -834,6 +836,23 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
return RESULT_SUCCESS;
}
+static ResultCode CreatePort(Handle* server_port, Handle* client_port, const char* name, u32 max_sessions) {
+ // TODO(Subv): Implement named ports.
+ ASSERT_MSG(name == nullptr, "Named ports are currently unimplemented");
+
+ using Kernel::ServerPort;
+ using Kernel::ClientPort;
+ using Kernel::SharedPtr;
+
+ auto ports = ServerPort::CreatePortPair(max_sessions);
+ CASCADE_RESULT(*client_port, Kernel::g_handle_table.Create(std::move(std::get<SharedPtr<ClientPort>>(ports))));
+ // Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be created.
+ CASCADE_RESULT(*server_port, Kernel::g_handle_table.Create(std::move(std::get<SharedPtr<ServerPort>>(ports))));
+
+ LOG_TRACE(Kernel_SVC, "called max_sessions=%u", max_sessions);
+ return RESULT_SUCCESS;
+}
+
static ResultCode GetSystemInfo(s64* out, u32 type, s32 param) {
using Kernel::MemoryRegion;
@@ -1011,7 +1030,7 @@ static const FunctionDef SVC_Table[] = {
{0x44, nullptr, "Unknown"},
{0x45, nullptr, "Unknown"},
{0x46, nullptr, "Unknown"},
- {0x47, nullptr, "CreatePort"},
+ {0x47, HLE::Wrap<CreatePort>, "CreatePort"},
{0x48, nullptr, "CreateSessionToPort"},
{0x49, nullptr, "CreateSession"},
{0x4A, nullptr, "AcceptSession"},
diff --git a/src/core/settings.h b/src/core/settings.h
index ea72f4d9c..f95e62390 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -13,29 +13,40 @@ namespace Settings {
namespace NativeInput {
enum Values {
+ // directly mapped keys
A, B, X, Y,
L, R, ZL, ZR,
START, SELECT, HOME,
DUP, DDOWN, DLEFT, DRIGHT,
- SUP, SDOWN, SLEFT, SRIGHT,
CUP, CDOWN, CLEFT, CRIGHT,
+
+ // indirectly mapped keys
+ CIRCLE_UP, CIRCLE_DOWN, CIRCLE_LEFT, CIRCLE_RIGHT,
+ CIRCLE_MODIFIER,
+
NUM_INPUTS
};
+
static const std::array<const char*, NUM_INPUTS> Mapping = {{
+ // directly mapped keys
"pad_a", "pad_b", "pad_x", "pad_y",
"pad_l", "pad_r", "pad_zl", "pad_zr",
"pad_start", "pad_select", "pad_home",
"pad_dup", "pad_ddown", "pad_dleft", "pad_dright",
- "pad_sup", "pad_sdown", "pad_sleft", "pad_sright",
- "pad_cup", "pad_cdown", "pad_cleft", "pad_cright"
+ "pad_cup", "pad_cdown", "pad_cleft", "pad_cright",
+
+ // indirectly mapped keys
+ "pad_circle_up", "pad_circle_down", "pad_circle_left", "pad_circle_right",
+ "pad_circle_modifier",
}};
static const std::array<Values, NUM_INPUTS> All = {{
A, B, X, Y,
L, R, ZL, ZR,
START, SELECT, HOME,
DUP, DDOWN, DLEFT, DRIGHT,
- SUP, SDOWN, SLEFT, SRIGHT,
- CUP, CDOWN, CLEFT, CRIGHT
+ CUP, CDOWN, CLEFT, CRIGHT,
+ CIRCLE_UP, CIRCLE_DOWN, CIRCLE_LEFT, CIRCLE_RIGHT,
+ CIRCLE_MODIFIER,
}};
}
@@ -46,6 +57,7 @@ struct Values {
// Controls
std::array<int, NativeInput::NUM_INPUTS> input_mappings;
+ float pad_circle_modifier_scale;
// Core
int frame_skip;