summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service')
-rw-r--r--src/core/hle/service/err_f.cpp2
-rw-r--r--src/core/hle/service/gsp_gpu.cpp2
-rw-r--r--src/core/hle/service/hid/hid.cpp150
-rw-r--r--src/core/hle/service/hid/hid.h3
-rw-r--r--src/core/hle/service/mic_u.cpp8
-rw-r--r--src/core/hle/service/nfc/nfc.cpp105
-rw-r--r--src/core/hle/service/nfc/nfc.h122
-rw-r--r--src/core/hle/service/nfc/nfc_m.cpp21
-rw-r--r--src/core/hle/service/nfc/nfc_u.cpp21
9 files changed, 351 insertions, 83 deletions
diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp
index cd0a1a598..9da55f328 100644
--- a/src/core/hle/service/err_f.cpp
+++ b/src/core/hle/service/err_f.cpp
@@ -227,6 +227,8 @@ static void ThrowFatalError(Interface* self) {
LOG_CRITICAL(Service_ERR, "FINST2: 0x%08X",
errtype.exception_data.exception_info.fpinst2);
break;
+ case ExceptionType::Undefined:
+ break; // Not logging exception_info for this case
}
LOG_CRITICAL(Service_ERR, "Datetime: %s", GetCurrentSystemTime().c_str());
break;
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 947958703..a8c1331ed 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -149,7 +149,7 @@ static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, VAddr
u32 mask = Memory::Read32(masks_vaddr);
// Update the current value of the register only for set mask bits
- reg_value = (reg_value & ~mask) | (data | mask);
+ reg_value = (reg_value & ~mask) | (data & mask);
WriteSingleHWReg(base_address, reg_value);
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 676154bd4..f14ab3811 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -35,6 +35,15 @@ static u32 next_gyroscope_index;
static int enable_accelerometer_count = 0; // positive means enabled
static int enable_gyroscope_count = 0; // positive means enabled
+static int pad_update_event;
+static int accelerometer_update_event;
+static int gyroscope_update_event;
+
+// Updating period for each HID device. These empirical values are measured from a 11.2 3DS.
+constexpr u64 pad_update_ticks = BASE_CLOCK_RATE_ARM11 / 234;
+constexpr u64 accelerometer_update_ticks = BASE_CLOCK_RATE_ARM11 / 104;
+constexpr u64 gyroscope_update_ticks = BASE_CLOCK_RATE_ARM11 / 101;
+
static PadState GetCirclePadDirectionState(s16 circle_pad_x, s16 circle_pad_y) {
// 30 degree and 60 degree are angular thresholds for directions
constexpr float TAN30 = 0.577350269f;
@@ -65,14 +74,9 @@ static PadState GetCirclePadDirectionState(s16 circle_pad_x, s16 circle_pad_y) {
return state;
}
-void Update() {
+static void UpdatePadCallback(u64 userdata, int cycles_late) {
SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer());
- 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
@@ -131,59 +135,68 @@ void Update() {
event_pad_or_touch_1->Signal();
event_pad_or_touch_2->Signal();
- // Update accelerometer
- if (enable_accelerometer_count > 0) {
- mem->accelerometer.index = next_accelerometer_index;
- next_accelerometer_index =
- (next_accelerometer_index + 1) % mem->accelerometer.entries.size();
-
- AccelerometerDataEntry& accelerometer_entry =
- mem->accelerometer.entries[mem->accelerometer.index];
- std::tie(accelerometer_entry.x, accelerometer_entry.y, accelerometer_entry.z) =
- VideoCore::g_emu_window->GetAccelerometerState();
-
- // Make up "raw" entry
- // TODO(wwylele):
- // From hardware testing, the raw_entry values are approximately,
- // but not exactly, as twice as corresponding entries (or with a minus sign).
- // It may caused by system calibration to the accelerometer.
- // Figure out how it works, or, if no game reads raw_entry,
- // the following three lines can be removed and leave raw_entry unimplemented.
- mem->accelerometer.raw_entry.x = -2 * accelerometer_entry.x;
- mem->accelerometer.raw_entry.z = 2 * accelerometer_entry.y;
- mem->accelerometer.raw_entry.y = -2 * accelerometer_entry.z;
-
- // If we just updated index 0, provide a new timestamp
- if (mem->accelerometer.index == 0) {
- mem->accelerometer.index_reset_ticks_previous = mem->accelerometer.index_reset_ticks;
- mem->accelerometer.index_reset_ticks = (s64)CoreTiming::GetTicks();
- }
+ // Reschedule recurrent event
+ CoreTiming::ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event);
+}
+
+static void UpdateAccelerometerCallback(u64 userdata, int cycles_late) {
+ SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer());
+
+ mem->accelerometer.index = next_accelerometer_index;
+ next_accelerometer_index = (next_accelerometer_index + 1) % mem->accelerometer.entries.size();
- event_accelerometer->Signal();
+ AccelerometerDataEntry& accelerometer_entry =
+ mem->accelerometer.entries[mem->accelerometer.index];
+ std::tie(accelerometer_entry.x, accelerometer_entry.y, accelerometer_entry.z) =
+ VideoCore::g_emu_window->GetAccelerometerState();
+
+ // Make up "raw" entry
+ // TODO(wwylele):
+ // From hardware testing, the raw_entry values are approximately, but not exactly, as twice as
+ // corresponding entries (or with a minus sign). It may caused by system calibration to the
+ // accelerometer. Figure out how it works, or, if no game reads raw_entry, the following three
+ // lines can be removed and leave raw_entry unimplemented.
+ mem->accelerometer.raw_entry.x = -2 * accelerometer_entry.x;
+ mem->accelerometer.raw_entry.z = 2 * accelerometer_entry.y;
+ mem->accelerometer.raw_entry.y = -2 * accelerometer_entry.z;
+
+ // If we just updated index 0, provide a new timestamp
+ if (mem->accelerometer.index == 0) {
+ mem->accelerometer.index_reset_ticks_previous = mem->accelerometer.index_reset_ticks;
+ mem->accelerometer.index_reset_ticks = (s64)CoreTiming::GetTicks();
}
- // Update gyroscope
- if (enable_gyroscope_count > 0) {
- mem->gyroscope.index = next_gyroscope_index;
- next_gyroscope_index = (next_gyroscope_index + 1) % mem->gyroscope.entries.size();
+ event_accelerometer->Signal();
- GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index];
- std::tie(gyroscope_entry.x, gyroscope_entry.y, gyroscope_entry.z) =
- VideoCore::g_emu_window->GetGyroscopeState();
+ // Reschedule recurrent event
+ CoreTiming::ScheduleEvent(accelerometer_update_ticks - cycles_late, accelerometer_update_event);
+}
- // Make up "raw" entry
- mem->gyroscope.raw_entry.x = gyroscope_entry.x;
- mem->gyroscope.raw_entry.z = -gyroscope_entry.y;
- mem->gyroscope.raw_entry.y = gyroscope_entry.z;
+static void UpdateGyroscopeCallback(u64 userdata, int cycles_late) {
+ SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer());
- // If we just updated index 0, provide a new timestamp
- if (mem->gyroscope.index == 0) {
- mem->gyroscope.index_reset_ticks_previous = mem->gyroscope.index_reset_ticks;
- mem->gyroscope.index_reset_ticks = (s64)CoreTiming::GetTicks();
- }
+ mem->gyroscope.index = next_gyroscope_index;
+ next_gyroscope_index = (next_gyroscope_index + 1) % mem->gyroscope.entries.size();
+
+ GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index];
+ std::tie(gyroscope_entry.x, gyroscope_entry.y, gyroscope_entry.z) =
+ VideoCore::g_emu_window->GetGyroscopeState();
+
+ // Make up "raw" entry
+ mem->gyroscope.raw_entry.x = gyroscope_entry.x;
+ mem->gyroscope.raw_entry.z = -gyroscope_entry.y;
+ mem->gyroscope.raw_entry.y = gyroscope_entry.z;
- event_gyroscope->Signal();
+ // If we just updated index 0, provide a new timestamp
+ if (mem->gyroscope.index == 0) {
+ mem->gyroscope.index_reset_ticks_previous = mem->gyroscope.index_reset_ticks;
+ mem->gyroscope.index_reset_ticks = (s64)CoreTiming::GetTicks();
}
+
+ event_gyroscope->Signal();
+
+ // Reschedule recurrent event
+ CoreTiming::ScheduleEvent(gyroscope_update_ticks - cycles_late, gyroscope_update_event);
}
void GetIPCHandles(Service::Interface* self) {
@@ -204,7 +217,11 @@ void EnableAccelerometer(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
++enable_accelerometer_count;
- event_accelerometer->Signal();
+
+ // Schedules the accelerometer update event if the accelerometer was just enabled
+ if (enable_accelerometer_count == 1) {
+ CoreTiming::ScheduleEvent(accelerometer_update_ticks, accelerometer_update_event);
+ }
cmd_buff[1] = RESULT_SUCCESS.raw;
@@ -215,7 +232,11 @@ void DisableAccelerometer(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
--enable_accelerometer_count;
- event_accelerometer->Signal();
+
+ // Unschedules the accelerometer update event if the accelerometer was just disabled
+ if (enable_accelerometer_count == 0) {
+ CoreTiming::UnscheduleEvent(accelerometer_update_event, 0);
+ }
cmd_buff[1] = RESULT_SUCCESS.raw;
@@ -226,7 +247,11 @@ void EnableGyroscopeLow(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
++enable_gyroscope_count;
- event_gyroscope->Signal();
+
+ // Schedules the gyroscope update event if the gyroscope was just enabled
+ if (enable_gyroscope_count == 1) {
+ CoreTiming::ScheduleEvent(gyroscope_update_ticks, gyroscope_update_event);
+ }
cmd_buff[1] = RESULT_SUCCESS.raw;
@@ -237,7 +262,11 @@ void DisableGyroscopeLow(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
--enable_gyroscope_count;
- event_gyroscope->Signal();
+
+ // Unschedules the gyroscope update event if the gyroscope was just disabled
+ if (enable_gyroscope_count == 0) {
+ CoreTiming::UnscheduleEvent(gyroscope_update_event, 0);
+ }
cmd_buff[1] = RESULT_SUCCESS.raw;
@@ -291,6 +320,8 @@ void Init() {
next_pad_index = 0;
next_touch_index = 0;
+ next_accelerometer_index = 0;
+ next_gyroscope_index = 0;
// Create event handles
event_pad_or_touch_1 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch1");
@@ -298,6 +329,15 @@ void Init() {
event_accelerometer = Event::Create(ResetType::OneShot, "HID:EventAccelerometer");
event_gyroscope = Event::Create(ResetType::OneShot, "HID:EventGyroscope");
event_debug_pad = Event::Create(ResetType::OneShot, "HID:EventDebugPad");
+
+ // Register update callbacks
+ pad_update_event = CoreTiming::RegisterEvent("HID::UpdatePadCallback", UpdatePadCallback);
+ accelerometer_update_event =
+ CoreTiming::RegisterEvent("HID::UpdateAccelerometerCallback", UpdateAccelerometerCallback);
+ gyroscope_update_event =
+ CoreTiming::RegisterEvent("HID::UpdateGyroscopeCallback", UpdateGyroscopeCallback);
+
+ CoreTiming::ScheduleEvent(pad_update_ticks, pad_update_event);
}
void Shutdown() {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 7904e7355..21e66dfe0 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -296,9 +296,6 @@ void GetGyroscopeLowRawToDpsCoefficient(Service::Interface* self);
*/
void GetGyroscopeLowCalibrateParam(Service::Interface* self);
-/// Checks for user input updates
-void Update();
-
/// Initialize HID service
void Init();
diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp
index c62f8afc6..e98388560 100644
--- a/src/core/hle/service/mic_u.cpp
+++ b/src/core/hle/service/mic_u.cpp
@@ -93,7 +93,7 @@ static void StartSampling(Interface* self) {
sample_rate = static_cast<SampleRate>(cmd_buff[2] & 0xFF);
audio_buffer_offset = cmd_buff[3];
audio_buffer_size = cmd_buff[4];
- audio_buffer_loop = static_cast<bool>(cmd_buff[5] & 0xFF);
+ audio_buffer_loop = (cmd_buff[5] & 0xFF) != 0;
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
is_sampling = true;
@@ -202,7 +202,7 @@ static void GetGain(Interface* self) {
*/
static void SetPower(Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- mic_power = static_cast<bool>(cmd_buff[1] & 0xFF);
+ mic_power = (cmd_buff[1] & 0xFF) != 0;
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
LOG_WARNING(Service_MIC, "(STUBBED) called, mic_power=%u", mic_power);
}
@@ -252,7 +252,7 @@ static void SetIirFilterMic(Interface* self) {
*/
static void SetClamp(Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- clamp = static_cast<bool>(cmd_buff[1] & 0xFF);
+ clamp = (cmd_buff[1] & 0xFF) != 0;
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
LOG_WARNING(Service_MIC, "(STUBBED) called, clamp=%u", clamp);
}
@@ -282,7 +282,7 @@ static void GetClamp(Interface* self) {
*/
static void SetAllowShellClosed(Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- allow_shell_closed = static_cast<bool>(cmd_buff[1] & 0xFF);
+ allow_shell_closed = (cmd_buff[1] & 0xFF) != 0;
cmd_buff[1] = RESULT_SUCCESS.raw; // No error
LOG_WARNING(Service_MIC, "(STUBBED) called, allow_shell_closed=%u", allow_shell_closed);
}
diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp
index e248285f9..fd3c7d9c2 100644
--- a/src/core/hle/service/nfc/nfc.cpp
+++ b/src/core/hle/service/nfc/nfc.cpp
@@ -11,6 +11,81 @@ namespace Service {
namespace NFC {
static Kernel::SharedPtr<Kernel::Event> tag_in_range_event;
+static Kernel::SharedPtr<Kernel::Event> tag_out_of_range_event;
+static TagState nfc_tag_state = TagState::NotInitialized;
+static CommunicationStatus nfc_status = CommunicationStatus::NfcInitialized;
+
+void Initialize(Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u8 param = static_cast<u8>(cmd_buff[1] & 0xFF);
+
+ nfc_tag_state = TagState::NotScanning;
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_NFC, "(STUBBED) called, param=%u", param);
+}
+
+void Shutdown(Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u8 param = static_cast<u8>(cmd_buff[1] & 0xFF);
+ nfc_tag_state = TagState::NotInitialized;
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_NFC, "(STUBBED) called, param=%u", param);
+}
+
+void StartCommunication(Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_NFC, "(STUBBED) called");
+}
+
+void StopCommunication(Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_NFC, "(STUBBED) called");
+}
+
+void StartTagScanning(Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ nfc_tag_state = TagState::TagInRange;
+ tag_in_range_event->Signal();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_NFC, "(STUBBED) called");
+}
+
+void StopTagScanning(Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ nfc_tag_state = TagState::NotScanning;
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_NFC, "(STUBBED) called");
+}
+
+void LoadAmiiboData(Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ nfc_tag_state = TagState::TagDataLoaded;
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_NFC, "(STUBBED) called");
+}
+
+void ResetTagScanState(Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ nfc_tag_state = TagState::NotScanning;
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_NFC, "(STUBBED) called");
+}
void GetTagInRangeEvent(Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
@@ -22,16 +97,46 @@ void GetTagInRangeEvent(Interface* self) {
LOG_WARNING(Service_NFC, "(STUBBED) called");
}
+void GetTagOutOfRangeEvent(Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[0] = IPC::MakeHeader(0xC, 1, 2);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ cmd_buff[2] = IPC::CopyHandleDesc();
+ cmd_buff[3] = Kernel::g_handle_table.Create(tag_out_of_range_event).MoveFrom();
+ LOG_WARNING(Service_NFC, "(STUBBED) called");
+}
+
+void GetTagState(Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[2] = static_cast<u8>(nfc_tag_state);
+ LOG_DEBUG(Service_NFC, "(STUBBED) called");
+}
+
+void CommunicationGetStatus(Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[2] = static_cast<u8>(nfc_status);
+ LOG_DEBUG(Service_NFC, "(STUBBED) called");
+}
+
void Init() {
AddService(new NFC_M());
AddService(new NFC_U());
tag_in_range_event =
Kernel::Event::Create(Kernel::ResetType::OneShot, "NFC::tag_in_range_event");
+ tag_out_of_range_event =
+ Kernel::Event::Create(Kernel::ResetType::OneShot, "NFC::tag_out_range_event");
+ nfc_tag_state = TagState::NotInitialized;
}
void Shutdown() {
tag_in_range_event = nullptr;
+ tag_out_of_range_event = nullptr;
}
} // namespace NFC
diff --git a/src/core/hle/service/nfc/nfc.h b/src/core/hle/service/nfc/nfc.h
index b02354201..a013bdae7 100644
--- a/src/core/hle/service/nfc/nfc.h
+++ b/src/core/hle/service/nfc/nfc.h
@@ -4,12 +4,103 @@
#pragma once
+#include "common/common_types.h"
+
namespace Service {
class Interface;
namespace NFC {
+enum class TagState : u8 {
+ NotInitialized = 0,
+ NotScanning = 1,
+ Scanning = 2,
+ TagInRange = 3,
+ TagOutOfRange = 4,
+ TagDataLoaded = 5,
+};
+
+enum class CommunicationStatus : u8 {
+ AttemptInitialize = 1,
+ NfcInitialized = 2,
+};
+
+/**
+ * NFC::Initialize service function
+ * Inputs:
+ * 0 : Header code [0x00010040]
+ * 1 : (u8) unknown parameter. Can be either value 0x1 or 0x2
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void Initialize(Interface* self);
+
+/**
+ * NFC::Shutdown service function
+ * Inputs:
+ * 0 : Header code [0x00020040]
+ * 1 : (u8) unknown parameter
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void Shutdown(Interface* self);
+
+/**
+ * NFC::StartCommunication service function
+ * Inputs:
+ * 0 : Header code [0x00030000]
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void StartCommunication(Interface* self);
+
+/**
+ * NFC::StopCommunication service function
+ * Inputs:
+ * 0 : Header code [0x00040000]
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void StopCommunication(Interface* self);
+
+/**
+ * NFC::StartTagScanning service function
+ * Inputs:
+ * 0 : Header code [0x00050040]
+ * 1 : (u16) unknown. This is normally 0x0
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void StartTagScanning(Interface* self);
+
+/**
+ * NFC::StopTagScanning service function
+ * Inputs:
+ * 0 : Header code [0x00060000]
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void StopTagScanning(Interface* self);
+
+/**
+ * NFC::LoadAmiiboData service function
+ * Inputs:
+ * 0 : Header code [0x00070000]
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void LoadAmiiboData(Interface* self);
+
+/**
+ * NFC::ResetTagScanState service function
+ * Inputs:
+ * 0 : Header code [0x00080000]
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void ResetTagScanState(Interface* self);
+
/**
* NFC::GetTagInRangeEvent service function
* Inputs:
@@ -21,6 +112,37 @@ namespace NFC {
*/
void GetTagInRangeEvent(Interface* self);
+/**
+ * NFC::GetTagOutOfRangeEvent service function
+ * Inputs:
+ * 0 : Header code [0x000C0000]
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Copy handle descriptor
+ * 3 : Event Handle
+ */
+void GetTagOutOfRangeEvent(Interface* self);
+
+/**
+ * NFC::GetTagState service function
+ * Inputs:
+ * 0 : Header code [0x000D0000]
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : (u8) Tag state
+ */
+void GetTagState(Interface* self);
+
+/**
+ * NFC::CommunicationGetStatus service function
+ * Inputs:
+ * 0 : Header code [0x000F0000]
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : (u8) Communication state
+ */
+void CommunicationGetStatus(Interface* self);
+
/// Initialize all NFC services.
void Init();
diff --git a/src/core/hle/service/nfc/nfc_m.cpp b/src/core/hle/service/nfc/nfc_m.cpp
index f43b4029a..ebe637650 100644
--- a/src/core/hle/service/nfc/nfc_m.cpp
+++ b/src/core/hle/service/nfc/nfc_m.cpp
@@ -11,18 +11,19 @@ namespace NFC {
const Interface::FunctionInfo FunctionTable[] = {
// clang-format off
// nfc:u shared commands
- {0x00010040, nullptr, "Initialize"},
- {0x00020040, nullptr, "Shutdown"},
- {0x00030000, nullptr, "StartCommunication"},
- {0x00040000, nullptr, "StopCommunication"},
- {0x00050040, nullptr, "StartTagScanning"},
- {0x00060000, nullptr, "StopTagScanning"},
- {0x00070000, nullptr, "LoadAmiiboData"},
- {0x00080000, nullptr, "ResetTagScanState"},
+ {0x00010040, Initialize, "Initialize"},
+ {0x00020040, Shutdown, "Shutdown"},
+ {0x00030000, StartCommunication, "StartCommunication"},
+ {0x00040000, StopCommunication, "StopCommunication"},
+ {0x00050040, StartTagScanning, "StartTagScanning"},
+ {0x00060000, StopTagScanning, "StopTagScanning"},
+ {0x00070000, LoadAmiiboData, "LoadAmiiboData"},
+ {0x00080000, ResetTagScanState, "ResetTagScanState"},
{0x00090002, nullptr, "UpdateStoredAmiiboData"},
{0x000B0000, GetTagInRangeEvent, "GetTagInRangeEvent"},
- {0x000D0000, nullptr, "GetTagState"},
- {0x000F0000, nullptr, "CommunicationGetStatus"},
+ {0x000C0000, GetTagOutOfRangeEvent, "GetTagOutOfRangeEvent"},
+ {0x000D0000, GetTagState, "GetTagState"},
+ {0x000F0000, CommunicationGetStatus, "CommunicationGetStatus"},
{0x00100000, nullptr, "GetTagInfo2"},
{0x00110000, nullptr, "GetTagInfo"},
{0x00120000, nullptr, "CommunicationGetResult"},
diff --git a/src/core/hle/service/nfc/nfc_u.cpp b/src/core/hle/service/nfc/nfc_u.cpp
index 4b5200ae8..5a40c7874 100644
--- a/src/core/hle/service/nfc/nfc_u.cpp
+++ b/src/core/hle/service/nfc/nfc_u.cpp
@@ -10,18 +10,19 @@ namespace NFC {
const Interface::FunctionInfo FunctionTable[] = {
// clang-format off
- {0x00010040, nullptr, "Initialize"},
- {0x00020040, nullptr, "Shutdown"},
- {0x00030000, nullptr, "StartCommunication"},
- {0x00040000, nullptr, "StopCommunication"},
- {0x00050040, nullptr, "StartTagScanning"},
- {0x00060000, nullptr, "StopTagScanning"},
- {0x00070000, nullptr, "LoadAmiiboData"},
- {0x00080000, nullptr, "ResetTagScanState"},
+ {0x00010040, Initialize, "Initialize"},
+ {0x00020040, Shutdown, "Shutdown"},
+ {0x00030000, StartCommunication, "StartCommunication"},
+ {0x00040000, StopCommunication, "StopCommunication"},
+ {0x00050040, StartTagScanning, "StartTagScanning"},
+ {0x00060000, StopTagScanning, "StopTagScanning"},
+ {0x00070000, LoadAmiiboData, "LoadAmiiboData"},
+ {0x00080000, ResetTagScanState, "ResetTagScanState"},
{0x00090002, nullptr, "UpdateStoredAmiiboData"},
{0x000B0000, GetTagInRangeEvent, "GetTagInRangeEvent"},
- {0x000D0000, nullptr, "GetTagState"},
- {0x000F0000, nullptr, "CommunicationGetStatus"},
+ {0x000C0000, GetTagOutOfRangeEvent, "GetTagOutOfRangeEvent"},
+ {0x000D0000, GetTagState, "GetTagState"},
+ {0x000F0000, CommunicationGetStatus, "CommunicationGetStatus"},
{0x00100000, nullptr, "GetTagInfo2"},
{0x00110000, nullptr, "GetTagInfo"},
{0x00120000, nullptr, "CommunicationGetResult"},