aboutsummaryrefslogtreecommitdiff
path: root/src/core/hle
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/ipc_helpers.h7
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp38
-rw-r--r--src/core/hle/kernel/address_arbiter.h4
-rw-r--r--src/core/hle/kernel/client_port.cpp17
-rw-r--r--src/core/hle/kernel/client_port.h16
-rw-r--r--src/core/hle/kernel/client_session.cpp2
-rw-r--r--src/core/hle/kernel/client_session.h2
-rw-r--r--src/core/hle/kernel/event.cpp4
-rw-r--r--src/core/hle/kernel/event.h14
-rw-r--r--src/core/hle/kernel/handle_table.cpp1
-rw-r--r--src/core/hle/kernel/handle_table.h2
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp9
-rw-r--r--src/core/hle/kernel/hle_ipc.h5
-rw-r--r--src/core/hle/kernel/kernel.cpp10
-rw-r--r--src/core/hle/kernel/kernel.h112
-rw-r--r--src/core/hle/kernel/memory.cpp92
-rw-r--r--src/core/hle/kernel/memory.h31
-rw-r--r--src/core/hle/kernel/mutex.cpp7
-rw-r--r--src/core/hle/kernel/mutex.h8
-rw-r--r--src/core/hle/kernel/object.cpp35
-rw-r--r--src/core/hle/kernel/object.h101
-rw-r--r--src/core/hle/kernel/object_address_table.cpp36
-rw-r--r--src/core/hle/kernel/object_address_table.h62
-rw-r--r--src/core/hle/kernel/process.cpp84
-rw-r--r--src/core/hle/kernel/process.h64
-rw-r--r--src/core/hle/kernel/resource_limit.h2
-rw-r--r--src/core/hle/kernel/scheduler.cpp6
-rw-r--r--src/core/hle/kernel/scheduler.h6
-rw-r--r--src/core/hle/kernel/server_port.cpp2
-rw-r--r--src/core/hle/kernel/server_port.h3
-rw-r--r--src/core/hle/kernel/server_session.cpp14
-rw-r--r--src/core/hle/kernel/server_session.h13
-rw-r--r--src/core/hle/kernel/session.h2
-rw-r--r--src/core/hle/kernel/shared_memory.cpp37
-rw-r--r--src/core/hle/kernel/shared_memory.h8
-rw-r--r--src/core/hle/kernel/svc.cpp17
-rw-r--r--src/core/hle/kernel/thread.cpp90
-rw-r--r--src/core/hle/kernel/thread.h15
-rw-r--r--src/core/hle/kernel/timer.cpp2
-rw-r--r--src/core/hle/kernel/timer.h24
-rw-r--r--src/core/hle/kernel/vm_manager.cpp36
-rw-r--r--src/core/hle/kernel/vm_manager.h8
-rw-r--r--src/core/hle/kernel/wait_object.cpp5
-rw-r--r--src/core/hle/kernel/wait_object.h2
-rw-r--r--src/core/hle/romfs.cpp102
-rw-r--r--src/core/hle/romfs.h22
-rw-r--r--src/core/hle/service/acc/acc.cpp60
-rw-r--r--src/core/hle/service/acc/acc.h1
-rw-r--r--src/core/hle/service/acc/acc_su.cpp2
-rw-r--r--src/core/hle/service/acc/acc_u0.cpp2
-rw-r--r--src/core/hle/service/acc/acc_u1.cpp2
-rw-r--r--src/core/hle/service/am/am.cpp52
-rw-r--r--src/core/hle/service/am/am.h5
-rw-r--r--src/core/hle/service/am/idle.cpp24
-rw-r--r--src/core/hle/service/am/idle.h16
-rw-r--r--src/core/hle/service/am/omm.cpp42
-rw-r--r--src/core/hle/service/am/omm.h16
-rw-r--r--src/core/hle/service/am/spsm.cpp30
-rw-r--r--src/core/hle/service/am/spsm.h16
-rw-r--r--src/core/hle/service/apm/apm.cpp1
-rw-r--r--src/core/hle/service/apm/interface.cpp25
-rw-r--r--src/core/hle/service/apm/interface.h8
-rw-r--r--src/core/hle/service/arp/arp.cpp75
-rw-r--r--src/core/hle/service/arp/arp.h16
-rw-r--r--src/core/hle/service/audio/audctl.cpp45
-rw-r--r--src/core/hle/service/audio/audctl.h16
-rw-r--r--src/core/hle/service/audio/auddbg.cpp20
-rw-r--r--src/core/hle/service/audio/auddbg.h16
-rw-r--r--src/core/hle/service/audio/audin_a.cpp22
-rw-r--r--src/core/hle/service/audio/audin_a.h16
-rw-r--r--src/core/hle/service/audio/audio.cpp16
-rw-r--r--src/core/hle/service/audio/audout_a.cpp24
-rw-r--r--src/core/hle/service/audio/audout_a.h16
-rw-r--r--src/core/hle/service/audio/audout_u.cpp199
-rw-r--r--src/core/hle/service/audio/audout_u.h24
-rw-r--r--src/core/hle/service/audio/audrec_a.cpp20
-rw-r--r--src/core/hle/service/audio/audrec_a.h16
-rw-r--r--src/core/hle/service/audio/audren_a.cpp26
-rw-r--r--src/core/hle/service/audio/audren_a.h16
-rw-r--r--src/core/hle/service/audio/audren_u.cpp250
-rw-r--r--src/core/hle/service/audio/audren_u.h20
-rw-r--r--src/core/hle/service/audio/hwopus.cpp135
-rw-r--r--src/core/hle/service/audio/hwopus.h1
-rw-r--r--src/core/hle/service/bpc/bpc.cpp57
-rw-r--r--src/core/hle/service/bpc/bpc.h15
-rw-r--r--src/core/hle/service/btdrv/btdrv.cpp72
-rw-r--r--src/core/hle/service/btdrv/btdrv.h16
-rw-r--r--src/core/hle/service/btm/btm.cpp121
-rw-r--r--src/core/hle/service/btm/btm.h15
-rw-r--r--src/core/hle/service/caps/caps.cpp152
-rw-r--r--src/core/hle/service/caps/caps.h15
-rw-r--r--src/core/hle/service/fgm/fgm.cpp75
-rw-r--r--src/core/hle/service/fgm/fgm.h15
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp39
-rw-r--r--src/core/hle/service/filesystem/filesystem.h10
-rw-r--r--src/core/hle/service/filesystem/fsp_ldr.cpp22
-rw-r--r--src/core/hle/service/filesystem/fsp_ldr.h16
-rw-r--r--src/core/hle/service/filesystem/fsp_pr.cpp23
-rw-r--r--src/core/hle/service/filesystem/fsp_pr.h16
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp9
-rw-r--r--src/core/hle/service/friend/friend.cpp104
-rw-r--r--src/core/hle/service/grc/grc.cpp31
-rw-r--r--src/core/hle/service/grc/grc.h15
-rw-r--r--src/core/hle/service/hid/hid.cpp261
-rw-r--r--src/core/hle/service/hid/irs.cpp49
-rw-r--r--src/core/hle/service/hid/irs.h21
-rw-r--r--src/core/hle/service/hid/xcd.cpp37
-rw-r--r--src/core/hle/service/hid/xcd.h16
-rw-r--r--src/core/hle/service/lbl/lbl.cpp90
-rw-r--r--src/core/hle/service/lbl/lbl.h15
-rw-r--r--src/core/hle/service/ldn/ldn.cpp142
-rw-r--r--src/core/hle/service/ldn/ldn.h16
-rw-r--r--src/core/hle/service/lm/lm.cpp30
-rw-r--r--src/core/hle/service/mig/mig.cpp34
-rw-r--r--src/core/hle/service/mig/mig.h15
-rw-r--r--src/core/hle/service/mii/mii.cpp107
-rw-r--r--src/core/hle/service/mii/mii.h15
-rw-r--r--src/core/hle/service/mm/mm_u.cpp83
-rw-r--r--src/core/hle/service/mm/mm_u.h15
-rw-r--r--src/core/hle/service/ncm/ncm.cpp59
-rw-r--r--src/core/hle/service/ncm/ncm.h15
-rw-r--r--src/core/hle/service/nfc/nfc.cpp222
-rw-r--r--src/core/hle/service/nfc/nfc.h15
-rw-r--r--src/core/hle/service/nim/nim.cpp124
-rw-r--r--src/core/hle/service/nim/nim.h15
-rw-r--r--src/core/hle/service/ns/ns.cpp447
-rw-r--r--src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp8
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp16
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp3
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl.h2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp16
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp17
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.h1
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvdec.h4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp34
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h36
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_vic.cpp34
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_vic.h36
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp2
-rw-r--r--src/core/hle/service/nvdrv/interface.h1
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.cpp13
-rw-r--r--src/core/hle/service/nvdrv/nvdrv.h8
-rw-r--r--src/core/hle/service/nvdrv/nvmemp.cpp2
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp7
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.h3
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp20
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.h17
-rw-r--r--src/core/hle/service/pcie/pcie.cpp64
-rw-r--r--src/core/hle/service/pcie/pcie.h15
-rw-r--r--src/core/hle/service/pcv/pcv.cpp84
-rw-r--r--src/core/hle/service/pcv/pcv.h15
-rw-r--r--src/core/hle/service/psc/psc.cpp77
-rw-r--r--src/core/hle/service/psc/psc.h15
-rw-r--r--src/core/hle/service/service.cpp48
-rw-r--r--src/core/hle/service/service.h10
-rw-r--r--src/core/hle/service/set/set.cpp15
-rw-r--r--src/core/hle/service/set/set.h2
-rw-r--r--src/core/hle/service/sm/controller.cpp4
-rw-r--r--src/core/hle/service/sm/sm.h8
-rw-r--r--src/core/hle/service/sockets/bsd.cpp22
-rw-r--r--src/core/hle/service/sockets/bsd.h5
-rw-r--r--src/core/hle/service/sockets/ethc.cpp38
-rw-r--r--src/core/hle/service/sockets/ethc.h21
-rw-r--r--src/core/hle/service/sockets/sockets.cpp7
-rw-r--r--src/core/hle/service/time/time.cpp4
-rw-r--r--src/core/hle/service/usb/usb.cpp238
-rw-r--r--src/core/hle/service/usb/usb.h15
-rw-r--r--src/core/hle/service/wlan/wlan.cpp172
-rw-r--r--src/core/hle/service/wlan/wlan.h15
170 files changed, 5074 insertions, 1253 deletions
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h
index 7fb0da408..d3a734831 100644
--- a/src/core/hle/ipc_helpers.h
+++ b/src/core/hle/ipc_helpers.h
@@ -5,15 +5,18 @@
#pragma once
#include <array>
+#include <cstring>
+#include <memory>
#include <tuple>
#include <type_traits>
#include <utility>
+#include "common/assert.h"
+#include "common/common_types.h"
#include "core/hle/ipc.h"
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h"
-#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/hle_ipc.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/server_port.h"
namespace IPC {
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 233fdab25..03a954a9f 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -2,15 +2,17 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <algorithm>
+#include <vector>
+
#include "common/assert.h"
-#include "common/common_funcs.h"
#include "common/common_types.h"
#include "core/core.h"
#include "core/hle/kernel/errors.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/thread.h"
-#include "core/hle/lock.h"
+#include "core/hle/result.h"
#include "core/memory.h"
namespace Kernel {
@@ -30,9 +32,8 @@ static ResultCode WaitForAddress(VAddr address, s64 timeout) {
}
// Gets the threads waiting on an address.
-static void GetThreadsWaitingOnAddress(std::vector<SharedPtr<Thread>>& waiting_threads,
- VAddr address) {
- auto RetrieveWaitingThreads =
+static std::vector<SharedPtr<Thread>> GetThreadsWaitingOnAddress(VAddr address) {
+ const auto RetrieveWaitingThreads =
[](size_t core_index, std::vector<SharedPtr<Thread>>& waiting_threads, VAddr arb_addr) {
const auto& scheduler = Core::System::GetInstance().Scheduler(core_index);
auto& thread_list = scheduler->GetThreadList();
@@ -43,16 +44,20 @@ static void GetThreadsWaitingOnAddress(std::vector<SharedPtr<Thread>>& waiting_t
}
};
- // Retrieve a list of all threads that are waiting for this address.
- RetrieveWaitingThreads(0, waiting_threads, address);
- RetrieveWaitingThreads(1, waiting_threads, address);
- RetrieveWaitingThreads(2, waiting_threads, address);
- RetrieveWaitingThreads(3, waiting_threads, address);
+ // Retrieve all threads that are waiting for this address.
+ std::vector<SharedPtr<Thread>> threads;
+ RetrieveWaitingThreads(0, threads, address);
+ RetrieveWaitingThreads(1, threads, address);
+ RetrieveWaitingThreads(2, threads, address);
+ RetrieveWaitingThreads(3, threads, address);
+
// Sort them by priority, such that the highest priority ones come first.
- std::sort(waiting_threads.begin(), waiting_threads.end(),
+ std::sort(threads.begin(), threads.end(),
[](const SharedPtr<Thread>& lhs, const SharedPtr<Thread>& rhs) {
return lhs->current_priority < rhs->current_priority;
});
+
+ return threads;
}
// Wake up num_to_wake (or all) threads in a vector.
@@ -74,9 +79,7 @@ static void WakeThreads(std::vector<SharedPtr<Thread>>& waiting_threads, s32 num
// Signals an address being waited on.
ResultCode SignalToAddress(VAddr address, s32 num_to_wake) {
- // Get threads waiting on the address.
- std::vector<SharedPtr<Thread>> waiting_threads;
- GetThreadsWaitingOnAddress(waiting_threads, address);
+ std::vector<SharedPtr<Thread>> waiting_threads = GetThreadsWaitingOnAddress(address);
WakeThreads(waiting_threads, num_to_wake);
return RESULT_SUCCESS;
@@ -108,12 +111,11 @@ ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 valu
}
// Get threads waiting on the address.
- std::vector<SharedPtr<Thread>> waiting_threads;
- GetThreadsWaitingOnAddress(waiting_threads, address);
+ std::vector<SharedPtr<Thread>> waiting_threads = GetThreadsWaitingOnAddress(address);
// Determine the modified value depending on the waiting count.
s32 updated_value;
- if (waiting_threads.size() == 0) {
+ if (waiting_threads.empty()) {
updated_value = value - 1;
} else if (num_to_wake <= 0 || waiting_threads.size() <= static_cast<u32>(num_to_wake)) {
updated_value = value + 1;
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h
index f20f3dbc0..e3657b8e9 100644
--- a/src/core/hle/kernel/address_arbiter.h
+++ b/src/core/hle/kernel/address_arbiter.h
@@ -4,7 +4,9 @@
#pragma once
-#include "core/hle/result.h"
+#include "common/common_types.h"
+
+union ResultCode;
namespace Kernel {
diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp
index fb2b6f7a3..134e41ebc 100644
--- a/src/core/hle/kernel/client_port.cpp
+++ b/src/core/hle/kernel/client_port.cpp
@@ -2,19 +2,20 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "common/assert.h"
+#include <tuple>
+
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/hle_ipc.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/server_port.h"
#include "core/hle/kernel/server_session.h"
namespace Kernel {
-ClientPort::ClientPort() {}
-ClientPort::~ClientPort() {}
+ClientPort::ClientPort() = default;
+ClientPort::~ClientPort() = default;
ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
// Note: Threads do not wait for the server endpoint to call
@@ -39,4 +40,12 @@ ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
return MakeResult(std::get<SharedPtr<ClientSession>>(sessions));
}
+void ClientPort::ConnectionClosed() {
+ if (active_sessions == 0) {
+ return;
+ }
+
+ --active_sessions;
+}
+
} // namespace Kernel
diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h
index a829aeb6d..b1269ea5c 100644
--- a/src/core/hle/kernel/client_port.h
+++ b/src/core/hle/kernel/client_port.h
@@ -6,7 +6,7 @@
#include <string>
#include "common/common_types.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/result.h"
namespace Kernel {
@@ -37,14 +37,20 @@ public:
*/
ResultVal<SharedPtr<ClientSession>> Connect();
- 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)
+ /**
+ * Signifies that a previously active connection has been closed,
+ * decreasing the total number of active connections to this port.
+ */
+ void ConnectionClosed();
private:
ClientPort();
~ClientPort() override;
+
+ SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
+ u32 max_sessions = 0; ///< Maximum number of simultaneous sessions the port can have
+ u32 active_sessions = 0; ///< Number of currently open sessions to this port
+ std::string name; ///< Name of client port (optional)
};
} // namespace Kernel
diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp
index 72773d8b1..fdffc648d 100644
--- a/src/core/hle/kernel/client_session.cpp
+++ b/src/core/hle/kernel/client_session.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include "common/assert.h"
-
#include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/hle_ipc.h"
diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h
index 2258f95bc..dabd93ed7 100644
--- a/src/core/hle/kernel/client_session.h
+++ b/src/core/hle/kernel/client_session.h
@@ -7,7 +7,7 @@
#include <memory>
#include <string>
#include "common/common_types.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/result.h"
namespace Kernel {
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index 9cae2369f..5623c4b6a 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -3,11 +3,9 @@
// Refer to the license.txt file included.
#include <algorithm>
-#include <map>
-#include <vector>
#include "common/assert.h"
#include "core/hle/kernel/event.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/thread.h"
namespace Kernel {
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h
index e5c924a75..3c20c05e8 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/event.h
@@ -5,7 +5,7 @@
#pragma once
#include "common/common_types.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/wait_object.h"
namespace Kernel {
@@ -31,10 +31,9 @@ public:
return HANDLE_TYPE;
}
- ResetType reset_type; ///< Current ResetType
-
- bool signaled; ///< Whether the event has already been signaled
- std::string name; ///< Name of event (optional)
+ ResetType GetResetType() const {
+ return reset_type;
+ }
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;
@@ -47,6 +46,11 @@ public:
private:
Event();
~Event() override;
+
+ ResetType reset_type; ///< Current ResetType
+
+ bool signaled; ///< Whether the event has already been signaled
+ std::string name; ///< Name of event (optional)
};
} // namespace Kernel
diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp
index 7dd67f80f..28e21428a 100644
--- a/src/core/hle/kernel/handle_table.cpp
+++ b/src/core/hle/kernel/handle_table.cpp
@@ -8,7 +8,6 @@
#include "core/core.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h"
-#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/thread.h"
diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h
index ba968c666..22ddda630 100644
--- a/src/core/hle/kernel/handle_table.h
+++ b/src/core/hle/kernel/handle_table.h
@@ -7,7 +7,7 @@
#include <array>
#include <cstddef>
#include "common/common_types.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/result.h"
namespace Kernel {
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index f24392520..82a3fb5a8 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -2,17 +2,22 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <algorithm>
+#include <array>
+#include <sstream>
#include <utility>
#include <boost/range/algorithm_ext/erase.hpp>
+
#include "common/assert.h"
#include "common/common_funcs.h"
#include "common/common_types.h"
+#include "common/logging/log.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/hle_ipc.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/server_session.h"
#include "core/memory.h"
@@ -196,7 +201,7 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(u32_le* src_cmdb
return RESULT_SUCCESS;
}
-ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(Thread& thread) {
+ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(const Thread& thread) {
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> dst_cmdbuf;
Memory::ReadBlock(*thread.owner_process, thread.GetTLSAddress(), dst_cmdbuf.data(),
dst_cmdbuf.size() * sizeof(u32));
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index 84727f748..f0d07f1b6 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -5,7 +5,6 @@
#pragma once
#include <array>
-#include <iterator>
#include <memory>
#include <string>
#include <type_traits>
@@ -14,7 +13,7 @@
#include "common/common_types.h"
#include "common/swap.h"
#include "core/hle/ipc.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/server_session.h"
#include "core/hle/kernel/thread.h"
@@ -133,7 +132,7 @@ public:
ResultCode PopulateFromIncomingCommandBuffer(u32_le* src_cmdbuf, Process& src_process,
HandleTable& src_table);
/// Writes data from this context back to the requesting process/thread.
- ResultCode WriteToOutgoingCommandBuffer(Thread& thread);
+ ResultCode WriteToOutgoingCommandBuffer(const Thread& thread);
u32_le GetCommand() const {
return command;
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 1beb98566..8c19e86d3 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -4,8 +4,6 @@
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/memory.h"
-#include "core/hle/kernel/object_address_table.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/thread.h"
@@ -13,12 +11,10 @@
namespace Kernel {
-unsigned int Object::next_object_id;
+std::atomic<u32> Object::next_object_id{0};
/// Initialize the kernel
-void Init(u32 system_mode) {
- Kernel::MemoryInit(system_mode);
-
+void Init() {
Kernel::ResourceLimitsInit();
Kernel::ThreadingInit();
Kernel::TimersInit();
@@ -33,13 +29,11 @@ void Init(u32 system_mode) {
void Shutdown() {
// Free all kernel objects
g_handle_table.Clear();
- g_object_address_table.Clear();
Kernel::ThreadingShutdown();
Kernel::TimersShutdown();
Kernel::ResourceLimitsShutdown();
- Kernel::MemoryShutdown();
}
} // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 402ae900f..131311472 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -4,122 +4,12 @@
#pragma once
-#include <cstddef>
-#include <string>
-#include <utility>
-#include <boost/smart_ptr/intrusive_ptr.hpp>
-#include "common/assert.h"
#include "common/common_types.h"
namespace Kernel {
-using Handle = u32;
-
-enum class HandleType : u32 {
- Unknown,
- Event,
- SharedMemory,
- Thread,
- Process,
- AddressArbiter,
- Timer,
- ResourceLimit,
- CodeSet,
- ClientPort,
- ServerPort,
- ClientSession,
- ServerSession,
-};
-
-enum class ResetType {
- OneShot,
- Sticky,
- Pulse,
-};
-
-class Object : NonCopyable {
-public:
- virtual ~Object() {}
-
- /// Returns a unique identifier for the object. For debugging purposes only.
- unsigned int GetObjectId() const {
- return object_id;
- }
-
- virtual std::string GetTypeName() const {
- return "[BAD KERNEL OBJECT TYPE]";
- }
- virtual std::string GetName() const {
- return "[UNKNOWN KERNEL OBJECT]";
- }
- virtual Kernel::HandleType GetHandleType() const = 0;
-
- /**
- * Check if a thread can wait on the object
- * @return True if a thread can wait on the object, otherwise false
- */
- bool IsWaitable() const {
- switch (GetHandleType()) {
- case HandleType::Event:
- case HandleType::Thread:
- case HandleType::Timer:
- case HandleType::ServerPort:
- case HandleType::ServerSession:
- return true;
-
- case HandleType::Unknown:
- case HandleType::SharedMemory:
- case HandleType::Process:
- case HandleType::AddressArbiter:
- case HandleType::ResourceLimit:
- case HandleType::CodeSet:
- case HandleType::ClientPort:
- case HandleType::ClientSession:
- return false;
- }
-
- UNREACHABLE();
- }
-
-public:
- static unsigned int next_object_id;
-
-private:
- friend void intrusive_ptr_add_ref(Object*);
- friend void intrusive_ptr_release(Object*);
-
- unsigned int ref_count = 0;
- unsigned int object_id = next_object_id++;
-};
-
-// Special functions used by boost::instrusive_ptr to do automatic ref-counting
-inline void intrusive_ptr_add_ref(Object* object) {
- ++object->ref_count;
-}
-
-inline void intrusive_ptr_release(Object* object) {
- if (--object->ref_count == 0) {
- delete object;
- }
-}
-
-template <typename T>
-using SharedPtr = boost::intrusive_ptr<T>;
-
-/**
- * Attempts to downcast the given Object pointer to a pointer to T.
- * @return Derived pointer to the object, or `nullptr` if `object` isn't of type T.
- */
-template <typename T>
-inline SharedPtr<T> DynamicObjectCast(SharedPtr<Object> object) {
- if (object != nullptr && object->GetHandleType() == T::HANDLE_TYPE) {
- return boost::static_pointer_cast<T>(std::move(object));
- }
- return nullptr;
-}
-
/// Initialize the kernel with the specified system mode.
-void Init(u32 system_mode);
+void Init();
/// Shutdown the kernel
void Shutdown();
diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp
deleted file mode 100644
index 94eac677c..000000000
--- a/src/core/hle/kernel/memory.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <algorithm>
-#include <cinttypes>
-#include <map>
-#include <memory>
-#include <utility>
-#include <vector>
-#include "common/assert.h"
-#include "common/common_types.h"
-#include "common/logging/log.h"
-#include "core/hle/kernel/memory.h"
-#include "core/hle/kernel/vm_manager.h"
-#include "core/hle/result.h"
-#include "core/memory.h"
-#include "core/memory_setup.h"
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-namespace Kernel {
-
-MemoryRegionInfo memory_regions[3];
-
-/// Size of the APPLICATION, SYSTEM and BASE memory regions (respectively) for each system
-/// memory configuration type.
-static const u32 memory_region_sizes[8][3] = {
- // Old 3DS layouts
- {0x04000000, 0x02C00000, 0x01400000}, // 0
- {/* This appears to be unused. */}, // 1
- {0x06000000, 0x00C00000, 0x01400000}, // 2
- {0x05000000, 0x01C00000, 0x01400000}, // 3
- {0x04800000, 0x02400000, 0x01400000}, // 4
- {0x02000000, 0x04C00000, 0x01400000}, // 5
-
- // New 3DS layouts
- {0x07C00000, 0x06400000, 0x02000000}, // 6
- {0x0B200000, 0x02E00000, 0x02000000}, // 7
-};
-
-void MemoryInit(u32 mem_type) {
- // TODO(yuriks): On the n3DS, all o3DS configurations (<=5) are forced to 6 instead.
- ASSERT_MSG(mem_type <= 5, "New 3DS memory configuration aren't supported yet!");
- ASSERT(mem_type != 1);
-
- // The kernel allocation regions (APPLICATION, SYSTEM and BASE) are laid out in sequence, with
- // the sizes specified in the memory_region_sizes table.
- VAddr base = 0;
- for (int i = 0; i < 3; ++i) {
- memory_regions[i].base = base;
- memory_regions[i].size = memory_region_sizes[mem_type][i];
- memory_regions[i].used = 0;
- memory_regions[i].linear_heap_memory = std::make_shared<std::vector<u8>>();
- // Reserve enough space for this region of FCRAM.
- // We do not want this block of memory to be relocated when allocating from it.
- memory_regions[i].linear_heap_memory->reserve(memory_regions[i].size);
-
- base += memory_regions[i].size;
- }
-
- // We must've allocated the entire FCRAM by the end
- ASSERT(base == Memory::FCRAM_SIZE);
-}
-
-void MemoryShutdown() {
- for (auto& region : memory_regions) {
- region.base = 0;
- region.size = 0;
- region.used = 0;
- region.linear_heap_memory = nullptr;
- }
-}
-
-MemoryRegionInfo* GetMemoryRegion(MemoryRegion region) {
- switch (region) {
- case MemoryRegion::APPLICATION:
- return &memory_regions[0];
- case MemoryRegion::SYSTEM:
- return &memory_regions[1];
- case MemoryRegion::BASE:
- return &memory_regions[2];
- default:
- UNREACHABLE();
- }
-}
-
-void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) {}
-
-void MapSharedPages(VMManager& address_space) {}
-
-} // namespace Kernel
diff --git a/src/core/hle/kernel/memory.h b/src/core/hle/kernel/memory.h
deleted file mode 100644
index 61e30c679..000000000
--- a/src/core/hle/kernel/memory.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <memory>
-#include "common/common_types.h"
-#include "core/hle/kernel/process.h"
-
-namespace Kernel {
-
-class VMManager;
-
-struct MemoryRegionInfo {
- u64 base; // Not an address, but offset from start of FCRAM
- u64 size;
- u64 used;
-
- std::shared_ptr<std::vector<u8>> linear_heap_memory;
-};
-
-void MemoryInit(u32 mem_type);
-void MemoryShutdown();
-MemoryRegionInfo* GetMemoryRegion(MemoryRegion region);
-
-void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping);
-void MapSharedPages(VMManager& address_space);
-
-extern MemoryRegionInfo memory_regions[3];
-} // namespace Kernel
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index feb7b88d2..cb7f58b35 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -3,16 +3,19 @@
// Refer to the license.txt file included.
#include <map>
+#include <utility>
#include <vector>
+
#include <boost/range/algorithm_ext/erase.hpp>
+
#include "common/assert.h"
#include "core/core.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h"
-#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/mutex.h"
-#include "core/hle/kernel/object_address_table.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/thread.h"
+#include "core/hle/result.h"
namespace Kernel {
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index 3117e7c70..45268bbe9 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -4,12 +4,10 @@
#pragma once
-#include <string>
#include "common/common_types.h"
-#include "common/swap.h"
-#include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/wait_object.h"
-#include "core/hle/result.h"
+#include "core/hle/kernel/object.h"
+
+union ResultCode;
namespace Kernel {
diff --git a/src/core/hle/kernel/object.cpp b/src/core/hle/kernel/object.cpp
new file mode 100644
index 000000000..cdba272f5
--- /dev/null
+++ b/src/core/hle/kernel/object.cpp
@@ -0,0 +1,35 @@
+// Copyright 2018 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/object.h"
+
+namespace Kernel {
+
+Object::~Object() = default;
+
+bool Object::IsWaitable() const {
+ switch (GetHandleType()) {
+ case HandleType::Event:
+ case HandleType::Thread:
+ case HandleType::Timer:
+ case HandleType::ServerPort:
+ case HandleType::ServerSession:
+ return true;
+
+ case HandleType::Unknown:
+ case HandleType::SharedMemory:
+ case HandleType::Process:
+ case HandleType::AddressArbiter:
+ case HandleType::ResourceLimit:
+ case HandleType::CodeSet:
+ case HandleType::ClientPort:
+ case HandleType::ClientSession:
+ return false;
+ }
+
+ UNREACHABLE();
+}
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h
new file mode 100644
index 000000000..526ac9cc3
--- /dev/null
+++ b/src/core/hle/kernel/object.h
@@ -0,0 +1,101 @@
+// Copyright 2018 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <atomic>
+#include <string>
+#include <utility>
+
+#include <boost/smart_ptr/intrusive_ptr.hpp>
+
+#include "common/common_types.h"
+
+namespace Kernel {
+
+using Handle = u32;
+
+enum class HandleType : u32 {
+ Unknown,
+ Event,
+ SharedMemory,
+ Thread,
+ Process,
+ AddressArbiter,
+ Timer,
+ ResourceLimit,
+ CodeSet,
+ ClientPort,
+ ServerPort,
+ ClientSession,
+ ServerSession,
+};
+
+enum class ResetType {
+ OneShot,
+ Sticky,
+ Pulse,
+};
+
+class Object : NonCopyable {
+public:
+ virtual ~Object();
+
+ /// Returns a unique identifier for the object. For debugging purposes only.
+ u32 GetObjectId() const {
+ return object_id.load(std::memory_order_relaxed);
+ }
+
+ virtual std::string GetTypeName() const {
+ return "[BAD KERNEL OBJECT TYPE]";
+ }
+ virtual std::string GetName() const {
+ return "[UNKNOWN KERNEL OBJECT]";
+ }
+ virtual HandleType GetHandleType() const = 0;
+
+ /**
+ * Check if a thread can wait on the object
+ * @return True if a thread can wait on the object, otherwise false
+ */
+ bool IsWaitable() const;
+
+public:
+ static std::atomic<u32> next_object_id;
+
+private:
+ friend void intrusive_ptr_add_ref(Object*);
+ friend void intrusive_ptr_release(Object*);
+
+ std::atomic<u32> ref_count{0};
+ std::atomic<u32> object_id{next_object_id++};
+};
+
+// Special functions used by boost::instrusive_ptr to do automatic ref-counting
+inline void intrusive_ptr_add_ref(Object* object) {
+ object->ref_count.fetch_add(1, std::memory_order_relaxed);
+}
+
+inline void intrusive_ptr_release(Object* object) {
+ if (object->ref_count.fetch_sub(1, std::memory_order_acq_rel) == 1) {
+ delete object;
+ }
+}
+
+template <typename T>
+using SharedPtr = boost::intrusive_ptr<T>;
+
+/**
+ * Attempts to downcast the given Object pointer to a pointer to T.
+ * @return Derived pointer to the object, or `nullptr` if `object` isn't of type T.
+ */
+template <typename T>
+inline SharedPtr<T> DynamicObjectCast(SharedPtr<Object> object) {
+ if (object != nullptr && object->GetHandleType() == T::HANDLE_TYPE) {
+ return boost::static_pointer_cast<T>(std::move(object));
+ }
+ return nullptr;
+}
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/object_address_table.cpp b/src/core/hle/kernel/object_address_table.cpp
deleted file mode 100644
index ca8a833a1..000000000
--- a/src/core/hle/kernel/object_address_table.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2018 yuzu emulator team
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <utility>
-
-#include "common/assert.h"
-#include "core/hle/kernel/object_address_table.h"
-
-namespace Kernel {
-
-ObjectAddressTable g_object_address_table;
-
-void ObjectAddressTable::Insert(VAddr addr, SharedPtr<Object> obj) {
- ASSERT_MSG(objects.find(addr) == objects.end(), "Object already exists with addr=0x{:X}", addr);
- objects[addr] = std::move(obj);
-}
-
-void ObjectAddressTable::Close(VAddr addr) {
- ASSERT_MSG(objects.find(addr) != objects.end(), "Object does not exist with addr=0x{:X}", addr);
- objects.erase(addr);
-}
-
-SharedPtr<Object> ObjectAddressTable::GetGeneric(VAddr addr) const {
- auto iter = objects.find(addr);
- if (iter != objects.end()) {
- return iter->second;
- }
- return {};
-}
-
-void ObjectAddressTable::Clear() {
- objects.clear();
-}
-
-} // namespace Kernel
diff --git a/src/core/hle/kernel/object_address_table.h b/src/core/hle/kernel/object_address_table.h
deleted file mode 100644
index a09004b32..000000000
--- a/src/core/hle/kernel/object_address_table.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2018 yuzu emulator team
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <map>
-#include "common/common_types.h"
-#include "core/hle/kernel/kernel.h"
-
-namespace Kernel {
-
-/**
- * This class is used to keep a table of Kernel objects and their respective addresses in emulated
- * memory. For certain Switch SVCs, Kernel objects are referenced by an address to an object the
- * guest application manages, so we use this table to look these kernel objects up. This is similiar
- * to the HandleTable class.
- */
-class ObjectAddressTable final : NonCopyable {
-public:
- ObjectAddressTable() = default;
-
- /**
- * Inserts an object and address pair into the table.
- */
- void Insert(VAddr addr, SharedPtr<Object> obj);
-
- /**
- * Closes an object by its address, removing it from the table and decreasing the object's
- * ref-count.
- * @return `RESULT_SUCCESS` or one of the following errors:
- * - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
- */
- void Close(VAddr addr);
-
- /**
- * Looks up an object by its address.
- * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid.
- */
- SharedPtr<Object> GetGeneric(VAddr addr) const;
-
- /**
- * Looks up an object by its address while verifying its type.
- * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid or its
- * type differs from the requested one.
- */
- template <class T>
- SharedPtr<T> Get(VAddr addr) const {
- return DynamicObjectCast<T>(GetGeneric(addr));
- }
-
- /// Closes all addresses held in this table.
- void Clear();
-
-private:
- /// Stores the Object referenced by the address
- std::map<VAddr, SharedPtr<Object>> objects;
-};
-
-extern ObjectAddressTable g_object_address_table;
-
-} // namespace Kernel
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 0c0506085..edf34c5a3 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -8,7 +8,6 @@
#include "common/common_funcs.h"
#include "common/logging/log.h"
#include "core/hle/kernel/errors.h"
-#include "core/hle/kernel/memory.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/thread.h"
@@ -125,14 +124,6 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {
std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size,
MemoryState::Mapped)
.Unwrap();
- misc_memory_used += stack_size;
- memory_region->used += stack_size;
-
- // Map special address mappings
- MapSharedPages(vm_manager);
- for (const auto& mapping : address_mappings) {
- HandleSpecialMapping(vm_manager, mapping);
- }
vm_manager.LogLayout();
status = ProcessStatus::Running;
@@ -141,37 +132,19 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {
}
void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) {
- memory_region = GetMemoryRegion(flags.memory_region);
-
- auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions,
- MemoryState memory_state) {
+ const auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions,
+ MemoryState memory_state) {
auto vma = vm_manager
.MapMemoryBlock(segment.addr + base_addr, module_->memory, segment.offset,
segment.size, memory_state)
.Unwrap();
vm_manager.Reprotect(vma, permissions);
- misc_memory_used += segment.size;
- memory_region->used += segment.size;
};
// Map CodeSet segments
- MapSegment(module_->code, VMAPermission::ReadExecute, MemoryState::CodeStatic);
- MapSegment(module_->rodata, VMAPermission::Read, MemoryState::CodeMutable);
- MapSegment(module_->data, VMAPermission::ReadWrite, MemoryState::CodeMutable);
-}
-
-VAddr Process::GetLinearHeapAreaAddress() const {
- // Starting from system version 8.0.0 a new linear heap layout is supported to allow usage of
- // the extra RAM in the n3DS.
- return kernel_version < 0x22C ? Memory::LINEAR_HEAP_VADDR : Memory::NEW_LINEAR_HEAP_VADDR;
-}
-
-VAddr Process::GetLinearHeapBase() const {
- return GetLinearHeapAreaAddress() + memory_region->base;
-}
-
-VAddr Process::GetLinearHeapLimit() const {
- return GetLinearHeapBase() + memory_region->size;
+ MapSegment(module_->CodeSegment(), VMAPermission::ReadExecute, MemoryState::CodeStatic);
+ MapSegment(module_->RODataSegment(), VMAPermission::Read, MemoryState::CodeMutable);
+ MapSegment(module_->DataSegment(), VMAPermission::ReadWrite, MemoryState::CodeMutable);
}
ResultVal<VAddr> Process::HeapAllocate(VAddr target, u64 size, VMAPermission perms) {
@@ -206,7 +179,6 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u64 size, VMAPermission per
vm_manager.Reprotect(vma, perms);
heap_used = size;
- memory_region->used += size;
return MakeResult<VAddr>(heap_end - size);
}
@@ -226,52 +198,6 @@ ResultCode Process::HeapFree(VAddr target, u32 size) {
return result;
heap_used -= size;
- memory_region->used -= size;
-
- return RESULT_SUCCESS;
-}
-
-ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission perms) {
- UNIMPLEMENTED();
- return {};
-}
-
-ResultCode Process::LinearFree(VAddr target, u32 size) {
- auto& linheap_memory = memory_region->linear_heap_memory;
-
- if (target < GetLinearHeapBase() || target + size > GetLinearHeapLimit() ||
- target + size < target) {
-
- return ERR_INVALID_ADDRESS;
- }
-
- if (size == 0) {
- return RESULT_SUCCESS;
- }
-
- VAddr heap_end = GetLinearHeapBase() + (u32)linheap_memory->size();
- if (target + size > heap_end) {
- return ERR_INVALID_ADDRESS_STATE;
- }
-
- ResultCode result = vm_manager.UnmapRange(target, size);
- if (result.IsError())
- return result;
-
- linear_heap_used -= size;
- memory_region->used -= size;
-
- if (target + size == heap_end) {
- // End of linear heap has been freed, so check what's the last allocated block in it and
- // reduce the size.
- auto vma = vm_manager.FindVMA(target);
- ASSERT(vma != vm_manager.vma_map.end());
- ASSERT(vma->second.type == VMAType::Free);
- VAddr new_end = vma->second.base;
- if (new_end >= GetLinearHeapBase()) {
- linheap_memory->resize(new_end - GetLinearHeapBase());
- }
- }
return RESULT_SUCCESS;
}
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 68e77a4d1..992689186 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -4,6 +4,7 @@
#pragma once
+#include <array>
#include <bitset>
#include <cstddef>
#include <memory>
@@ -12,7 +13,7 @@
#include <boost/container/static_vector.hpp>
#include "common/bit_field.h"
#include "common/common_types.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/vm_manager.h"
@@ -53,9 +54,14 @@ union ProcessFlags {
enum class ProcessStatus { Created, Running, Exited };
class ResourceLimit;
-struct MemoryRegionInfo;
struct CodeSet final : public Object {
+ struct Segment {
+ size_t offset = 0;
+ VAddr addr = 0;
+ u32 size = 0;
+ };
+
static SharedPtr<CodeSet> Create(std::string name);
std::string GetTypeName() const override {
@@ -70,24 +76,38 @@ struct CodeSet final : public Object {
return HANDLE_TYPE;
}
- /// Name of the process
- std::string name;
+ Segment& CodeSegment() {
+ return segments[0];
+ }
- std::shared_ptr<std::vector<u8>> memory;
+ const Segment& CodeSegment() const {
+ return segments[0];
+ }
- struct Segment {
- size_t offset = 0;
- VAddr addr = 0;
- u32 size = 0;
- };
+ Segment& RODataSegment() {
+ return segments[1];
+ }
+
+ const Segment& RODataSegment() const {
+ return segments[1];
+ }
+
+ Segment& DataSegment() {
+ return segments[2];
+ }
+
+ const Segment& DataSegment() const {
+ return segments[2];
+ }
- Segment segments[3];
- Segment& code = segments[0];
- Segment& rodata = segments[1];
- Segment& data = segments[2];
+ std::shared_ptr<std::vector<u8>> memory;
+ std::array<Segment, 3> segments;
VAddr entrypoint;
+ /// Name of the process
+ std::string name;
+
private:
CodeSet();
~CodeSet() override;
@@ -163,12 +183,11 @@ public:
// This makes deallocation and reallocation of holes fast and keeps process memory contiguous
// in the emulator address space, allowing Memory::GetPointer to be reasonably safe.
std::shared_ptr<std::vector<u8>> heap_memory;
- // The left/right bounds of the address space covered by heap_memory.
- VAddr heap_start = 0, heap_end = 0;
- u64 heap_used = 0, linear_heap_used = 0, misc_memory_used = 0;
-
- MemoryRegionInfo* memory_region = nullptr;
+ // The left/right bounds of the address space covered by heap_memory.
+ VAddr heap_start = 0;
+ VAddr heap_end = 0;
+ u64 heap_used = 0;
/// The Thread Local Storage area is allocated as processes create threads,
/// each TLS area is 0x200 bytes, so one page (0x1000) is split up in 8 parts, and each part
@@ -179,16 +198,9 @@ public:
std::string name;
- VAddr GetLinearHeapAreaAddress() const;
- VAddr GetLinearHeapBase() const;
- VAddr GetLinearHeapLimit() const;
-
ResultVal<VAddr> HeapAllocate(VAddr target, u64 size, VMAPermission perms);
ResultCode HeapFree(VAddr target, u32 size);
- ResultVal<VAddr> LinearAllocate(VAddr target, u32 size, VMAPermission perms);
- ResultCode LinearFree(VAddr target, u32 size);
-
ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size);
ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size);
diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h
index cc689a27a..0fa141db3 100644
--- a/src/core/hle/kernel/resource_limit.h
+++ b/src/core/hle/kernel/resource_limit.h
@@ -5,7 +5,7 @@
#pragma once
#include "common/common_types.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
namespace Kernel {
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index e307eec98..e770b9103 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -2,8 +2,12 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <algorithm>
#include <utility>
+#include "common/assert.h"
+#include "common/logging/log.h"
+#include "core/arm/arm_interface.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/process.h"
@@ -21,7 +25,7 @@ Scheduler::~Scheduler() {
}
}
-bool Scheduler::HaveReadyThreads() {
+bool Scheduler::HaveReadyThreads() const {
std::lock_guard<std::mutex> lock(scheduler_mutex);
return ready_queue.get_first() != nullptr;
}
diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h
index a3b5fb8ca..6a61ef64e 100644
--- a/src/core/hle/kernel/scheduler.h
+++ b/src/core/hle/kernel/scheduler.h
@@ -8,9 +8,11 @@
#include <vector>
#include "common/common_types.h"
#include "common/thread_queue_list.h"
-#include "core/arm/arm_interface.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/thread.h"
+class ARM_Interface;
+
namespace Kernel {
class Scheduler final {
@@ -19,7 +21,7 @@ public:
~Scheduler();
/// Returns whether there are any threads that are ready to run.
- bool HaveReadyThreads();
+ bool HaveReadyThreads() const;
/// Reschedules to the next available thread (call after current thread is suspended)
void Reschedule();
diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp
index 0b7061403..7b6211fd8 100644
--- a/src/core/hle/kernel/server_port.cpp
+++ b/src/core/hle/kernel/server_port.cpp
@@ -6,7 +6,7 @@
#include "common/assert.h"
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/errors.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/server_port.h"
#include "core/hle/kernel/server_session.h"
#include "core/hle/kernel/thread.h"
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h
index 9ef4ecc35..7f6d6b3eb 100644
--- a/src/core/hle/kernel/server_port.h
+++ b/src/core/hle/kernel/server_port.h
@@ -7,8 +7,9 @@
#include <memory>
#include <string>
#include <tuple>
+#include <vector>
#include "common/common_types.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/wait_object.h"
namespace Kernel {
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp
index 29b163528..51a1ec160 100644
--- a/src/core/hle/kernel/server_session.cpp
+++ b/src/core/hle/kernel/server_session.cpp
@@ -5,6 +5,8 @@
#include <tuple>
#include <utility>
+#include "common/assert.h"
+#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/client_port.h"
@@ -25,7 +27,7 @@ ServerSession::~ServerSession() {
// Decrease the port's connection count.
if (parent->port)
- parent->port->active_sessions--;
+ parent->port->ConnectionClosed();
// TODO(Subv): Wake up all the ClientSession's waiting threads and set
// the SendSyncRequest result to 0xC920181A.
@@ -69,6 +71,14 @@ ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& con
const u32 object_id{context.GetDomainMessageHeader()->object_id};
switch (domain_message_header->command) {
case IPC::DomainMessageHeader::CommandType::SendMessage:
+ if (object_id > domain_request_handlers.size()) {
+ LOG_CRITICAL(IPC,
+ "object_id {} is too big! This probably means a recent service call "
+ "to {} needed to return a new interface!",
+ object_id, name);
+ UNREACHABLE();
+ return RESULT_SUCCESS; // Ignore error if asserts are off
+ }
return domain_request_handlers[object_id - 1]->HandleSyncRequest(context);
case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: {
@@ -142,7 +152,7 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) {
// Handle scenario when ConvertToDomain command was issued, as we must do the conversion at the
// end of the command such that only commands following this one are handled as domains
if (convert_to_domain) {
- ASSERT_MSG(domain_request_handlers.empty(), "already a domain");
+ ASSERT_MSG(IsSession(), "ServerSession is already a domain instance.");
domain_request_handlers = {hle_handler};
convert_to_domain = false;
}
diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h
index 2da807042..1a88e66b9 100644
--- a/src/core/hle/kernel/server_session.h
+++ b/src/core/hle/kernel/server_session.h
@@ -6,12 +6,12 @@
#include <memory>
#include <string>
-#include "common/assert.h"
+#include <vector>
+
#include "common/common_types.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/wait_object.h"
#include "core/hle/result.h"
-#include "core/memory.h"
namespace Kernel {
@@ -97,7 +97,12 @@ public:
/// Returns true if the session has been converted to a domain, otherwise False
bool IsDomain() const {
- return !domain_request_handlers.empty();
+ return !IsSession();
+ }
+
+ /// Returns true if this session has not been converted to a domain, otherwise false.
+ bool IsSession() const {
+ return domain_request_handlers.empty();
}
/// Converts the session to a domain at the end of the current command
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h
index e69b034a7..7a551f5e4 100644
--- a/src/core/hle/kernel/session.h
+++ b/src/core/hle/kernel/session.h
@@ -4,7 +4,7 @@
#pragma once
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
namespace Kernel {
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 4bf11c7e2..21ddc2f7d 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -3,10 +3,11 @@
// Refer to the license.txt file included.
#include <utility>
+
+#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/kernel/errors.h"
-#include "core/hle/kernel/memory.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/memory.h"
@@ -28,35 +29,17 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
shared_memory->other_permissions = other_permissions;
if (address == 0) {
- // We need to allocate a block from the Linear Heap ourselves.
- // We'll manually allocate some memory from the linear heap in the specified region.
- MemoryRegionInfo* memory_region = GetMemoryRegion(region);
- auto& linheap_memory = memory_region->linear_heap_memory;
-
- ASSERT_MSG(linheap_memory->size() + size <= memory_region->size,
- "Not enough space in region to allocate shared memory!");
-
- shared_memory->backing_block = linheap_memory;
- shared_memory->backing_block_offset = linheap_memory->size();
- // Allocate some memory from the end of the linear heap for this region.
- linheap_memory->insert(linheap_memory->end(), size, 0);
- memory_region->used += size;
-
- shared_memory->linear_heap_phys_address =
- Memory::FCRAM_PADDR + memory_region->base +
- static_cast<PAddr>(shared_memory->backing_block_offset);
-
- // Increase the amount of used linear heap memory for the owner process.
- if (shared_memory->owner_process != nullptr) {
- shared_memory->owner_process->linear_heap_used += size;
- }
+ shared_memory->backing_block = std::make_shared<std::vector<u8>>(size);
+ shared_memory->backing_block_offset = 0;
// Refresh the address mappings for the current process.
if (Core::CurrentProcess() != nullptr) {
- Core::CurrentProcess()->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get());
+ Core::CurrentProcess()->vm_manager.RefreshMemoryBlockMappings(
+ shared_memory->backing_block.get());
}
} else {
auto& vm_manager = shared_memory->owner_process->vm_manager;
+
// The memory is already available and mapped in the owner process.
auto vma = vm_manager.FindVMA(address);
ASSERT_MSG(vma != vm_manager.vma_map.end(), "Invalid memory address");
@@ -72,6 +55,7 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
}
shared_memory->base_address = address;
+
return shared_memory;
}
@@ -122,11 +106,6 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
VAddr target_address = address;
- if (base_address == 0 && target_address == 0) {
- // Calculate the address at which to map the memory block.
- target_address = Memory::PhysicalToVirtualAddress(linear_heap_phys_address).value();
- }
-
// Map the memory block into the target process
auto result = target_process->vm_manager.MapMemoryBlock(
target_address, backing_block, backing_block_offset, size, MemoryState::Shared);
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index 86f818e90..c50fee615 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -4,9 +4,12 @@
#pragma once
+#include <memory>
#include <string>
+#include <vector>
+
#include "common/common_types.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/process.h"
#include "core/hle/result.h"
@@ -108,9 +111,6 @@ public:
SharedPtr<Process> owner_process;
/// Address of shared memory block in the owner process if specified.
VAddr base_address;
- /// Physical address of the shared memory block in the linear heap if no address was specified
- /// during creation.
- PAddr linear_heap_phys_address;
/// Backing memory for this shared memory block.
std::shared_ptr<std::vector<u8>> backing_block;
/// Offset into the backing block for this shared memory.
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 0b439401a..6be5c474e 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -5,7 +5,10 @@
#include <algorithm>
#include <cinttypes>
#include <iterator>
+#include <mutex>
+#include <vector>
+#include "common/assert.h"
#include "common/logging/log.h"
#include "common/microprofile.h"
#include "common/string_util.h"
@@ -17,7 +20,6 @@
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/mutex.h"
-#include "core/hle/kernel/object_address_table.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/shared_memory.h"
@@ -248,8 +250,11 @@ static ResultCode ArbitrateUnlock(VAddr mutex_addr) {
}
/// Break program execution
-static void Break(u64 unk_0, u64 unk_1, u64 unk_2) {
- LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!");
+static void Break(u64 reason, u64 info1, u64 info2) {
+ LOG_CRITICAL(
+ Debug_Emulated,
+ "Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}",
+ reason, info1, info2);
ASSERT(false);
}
@@ -265,7 +270,7 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id,
info_sub_id, handle);
- auto& vm_manager = Core::CurrentProcess()->vm_manager;
+ const auto& vm_manager = Core::CurrentProcess()->vm_manager;
switch (static_cast<GetInfoType>(info_id)) {
case GetInfoType::AllowedCpuIdBitmask:
@@ -530,7 +535,6 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
CASCADE_RESULT(thread->guest_handle, g_handle_table.Create(thread));
*out_handle = thread->guest_handle;
- Core::System::GetInstance().PrepareReschedule();
Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule();
LOG_TRACE(Kernel_SVC,
@@ -704,8 +708,7 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
auto owner = g_handle_table.Get<Thread>(owner_handle);
ASSERT(owner);
- ASSERT(thread->status != ThreadStatus::Running);
- thread->status = ThreadStatus::WaitMutex;
+ ASSERT(thread->status == ThreadStatus::WaitMutex);
thread->wakeup_callback = nullptr;
owner->AddMutexWaiter(thread);
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 94735c86e..cf4f94822 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -4,8 +4,11 @@
#include <algorithm>
#include <cinttypes>
-#include <list>
#include <vector>
+
+#include <boost/optional.hpp>
+#include <boost/range/algorithm_ext/erase.hpp>
+
#include "common/assert.h"
#include "common/common_types.h"
#include "common/logging/log.h"
@@ -17,11 +20,10 @@
#include "core/core_timing_util.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h"
-#include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/memory.h"
-#include "core/hle/kernel/mutex.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/thread.h"
+#include "core/hle/lock.h"
#include "core/hle/result.h"
#include "core/memory.h"
@@ -79,8 +81,8 @@ void Thread::Stop() {
wait_objects.clear();
// Mark the TLS slot in the thread's page as free.
- u64 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE;
- u64 tls_slot =
+ const u64 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE;
+ const u64 tls_slot =
((tls_address - Memory::TLS_AREA_VADDR) % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE;
Core::CurrentProcess()->tls_slots[tls_page].reset(tls_slot);
}
@@ -103,6 +105,10 @@ void ExitCurrentThread() {
*/
static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
const auto proper_handle = static_cast<Handle>(thread_handle);
+
+ // Lock the global kernel mutex when we enter the kernel HLE.
+ std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock);
+
SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>(proper_handle);
if (thread == nullptr) {
LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle);
@@ -154,12 +160,14 @@ void Thread::WakeAfterDelay(s64 nanoseconds) {
if (nanoseconds == -1)
return;
- CoreTiming::ScheduleEvent(CoreTiming::nsToCycles(nanoseconds), ThreadWakeupEventType,
- callback_handle);
+ // This function might be called from any thread so we have to be cautious and use the
+ // thread-safe version of ScheduleEvent.
+ CoreTiming::ScheduleEventThreadsafe(CoreTiming::nsToCycles(nanoseconds), ThreadWakeupEventType,
+ callback_handle);
}
void Thread::CancelWakeupTimer() {
- CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle);
+ CoreTiming::UnscheduleEventThreadsafe(ThreadWakeupEventType, callback_handle);
}
static boost::optional<s32> GetNextProcessorId(u64 mask) {
@@ -250,13 +258,14 @@ void Thread::ResumeFromWait() {
* slot: The index of the first free slot in the indicated page.
* alloc_needed: Whether there's a need to allocate a new TLS page (All pages are full).
*/
-std::tuple<u32, u32, bool> GetFreeThreadLocalSlot(std::vector<std::bitset<8>>& tls_slots) {
+static std::tuple<std::size_t, std::size_t, bool> GetFreeThreadLocalSlot(
+ const std::vector<std::bitset<8>>& tls_slots) {
// Iterate over all the allocated pages, and try to find one where not all slots are used.
- for (unsigned page = 0; page < tls_slots.size(); ++page) {
+ for (std::size_t page = 0; page < tls_slots.size(); ++page) {
const auto& page_tls_slots = tls_slots[page];
if (!page_tls_slots.all()) {
// We found a page with at least one free slot, find which slot it is
- for (unsigned slot = 0; slot < page_tls_slots.size(); ++slot) {
+ for (std::size_t slot = 0; slot < page_tls_slots.size(); ++slot) {
if (!page_tls_slots.test(slot)) {
return std::make_tuple(page, slot, false);
}
@@ -331,42 +340,22 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
// Find the next available TLS index, and mark it as used
auto& tls_slots = owner_process->tls_slots;
- bool needs_allocation = true;
- u32 available_page; // Which allocated page has free space
- u32 available_slot; // Which slot within the page is free
-
- std::tie(available_page, available_slot, needs_allocation) = GetFreeThreadLocalSlot(tls_slots);
+ auto [available_page, available_slot, needs_allocation] = GetFreeThreadLocalSlot(tls_slots);
if (needs_allocation) {
- // There are no already-allocated pages with free slots, lets allocate a new one.
- // TLS pages are allocated from the BASE region in the linear heap.
- MemoryRegionInfo* memory_region = GetMemoryRegion(MemoryRegion::BASE);
- auto& linheap_memory = memory_region->linear_heap_memory;
-
- if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) {
- LOG_ERROR(Kernel_SVC,
- "Not enough space in region to allocate a new TLS page for thread");
- return ERR_OUT_OF_MEMORY;
- }
-
- size_t offset = linheap_memory->size();
-
- // Allocate some memory from the end of the linear heap for this region.
- linheap_memory->insert(linheap_memory->end(), Memory::PAGE_SIZE, 0);
- memory_region->used += Memory::PAGE_SIZE;
- owner_process->linear_heap_used += Memory::PAGE_SIZE;
-
tls_slots.emplace_back(0); // The page is completely available at the start
- available_page = static_cast<u32>(tls_slots.size() - 1);
+ available_page = tls_slots.size() - 1;
available_slot = 0; // Use the first slot in the new page
+ // Allocate some memory from the end of the linear heap for this region.
+ const size_t offset = thread->tls_memory->size();
+ thread->tls_memory->insert(thread->tls_memory->end(), Memory::PAGE_SIZE, 0);
+
auto& vm_manager = owner_process->vm_manager;
- vm_manager.RefreshMemoryBlockMappings(linheap_memory.get());
+ vm_manager.RefreshMemoryBlockMappings(thread->tls_memory.get());
- // Map the page to the current process' address space.
- // TODO(Subv): Find the correct MemoryState for this region.
vm_manager.MapMemoryBlock(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE,
- linheap_memory, offset, Memory::PAGE_SIZE,
+ thread->tls_memory, 0, Memory::PAGE_SIZE,
MemoryState::ThreadLocal);
}
@@ -437,12 +426,33 @@ VAddr Thread::GetCommandBufferAddress() const {
}
void Thread::AddMutexWaiter(SharedPtr<Thread> thread) {
+ if (thread->lock_owner == this) {
+ // If the thread is already waiting for this thread to release the mutex, ensure that the
+ // waiters list is consistent and return without doing anything.
+ auto itr = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread);
+ ASSERT(itr != wait_mutex_threads.end());
+ return;
+ }
+
+ // A thread can't wait on two different mutexes at the same time.
+ ASSERT(thread->lock_owner == nullptr);
+
+ // Ensure that the thread is not already in the list of mutex waiters
+ auto itr = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread);
+ ASSERT(itr == wait_mutex_threads.end());
+
thread->lock_owner = this;
wait_mutex_threads.emplace_back(std::move(thread));
UpdatePriority();
}
void Thread::RemoveMutexWaiter(SharedPtr<Thread> thread) {
+ ASSERT(thread->lock_owner == this);
+
+ // Ensure that the thread is in the list of mutex waiters
+ auto itr = std::find(wait_mutex_threads.begin(), wait_mutex_threads.end(), thread);
+ ASSERT(itr != wait_mutex_threads.end());
+
boost::remove_erase(wait_mutex_threads, thread);
thread->lock_owner = nullptr;
UpdatePriority();
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 6218960d2..adc804248 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -4,15 +4,14 @@
#pragma once
+#include <functional>
#include <memory>
#include <string>
-#include <unordered_map>
#include <vector>
-#include <boost/container/flat_map.hpp>
-#include <boost/container/flat_set.hpp>
+
#include "common/common_types.h"
#include "core/arm/arm_interface.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/wait_object.h"
#include "core/hle/result.h"
@@ -266,6 +265,8 @@ public:
private:
Thread();
~Thread() override;
+
+ std::shared_ptr<std::vector<u8>> tls_memory = std::make_shared<std::vector<u8>>();
};
/**
@@ -289,12 +290,6 @@ Thread* GetCurrentThread();
void WaitCurrentThread_Sleep();
/**
- * Waits the current thread from an ArbitrateAddress call
- * @param wait_address Arbitration address used to resume from wait
- */
-void WaitCurrentThread_ArbitrateAddress(VAddr wait_address);
-
-/**
* Stops the current thread and removes it from the thread_list
*/
void ExitCurrentThread();
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index 904a3d0a5..282360745 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -8,7 +8,7 @@
#include "core/core_timing.h"
#include "core/core_timing_util.h"
#include "core/hle/kernel/handle_table.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/timer.h"
diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h
index 82d19cefc..4dddc67e0 100644
--- a/src/core/hle/kernel/timer.h
+++ b/src/core/hle/kernel/timer.h
@@ -5,7 +5,7 @@
#pragma once
#include "common/common_types.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/wait_object.h"
namespace Kernel {
@@ -32,13 +32,17 @@ public:
return HANDLE_TYPE;
}
- ResetType reset_type; ///< The ResetType of this timer
+ ResetType GetResetType() const {
+ return reset_type;
+ }
- bool signaled; ///< Whether the timer has been signaled or not
- std::string name; ///< Name of timer (optional)
+ u64 GetInitialDelay() const {
+ return initial_delay;
+ }
- u64 initial_delay; ///< The delay until the timer fires for the first time
- u64 interval_delay; ///< The delay until the timer fires after the first time
+ u64 GetIntervalDelay() const {
+ return interval_delay;
+ }
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;
@@ -67,6 +71,14 @@ private:
Timer();
~Timer() override;
+ ResetType reset_type; ///< The ResetType of this timer
+
+ u64 initial_delay; ///< The delay until the timer fires for the first time
+ u64 interval_delay; ///< The delay until the timer fires after the first time
+
+ bool signaled; ///< Whether the timer has been signaled or not
+ std::string name; ///< Name of timer (optional)
+
/// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
Handle callback_handle;
};
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index 9d26fd781..479cacb62 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <algorithm>
#include <iterator>
#include <utility>
#include "common/assert.h"
@@ -175,9 +176,9 @@ VMManager::VMAIter VMManager::Unmap(VMAIter vma_handle) {
ResultCode VMManager::UnmapRange(VAddr target, u64 size) {
CASCADE_RESULT(VMAIter vma, CarveVMARange(target, size));
- VAddr target_end = target + size;
+ const VAddr target_end = target + size;
- VMAIter end = vma_map.end();
+ const VMAIter end = vma_map.end();
// The comparison against the end of the range must be done using addresses since VMAs can be
// merged during this process, causing invalidation of the iterators.
while (vma != end && vma->second.base < target_end) {
@@ -207,9 +208,9 @@ VMManager::VMAHandle VMManager::Reprotect(VMAHandle vma_handle, VMAPermission ne
ResultCode VMManager::ReprotectRange(VAddr target, u64 size, VMAPermission new_perms) {
CASCADE_RESULT(VMAIter vma, CarveVMARange(target, size));
- VAddr target_end = target + size;
+ const VAddr target_end = target + size;
- VMAIter end = vma_map.end();
+ const VMAIter end = vma_map.end();
// The comparison against the end of the range must be done using addresses since VMAs can be
// merged during this process, causing invalidation of the iterators.
while (vma != end && vma->second.base < target_end) {
@@ -258,14 +259,14 @@ ResultVal<VMManager::VMAIter> VMManager::CarveVMA(VAddr base, u64 size) {
return ERR_INVALID_ADDRESS;
}
- VirtualMemoryArea& vma = vma_handle->second;
+ const VirtualMemoryArea& vma = vma_handle->second;
if (vma.type != VMAType::Free) {
// Region is already allocated
return ERR_INVALID_ADDRESS_STATE;
}
- u64 start_in_vma = base - vma.base;
- u64 end_in_vma = start_in_vma + size;
+ const VAddr start_in_vma = base - vma.base;
+ const VAddr end_in_vma = start_in_vma + size;
if (end_in_vma > vma.size) {
// Requested allocation doesn't fit inside VMA
@@ -288,17 +289,16 @@ ResultVal<VMManager::VMAIter> VMManager::CarveVMARange(VAddr target, u64 size) {
ASSERT_MSG((size & Memory::PAGE_MASK) == 0, "non-page aligned size: 0x{:016X}", size);
ASSERT_MSG((target & Memory::PAGE_MASK) == 0, "non-page aligned base: 0x{:016X}", target);
- VAddr target_end = target + size;
+ const VAddr target_end = target + size;
ASSERT(target_end >= target);
ASSERT(target_end <= MAX_ADDRESS);
ASSERT(size > 0);
VMAIter begin_vma = StripIterConstness(FindVMA(target));
- VMAIter i_end = vma_map.lower_bound(target_end);
- for (auto i = begin_vma; i != i_end; ++i) {
- if (i->second.type == VMAType::Free) {
- return ERR_INVALID_ADDRESS_STATE;
- }
+ const VMAIter i_end = vma_map.lower_bound(target_end);
+ if (std::any_of(begin_vma, i_end,
+ [](const auto& entry) { return entry.second.type == VMAType::Free; })) {
+ return ERR_INVALID_ADDRESS_STATE;
}
if (target != begin_vma->second.base) {
@@ -346,7 +346,7 @@ VMManager::VMAIter VMManager::SplitVMA(VMAIter vma_handle, u64 offset_in_vma) {
}
VMManager::VMAIter VMManager::MergeAdjacent(VMAIter iter) {
- VMAIter next_vma = std::next(iter);
+ const VMAIter next_vma = std::next(iter);
if (next_vma != vma_map.end() && iter->second.CanBeMergedWith(next_vma->second)) {
iter->second.size += next_vma->second.size;
vma_map.erase(next_vma);
@@ -382,22 +382,22 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
}
}
-u64 VMManager::GetTotalMemoryUsage() {
+u64 VMManager::GetTotalMemoryUsage() const {
LOG_WARNING(Kernel, "(STUBBED) called");
return 0xF8000000;
}
-u64 VMManager::GetTotalHeapUsage() {
+u64 VMManager::GetTotalHeapUsage() const {
LOG_WARNING(Kernel, "(STUBBED) called");
return 0x0;
}
-VAddr VMManager::GetAddressSpaceBaseAddr() {
+VAddr VMManager::GetAddressSpaceBaseAddr() const {
LOG_WARNING(Kernel, "(STUBBED) called");
return 0x8000000;
}
-u64 VMManager::GetAddressSpaceSize() {
+u64 VMManager::GetAddressSpaceSize() const {
LOG_WARNING(Kernel, "(STUBBED) called");
return MAX_ADDRESS;
}
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index 38e4ebcd3..98bd04bea 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -190,16 +190,16 @@ public:
void LogLayout() const;
/// Gets the total memory usage, used by svcGetInfo
- u64 GetTotalMemoryUsage();
+ u64 GetTotalMemoryUsage() const;
/// Gets the total heap usage, used by svcGetInfo
- u64 GetTotalHeapUsage();
+ u64 GetTotalHeapUsage() const;
/// Gets the total address space base address, used by svcGetInfo
- VAddr GetAddressSpaceBaseAddr();
+ VAddr GetAddressSpaceBaseAddr() const;
/// Gets the total address space address size, used by svcGetInfo
- u64 GetAddressSpaceSize();
+ u64 GetAddressSpaceSize() const;
/// Each VMManager has its own page table, which is set as the main one when the owning process
/// is scheduled.
diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp
index 23af346d0..7681cdee7 100644
--- a/src/core/hle/kernel/wait_object.cpp
+++ b/src/core/hle/kernel/wait_object.cpp
@@ -5,11 +5,8 @@
#include <algorithm>
#include "common/assert.h"
#include "common/logging/log.h"
-#include "core/hle/kernel/errors.h"
-#include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/memory.h"
+#include "core/hle/kernel/object.h"
#include "core/hle/kernel/process.h"
-#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/timer.h"
diff --git a/src/core/hle/kernel/wait_object.h b/src/core/hle/kernel/wait_object.h
index 78bfd8c6c..b5fbc647b 100644
--- a/src/core/hle/kernel/wait_object.h
+++ b/src/core/hle/kernel/wait_object.h
@@ -7,7 +7,7 @@
#include <vector>
#include <boost/smart_ptr/intrusive_ptr.hpp>
#include "common/common_types.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
namespace Kernel {
diff --git a/src/core/hle/romfs.cpp b/src/core/hle/romfs.cpp
deleted file mode 100644
index 3157df71d..000000000
--- a/src/core/hle/romfs.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2017 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#include <cstring>
-#include "common/swap.h"
-#include "core/hle/romfs.h"
-
-namespace RomFS {
-
-struct Header {
- u32_le header_length;
- u32_le dir_hash_table_offset;
- u32_le dir_hash_table_length;
- u32_le dir_table_offset;
- u32_le dir_table_length;
- u32_le file_hash_table_offset;
- u32_le file_hash_table_length;
- u32_le file_table_offset;
- u32_le file_table_length;
- u32_le data_offset;
-};
-
-static_assert(sizeof(Header) == 0x28, "Header has incorrect size");
-
-struct DirectoryMetadata {
- u32_le parent_dir_offset;
- u32_le next_dir_offset;
- u32_le first_child_dir_offset;
- u32_le first_file_offset;
- u32_le same_hash_next_dir_offset;
- u32_le name_length; // in bytes
- // followed by directory name
-};
-
-static_assert(sizeof(DirectoryMetadata) == 0x18, "DirectoryMetadata has incorrect size");
-
-struct FileMetadata {
- u32_le parent_dir_offset;
- u32_le next_file_offset;
- u64_le data_offset;
- u64_le data_length;
- u32_le same_hash_next_file_offset;
- u32_le name_length; // in bytes
- // followed by file name
-};
-
-static_assert(sizeof(FileMetadata) == 0x20, "FileMetadata has incorrect size");
-
-static bool MatchName(const u8* buffer, u32 name_length, const std::u16string& name) {
- std::vector<char16_t> name_buffer(name_length / sizeof(char16_t));
- std::memcpy(name_buffer.data(), buffer, name_length);
- return name == std::u16string(name_buffer.begin(), name_buffer.end());
-}
-
-const u8* GetFilePointer(const u8* romfs, const std::vector<std::u16string>& path) {
- constexpr u32 INVALID_FIELD = 0xFFFFFFFF;
-
- // Split path into directory names and file name
- std::vector<std::u16string> dir_names = path;
- dir_names.pop_back();
- const std::u16string& file_name = path.back();
-
- Header header;
- std::memcpy(&header, romfs, sizeof(header));
-
- // Find directories of each level
- DirectoryMetadata dir;
- const u8* current_dir = romfs + header.dir_table_offset;
- std::memcpy(&dir, current_dir, sizeof(dir));
- for (const std::u16string& dir_name : dir_names) {
- u32 child_dir_offset;
- child_dir_offset = dir.first_child_dir_offset;
- while (true) {
- if (child_dir_offset == INVALID_FIELD) {
- return nullptr;
- }
- const u8* current_child_dir = romfs + header.dir_table_offset + child_dir_offset;
- std::memcpy(&dir, current_child_dir, sizeof(dir));
- if (MatchName(current_child_dir + sizeof(dir), dir.name_length, dir_name)) {
- current_dir = current_child_dir;
- break;
- }
- child_dir_offset = dir.next_dir_offset;
- }
- }
-
- // Find the file
- FileMetadata file;
- u32 file_offset = dir.first_file_offset;
- while (file_offset != INVALID_FIELD) {
- const u8* current_file = romfs + header.file_table_offset + file_offset;
- std::memcpy(&file, current_file, sizeof(file));
- if (MatchName(current_file + sizeof(file), file.name_length, file_name)) {
- return romfs + header.data_offset + file.data_offset;
- }
- file_offset = file.next_file_offset;
- }
- return nullptr;
-}
-
-} // namespace RomFS
diff --git a/src/core/hle/romfs.h b/src/core/hle/romfs.h
deleted file mode 100644
index ee9f29760..000000000
--- a/src/core/hle/romfs.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2017 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
-
-#pragma once
-
-#include <string>
-#include <vector>
-#include "common/common_types.h"
-
-namespace RomFS {
-
-/**
- * Gets the pointer to a file in a RomFS image.
- * @param romfs The pointer to the RomFS image
- * @param path A vector containing the directory names and file name of the path to the file
- * @return the pointer to the file
- * @todo reimplement this with a full RomFS manager
- */
-const u8* GetFilePointer(const u8* romfs, const std::vector<std::u16string>& path);
-
-} // namespace RomFS
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp
index 0b158e015..f3c5b1b9c 100644
--- a/src/core/hle/service/acc/acc.cpp
+++ b/src/core/hle/service/acc/acc.cpp
@@ -10,6 +10,7 @@
#include "core/hle/service/acc/acc_su.h"
#include "core/hle/service/acc/acc_u0.h"
#include "core/hle/service/acc/acc_u1.h"
+#include "core/settings.h"
namespace Service::Account {
@@ -31,34 +32,78 @@ struct ProfileBase {
};
static_assert(sizeof(ProfileBase) == 0x38, "ProfileBase structure has incorrect size");
+// TODO(ogniK): Generate a real user id based on username, md5(username) maybe?
static constexpr u128 DEFAULT_USER_ID{1ull, 0ull};
class IProfile final : public ServiceFramework<IProfile> {
public:
explicit IProfile(u128 user_id) : ServiceFramework("IProfile"), user_id(user_id) {
static const FunctionInfo functions[] = {
- {0, nullptr, "Get"},
+ {0, &IProfile::Get, "Get"},
{1, &IProfile::GetBase, "GetBase"},
{10, nullptr, "GetImageSize"},
- {11, nullptr, "LoadImage"},
+ {11, &IProfile::LoadImage, "LoadImage"},
};
RegisterHandlers(functions);
}
private:
+ void Get(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_ACC, "(STUBBED) called");
+ ProfileBase profile_base{};
+ profile_base.user_id = user_id;
+ if (Settings::values.username.size() > profile_base.username.size()) {
+ std::copy_n(Settings::values.username.begin(), profile_base.username.size(),
+ profile_base.username.begin());
+ } else {
+ std::copy(Settings::values.username.begin(), Settings::values.username.end(),
+ profile_base.username.begin());
+ }
+
+ IPC::ResponseBuilder rb{ctx, 16};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushRaw(profile_base);
+ }
+
void GetBase(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
// TODO(Subv): Retrieve this information from somewhere.
ProfileBase profile_base{};
profile_base.user_id = user_id;
- profile_base.username = {'y', 'u', 'z', 'u'};
-
+ if (Settings::values.username.size() > profile_base.username.size()) {
+ std::copy_n(Settings::values.username.begin(), profile_base.username.size(),
+ profile_base.username.begin());
+ } else {
+ std::copy(Settings::values.username.begin(), Settings::values.username.end(),
+ profile_base.username.begin());
+ }
IPC::ResponseBuilder rb{ctx, 16};
rb.Push(RESULT_SUCCESS);
rb.PushRaw(profile_base);
}
+ void LoadImage(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_ACC, "(STUBBED) called");
+ // smallest jpeg https://github.com/mathiasbynens/small/blob/master/jpeg.jpg
+ // TODO(mailwl): load actual profile image from disk, width 256px, max size 0x20000
+ const u32 jpeg_size = 107;
+ static const std::array<u8, jpeg_size> jpeg{
+ 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03,
+ 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x08, 0x06, 0x06, 0x05, 0x06, 0x09, 0x08, 0x0a, 0x0a, 0x09, 0x08, 0x09, 0x09, 0x0a,
+ 0x0c, 0x0f, 0x0c, 0x0a, 0x0b, 0x0e, 0x0b, 0x09, 0x09, 0x0d, 0x11, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x10, 0x11, 0x10, 0x0a, 0x0c, 0x12, 0x13, 0x12, 0x10, 0x13, 0x0f, 0x10, 0x10,
+ 0x10, 0xff, 0xc9, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x11, 0x00,
+ 0xff, 0xcc, 0x00, 0x06, 0x00, 0x10, 0x10, 0x05, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01,
+ 0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9,
+ };
+ ctx.WriteBuffer(jpeg.data(), jpeg_size);
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push<u32>(jpeg_size);
+ }
+
u128 user_id; ///< The user id this profile refers to.
};
@@ -95,6 +140,13 @@ private:
}
};
+void Module::Interface::GetUserCount(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_ACC, "(STUBBED) called");
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push<u32>(1);
+}
+
void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_ACC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h
index 0a01d954c..88cabaa01 100644
--- a/src/core/hle/service/acc/acc.h
+++ b/src/core/hle/service/acc/acc.h
@@ -14,6 +14,7 @@ public:
public:
explicit Interface(std::shared_ptr<Module> module, const char* name);
+ void GetUserCount(Kernel::HLERequestContext& ctx);
void GetUserExistence(Kernel::HLERequestContext& ctx);
void ListAllUsers(Kernel::HLERequestContext& ctx);
void ListOpenUsers(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/acc/acc_su.cpp b/src/core/hle/service/acc/acc_su.cpp
index 9ffb40b22..8b2a71f37 100644
--- a/src/core/hle/service/acc/acc_su.cpp
+++ b/src/core/hle/service/acc/acc_su.cpp
@@ -8,7 +8,7 @@ namespace Service::Account {
ACC_SU::ACC_SU(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:su") {
static const FunctionInfo functions[] = {
- {0, nullptr, "GetUserCount"},
+ {0, &ACC_SU::GetUserCount, "GetUserCount"},
{1, &ACC_SU::GetUserExistence, "GetUserExistence"},
{2, &ACC_SU::ListAllUsers, "ListAllUsers"},
{3, &ACC_SU::ListOpenUsers, "ListOpenUsers"},
diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp
index 44e21ac09..d84c8b2e1 100644
--- a/src/core/hle/service/acc/acc_u0.cpp
+++ b/src/core/hle/service/acc/acc_u0.cpp
@@ -8,7 +8,7 @@ namespace Service::Account {
ACC_U0::ACC_U0(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u0") {
static const FunctionInfo functions[] = {
- {0, nullptr, "GetUserCount"},
+ {0, &ACC_U0::GetUserCount, "GetUserCount"},
{1, &ACC_U0::GetUserExistence, "GetUserExistence"},
{2, &ACC_U0::ListAllUsers, "ListAllUsers"},
{3, &ACC_U0::ListOpenUsers, "ListOpenUsers"},
diff --git a/src/core/hle/service/acc/acc_u1.cpp b/src/core/hle/service/acc/acc_u1.cpp
index d101d4e0d..0ceaf06b5 100644
--- a/src/core/hle/service/acc/acc_u1.cpp
+++ b/src/core/hle/service/acc/acc_u1.cpp
@@ -8,7 +8,7 @@ namespace Service::Account {
ACC_U1::ACC_U1(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "acc:u1") {
static const FunctionInfo functions[] = {
- {0, nullptr, "GetUserCount"},
+ {0, &ACC_U1::GetUserCount, "GetUserCount"},
{1, &ACC_U1::GetUserExistence, "GetUserExistence"},
{2, &ACC_U1::ListAllUsers, "ListAllUsers"},
{3, &ACC_U1::ListOpenUsers, "ListOpenUsers"},
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 97ef07bf9..c524e7a48 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -11,6 +11,9 @@
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applet_ae.h"
#include "core/hle/service/am/applet_oe.h"
+#include "core/hle/service/am/idle.h"
+#include "core/hle/service/am/omm.h"
+#include "core/hle/service/am/spsm.h"
#include "core/hle/service/apm/apm.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/nvflinger/nvflinger.h"
@@ -133,7 +136,7 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
{16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"},
{17, nullptr, "SetControllerFirmwareUpdateSection"},
{18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"},
- {19, nullptr, "SetScreenShotImageOrientation"},
+ {19, &ISelfController::SetScreenShotImageOrientation, "SetScreenShotImageOrientation"},
{20, nullptr, "SetDesirableKeyboardLayout"},
{40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
{41, nullptr, "IsSystemBufferSharingEnabled"},
@@ -142,8 +145,8 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
{51, nullptr, "ApproveToDisplay"},
{60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
{61, nullptr, "SetMediaPlaybackState"},
- {62, nullptr, "SetIdleTimeDetectionExtension"},
- {63, nullptr, "GetIdleTimeDetectionExtension"},
+ {62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"},
+ {63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"},
{64, nullptr, "SetInputDetectionSourceSet"},
{65, nullptr, "ReportUserIsActive"},
{66, nullptr, "GetCurrentIlluminance"},
@@ -251,6 +254,13 @@ void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext&
LOG_WARNING(Service_AM, "(STUBBED) called");
}
+void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+}
+
void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx) {
// TODO(Subv): Find out how AM determines the display to use, for now just create the layer
// in the Default display.
@@ -271,6 +281,23 @@ void ISelfController::SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx)
LOG_WARNING(Service_AM, "(STUBBED) called");
}
+void ISelfController::SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ idle_time_detection_extension = rp.Pop<u32>();
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+}
+
+void ISelfController::GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push<u32>(idle_time_detection_extension);
+
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+}
+
ICommonStateGetter::ICommonStateGetter() : ServiceFramework("ICommonStateGetter") {
static const FunctionInfo functions[] = {
{0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
@@ -296,7 +323,8 @@ ICommonStateGetter::ICommonStateGetter() : ServiceFramework("ICommonStateGetter"
{52, nullptr, "SwitchLcdBacklight"},
{55, nullptr, "IsInControllerFirmwareUpdateSection"},
{60, nullptr, "GetDefaultDisplayResolution"},
- {61, nullptr, "GetDefaultDisplayResolutionChangeEvent"},
+ {61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent,
+ "GetDefaultDisplayResolutionChangeEvent"},
{62, nullptr, "GetHdcpAuthenticationState"},
{63, nullptr, "GetHdcpAuthenticationStateChangeEvent"},
};
@@ -331,6 +359,16 @@ void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
}
+void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(Kernel::HLERequestContext& ctx) {
+ event->Signal();
+
+ IPC::ResponseBuilder rb{ctx, 2, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushCopyObjects(event);
+
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+}
+
void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) {
const bool use_docked_mode{Settings::values.use_docked_mode};
IPC::ResponseBuilder rb{ctx, 3};
@@ -649,7 +687,8 @@ void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
// TODO(bunnei): This should be configurable
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
- rb.Push(static_cast<u64>(Service::Set::LanguageCode::EN_US));
+ rb.Push(
+ static_cast<u64>(Service::Set::GetLanguageCodeFromIndex(Settings::values.language_index)));
LOG_DEBUG(Service_AM, "called");
}
@@ -689,6 +728,9 @@ void InstallInterfaces(SM::ServiceManager& service_manager,
std::shared_ptr<NVFlinger::NVFlinger> nvflinger) {
std::make_shared<AppletAE>(nvflinger)->InstallAsService(service_manager);
std::make_shared<AppletOE>(nvflinger)->InstallAsService(service_manager);
+ std::make_shared<IdleSys>()->InstallAsService(service_manager);
+ std::make_shared<OMM>()->InstallAsService(service_manager);
+ std::make_shared<SPSM>()->InstallAsService(service_manager);
}
IHomeMenuFunctions::IHomeMenuFunctions() : ServiceFramework("IHomeMenuFunctions") {
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 8f4f98346..b763aff6f 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -83,12 +83,16 @@ private:
void LockExit(Kernel::HLERequestContext& ctx);
void UnlockExit(Kernel::HLERequestContext& ctx);
void GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx);
+ void SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx);
void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx);
void SetScreenShotPermission(Kernel::HLERequestContext& ctx);
void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx);
+ void SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx);
+ void GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx);
std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
Kernel::SharedPtr<Kernel::Event> launchable_event;
+ u32 idle_time_detection_extension = 0;
};
class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
@@ -109,6 +113,7 @@ private:
void GetEventHandle(Kernel::HLERequestContext& ctx);
void ReceiveMessage(Kernel::HLERequestContext& ctx);
void GetCurrentFocusState(Kernel::HLERequestContext& ctx);
+ void GetDefaultDisplayResolutionChangeEvent(Kernel::HLERequestContext& ctx);
void GetOperationMode(Kernel::HLERequestContext& ctx);
void GetPerformanceMode(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/am/idle.cpp b/src/core/hle/service/am/idle.cpp
new file mode 100644
index 000000000..af46e9494
--- /dev/null
+++ b/src/core/hle/service/am/idle.cpp
@@ -0,0 +1,24 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/am/idle.h"
+
+namespace Service::AM {
+
+IdleSys::IdleSys() : ServiceFramework{"idle:sys"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetAutoPowerDownEvent"},
+ {1, nullptr, "Unknown1"},
+ {2, nullptr, "Unknown2"},
+ {3, nullptr, "Unknown3"},
+ {4, nullptr, "Unknown4"},
+ {5, nullptr, "Unknown5"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/idle.h b/src/core/hle/service/am/idle.h
new file mode 100644
index 000000000..1eb68d2c9
--- /dev/null
+++ b/src/core/hle/service/am/idle.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class IdleSys final : public ServiceFramework<IdleSys> {
+public:
+ explicit IdleSys();
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/omm.cpp b/src/core/hle/service/am/omm.cpp
new file mode 100644
index 000000000..447fe8669
--- /dev/null
+++ b/src/core/hle/service/am/omm.cpp
@@ -0,0 +1,42 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/am/omm.h"
+
+namespace Service::AM {
+
+OMM::OMM() : ServiceFramework{"omm"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetOperationMode"},
+ {1, nullptr, "GetOperationModeChangeEvent"},
+ {2, nullptr, "EnableAudioVisual"},
+ {3, nullptr, "DisableAudioVisual"},
+ {4, nullptr, "EnterSleepAndWait"},
+ {5, nullptr, "GetCradleStatus"},
+ {6, nullptr, "FadeInDisplay"},
+ {7, nullptr, "FadeOutDisplay"},
+ {8, nullptr, "Unknown1"},
+ {9, nullptr, "Unknown2"},
+ {10, nullptr, "Unknown3"},
+ {11, nullptr, "Unknown4"},
+ {12, nullptr, "Unknown5"},
+ {13, nullptr, "Unknown6"},
+ {14, nullptr, "Unknown7"},
+ {15, nullptr, "Unknown8"},
+ {16, nullptr, "Unknown9"},
+ {17, nullptr, "Unknown10"},
+ {18, nullptr, "Unknown11"},
+ {19, nullptr, "Unknown12"},
+ {20, nullptr, "Unknown13"},
+ {21, nullptr, "Unknown14"},
+ {22, nullptr, "Unknown15"},
+ {23, nullptr, "Unknown16"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/omm.h b/src/core/hle/service/am/omm.h
new file mode 100644
index 000000000..49e5d331c
--- /dev/null
+++ b/src/core/hle/service/am/omm.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class OMM final : public ServiceFramework<OMM> {
+public:
+ explicit OMM();
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/spsm.cpp b/src/core/hle/service/am/spsm.cpp
new file mode 100644
index 000000000..a05d433d0
--- /dev/null
+++ b/src/core/hle/service/am/spsm.cpp
@@ -0,0 +1,30 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/am/spsm.h"
+
+namespace Service::AM {
+
+SPSM::SPSM() : ServiceFramework{"spsm"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetState"},
+ {1, nullptr, "SleepSystemAndWaitAwake"},
+ {2, nullptr, "Unknown1"},
+ {3, nullptr, "Unknown2"},
+ {4, nullptr, "GetNotificationMessageEventHandle"},
+ {5, nullptr, "Unknown3"},
+ {6, nullptr, "Unknown4"},
+ {7, nullptr, "Unknown5"},
+ {8, nullptr, "AnalyzePerformanceLogForLastSleepWakeSequence"},
+ {9, nullptr, "ChangeHomeButtonLongPressingTime"},
+ {10, nullptr, "Unknown6"},
+ {11, nullptr, "Unknown7"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/spsm.h b/src/core/hle/service/am/spsm.h
new file mode 100644
index 000000000..57dde62e1
--- /dev/null
+++ b/src/core/hle/service/am/spsm.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class SPSM final : public ServiceFramework<SPSM> {
+public:
+ explicit SPSM();
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/apm/apm.cpp b/src/core/hle/service/apm/apm.cpp
index 7a185c6c8..4109cb7f7 100644
--- a/src/core/hle/service/apm/apm.cpp
+++ b/src/core/hle/service/apm/apm.cpp
@@ -13,6 +13,7 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
auto module_ = std::make_shared<Module>();
std::make_shared<APM>(module_, "apm")->InstallAsService(service_manager);
std::make_shared<APM>(module_, "apm:p")->InstallAsService(service_manager);
+ std::make_shared<APM_Sys>()->InstallAsService(service_manager);
}
} // namespace Service::APM
diff --git a/src/core/hle/service/apm/interface.cpp b/src/core/hle/service/apm/interface.cpp
index ce943d829..4cd8132f5 100644
--- a/src/core/hle/service/apm/interface.cpp
+++ b/src/core/hle/service/apm/interface.cpp
@@ -74,6 +74,31 @@ void APM::OpenSession(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISession>();
+
+ LOG_DEBUG(Service_APM, "called");
+}
+
+APM_Sys::APM_Sys() : ServiceFramework{"apm:sys"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RequestPerformanceMode"},
+ {1, &APM_Sys::GetPerformanceEvent, "GetPerformanceEvent"},
+ {2, nullptr, "GetThrottlingState"},
+ {3, nullptr, "GetLastThrottlingState"},
+ {4, nullptr, "ClearLastThrottlingState"},
+ {5, nullptr, "LoadAndApplySettings"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+void APM_Sys::GetPerformanceEvent(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<ISession>();
+
+ LOG_DEBUG(Service_APM, "called");
}
} // namespace Service::APM
diff --git a/src/core/hle/service/apm/interface.h b/src/core/hle/service/apm/interface.h
index fa68c7d93..d14264ad7 100644
--- a/src/core/hle/service/apm/interface.h
+++ b/src/core/hle/service/apm/interface.h
@@ -19,4 +19,12 @@ private:
std::shared_ptr<Module> apm;
};
+class APM_Sys final : public ServiceFramework<APM_Sys> {
+public:
+ explicit APM_Sys();
+
+private:
+ void GetPerformanceEvent(Kernel::HLERequestContext& ctx);
+};
+
} // namespace Service::APM
diff --git a/src/core/hle/service/arp/arp.cpp b/src/core/hle/service/arp/arp.cpp
new file mode 100644
index 000000000..358ef2576
--- /dev/null
+++ b/src/core/hle/service/arp/arp.cpp
@@ -0,0 +1,75 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "common/logging/log.h"
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/service/arp/arp.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::ARP {
+
+class ARP_R final : public ServiceFramework<ARP_R> {
+public:
+ explicit ARP_R() : ServiceFramework{"arp:r"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetApplicationLaunchProperty"},
+ {1, nullptr, "GetApplicationLaunchPropertyWithApplicationId"},
+ {2, nullptr, "GetApplicationControlProperty"},
+ {3, nullptr, "GetApplicationControlPropertyWithApplicationId"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class IRegistrar final : public ServiceFramework<IRegistrar> {
+public:
+ explicit IRegistrar() : ServiceFramework{"IRegistrar"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Issue"},
+ {1, nullptr, "SetApplicationLaunchProperty"},
+ {2, nullptr, "SetApplicationControlProperty"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class ARP_W final : public ServiceFramework<ARP_W> {
+public:
+ explicit ARP_W() : ServiceFramework{"arp:w"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &ARP_W::AcquireRegistrar, "AcquireRegistrar"},
+ {1, nullptr, "DeleteProperties"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void AcquireRegistrar(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IRegistrar>();
+
+ LOG_DEBUG(Service_ARP, "called");
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<ARP_R>()->InstallAsService(sm);
+ std::make_shared<ARP_W>()->InstallAsService(sm);
+}
+
+} // namespace Service::ARP
diff --git a/src/core/hle/service/arp/arp.h b/src/core/hle/service/arp/arp.h
new file mode 100644
index 000000000..9d100187c
--- /dev/null
+++ b/src/core/hle/service/arp/arp.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::ARP {
+
+/// Registers all ARP services with the specified service manager.
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::ARP
diff --git a/src/core/hle/service/audio/audctl.cpp b/src/core/hle/service/audio/audctl.cpp
new file mode 100644
index 000000000..37c3fdcac
--- /dev/null
+++ b/src/core/hle/service/audio/audctl.cpp
@@ -0,0 +1,45 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/audio/audctl.h"
+
+namespace Service::Audio {
+
+AudCtl::AudCtl() : ServiceFramework{"audctl"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetTargetVolume"},
+ {1, nullptr, "SetTargetVolume"},
+ {2, nullptr, "GetTargetVolumeMin"},
+ {3, nullptr, "GetTargetVolumeMax"},
+ {4, nullptr, "IsTargetMute"},
+ {5, nullptr, "SetTargetMute"},
+ {6, nullptr, "IsTargetConnected"},
+ {7, nullptr, "SetDefaultTarget"},
+ {8, nullptr, "GetDefaultTarget"},
+ {9, nullptr, "GetAudioOutputMode"},
+ {10, nullptr, "SetAudioOutputMode"},
+ {11, nullptr, "SetForceMutePolicy"},
+ {12, nullptr, "GetForceMutePolicy"},
+ {13, nullptr, "GetOutputModeSetting"},
+ {14, nullptr, "SetOutputModeSetting"},
+ {15, nullptr, "SetOutputTarget"},
+ {16, nullptr, "SetInputTargetForceEnabled"},
+ {17, nullptr, "SetHeadphoneOutputLevelMode"},
+ {18, nullptr, "GetHeadphoneOutputLevelMode"},
+ {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"},
+ {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
+ {21, nullptr, "GetAudioOutputTargetForPlayReport"},
+ {22, nullptr, "NotifyHeadphoneVolumeWarningDisplayedEvent"},
+ {23, nullptr, "SetSystemOutputMasterVolume"},
+ {24, nullptr, "GetSystemOutputMasterVolume"},
+ {25, nullptr, "GetAudioVolumeDataForPlayReport"},
+ {26, nullptr, "UpdateHeadphoneSettings"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audctl.h b/src/core/hle/service/audio/audctl.h
new file mode 100644
index 000000000..ed837bdf2
--- /dev/null
+++ b/src/core/hle/service/audio/audctl.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::Audio {
+
+class AudCtl final : public ServiceFramework<AudCtl> {
+public:
+ explicit AudCtl();
+};
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/auddbg.cpp b/src/core/hle/service/audio/auddbg.cpp
new file mode 100644
index 000000000..b08c21a20
--- /dev/null
+++ b/src/core/hle/service/audio/auddbg.cpp
@@ -0,0 +1,20 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/audio/auddbg.h"
+
+namespace Service::Audio {
+
+AudDbg::AudDbg(const char* name) : ServiceFramework{name} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RequestSuspendForDebug"},
+ {1, nullptr, "RequestResumeForDebug"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/auddbg.h b/src/core/hle/service/audio/auddbg.h
new file mode 100644
index 000000000..a2f540b75
--- /dev/null
+++ b/src/core/hle/service/audio/auddbg.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::Audio {
+
+class AudDbg final : public ServiceFramework<AudDbg> {
+public:
+ explicit AudDbg(const char* name);
+};
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audin_a.cpp b/src/core/hle/service/audio/audin_a.cpp
new file mode 100644
index 000000000..a70d5bca4
--- /dev/null
+++ b/src/core/hle/service/audio/audin_a.cpp
@@ -0,0 +1,22 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/audio/audin_a.h"
+
+namespace Service::Audio {
+
+AudInA::AudInA() : ServiceFramework{"audin:a"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RequestSuspendAudioIns"},
+ {1, nullptr, "RequestResumeAudioIns"},
+ {2, nullptr, "GetAudioInsProcessMasterVolume"},
+ {3, nullptr, "SetAudioInsProcessMasterVolume"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audin_a.h b/src/core/hle/service/audio/audin_a.h
new file mode 100644
index 000000000..e4c75510f
--- /dev/null
+++ b/src/core/hle/service/audio/audin_a.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::Audio {
+
+class AudInA final : public ServiceFramework<AudInA> {
+public:
+ explicit AudInA();
+};
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audio.cpp b/src/core/hle/service/audio/audio.cpp
index d231e91e1..6b5e15633 100644
--- a/src/core/hle/service/audio/audio.cpp
+++ b/src/core/hle/service/audio/audio.cpp
@@ -2,10 +2,16 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "core/hle/service/audio/audctl.h"
+#include "core/hle/service/audio/auddbg.h"
+#include "core/hle/service/audio/audin_a.h"
#include "core/hle/service/audio/audin_u.h"
#include "core/hle/service/audio/audio.h"
+#include "core/hle/service/audio/audout_a.h"
#include "core/hle/service/audio/audout_u.h"
+#include "core/hle/service/audio/audrec_a.h"
#include "core/hle/service/audio/audrec_u.h"
+#include "core/hle/service/audio/audren_a.h"
#include "core/hle/service/audio/audren_u.h"
#include "core/hle/service/audio/codecctl.h"
#include "core/hle/service/audio/hwopus.h"
@@ -13,12 +19,22 @@
namespace Service::Audio {
void InstallInterfaces(SM::ServiceManager& service_manager) {
+ std::make_shared<AudCtl>()->InstallAsService(service_manager);
+ std::make_shared<AudOutA>()->InstallAsService(service_manager);
std::make_shared<AudOutU>()->InstallAsService(service_manager);
+ std::make_shared<AudInA>()->InstallAsService(service_manager);
std::make_shared<AudInU>()->InstallAsService(service_manager);
+ std::make_shared<AudRecA>()->InstallAsService(service_manager);
std::make_shared<AudRecU>()->InstallAsService(service_manager);
+ std::make_shared<AudRenA>()->InstallAsService(service_manager);
std::make_shared<AudRenU>()->InstallAsService(service_manager);
std::make_shared<CodecCtl>()->InstallAsService(service_manager);
std::make_shared<HwOpus>()->InstallAsService(service_manager);
+
+ std::make_shared<AudDbg>("audin:d")->InstallAsService(service_manager);
+ std::make_shared<AudDbg>("audout:d")->InstallAsService(service_manager);
+ std::make_shared<AudDbg>("audrec:d")->InstallAsService(service_manager);
+ std::make_shared<AudDbg>("audren:d")->InstallAsService(service_manager);
}
} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audout_a.cpp b/src/core/hle/service/audio/audout_a.cpp
new file mode 100644
index 000000000..bf8d40157
--- /dev/null
+++ b/src/core/hle/service/audio/audout_a.cpp
@@ -0,0 +1,24 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/audio/audout_a.h"
+
+namespace Service::Audio {
+
+AudOutA::AudOutA() : ServiceFramework{"audout:a"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RequestSuspendAudioOuts"},
+ {1, nullptr, "RequestResumeAudioOuts"},
+ {2, nullptr, "GetAudioOutsProcessMasterVolume"},
+ {3, nullptr, "SetAudioOutsProcessMasterVolume"},
+ {4, nullptr, "GetAudioOutsProcessRecordVolume"},
+ {5, nullptr, "SetAudioOutsProcessRecordVolume"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audout_a.h b/src/core/hle/service/audio/audout_a.h
new file mode 100644
index 000000000..91a069152
--- /dev/null
+++ b/src/core/hle/service/audio/audout_a.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::Audio {
+
+class AudOutA final : public ServiceFramework<AudOutA> {
+public:
+ explicit AudOutA();
+};
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index 1dcd84d98..ce709ccf4 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -4,9 +4,10 @@
#include <array>
#include <vector>
+
+#include "audio_core/codec.h"
#include "common/logging/log.h"
-#include "core/core_timing.h"
-#include "core/core_timing_util.h"
+#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/hle_ipc.h"
@@ -14,17 +15,21 @@
namespace Service::Audio {
-/// Switch sample rate frequency
-constexpr u32 sample_rate{48000};
-/// TODO(st4rk): dynamic number of channels, as I think Switch has support
-/// to more audio channels (probably when Docked I guess)
-constexpr u32 audio_channels{2};
-/// TODO(st4rk): find a proper value for the audio_ticks
-constexpr u64 audio_ticks{static_cast<u64>(CoreTiming::BASE_CLOCK_RATE / 500)};
+namespace ErrCodes {
+enum {
+ ErrorUnknown = 2,
+ BufferCountExceeded = 8,
+};
+}
+
+constexpr std::array<char, 10> DefaultDevice{{"DeviceOut"}};
+constexpr int DefaultSampleRate{48000};
class IAudioOut final : public ServiceFramework<IAudioOut> {
public:
- IAudioOut() : ServiceFramework("IAudioOut"), audio_out_state(AudioState::Stopped) {
+ IAudioOut(AudoutParams audio_params, AudioCore::AudioOut& audio_core)
+ : ServiceFramework("IAudioOut"), audio_core(audio_core), audio_params(audio_params) {
+
static const FunctionInfo functions[] = {
{0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},
{1, &IAudioOut::StartAudioOut, "StartAudioOut"},
@@ -32,66 +37,65 @@ public:
{3, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBuffer"},
{4, &IAudioOut::RegisterBufferEvent, "RegisterBufferEvent"},
{5, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBuffer"},
- {6, nullptr, "ContainsAudioOutBuffer"},
+ {6, &IAudioOut::ContainsAudioOutBuffer, "ContainsAudioOutBuffer"},
{7, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBufferAuto"},
{8, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBufferAuto"},
- {9, nullptr, "GetAudioOutBufferCount"},
+ {9, &IAudioOut::GetAudioOutBufferCount, "GetAudioOutBufferCount"},
{10, nullptr, "GetAudioOutPlayedSampleCount"},
{11, nullptr, "FlushAudioOutBuffers"},
};
RegisterHandlers(functions);
// This is the event handle used to check if the audio buffer was released
- buffer_event =
- Kernel::Event::Create(Kernel::ResetType::OneShot, "IAudioOutBufferReleasedEvent");
-
- // Register event callback to update the Audio Buffer
- audio_event = CoreTiming::RegisterEvent(
- "IAudioOut::UpdateAudioBuffersCallback", [this](u64 userdata, int cycles_late) {
- UpdateAudioBuffersCallback();
- CoreTiming::ScheduleEvent(audio_ticks - cycles_late, audio_event);
- });
-
- // Start the audio event
- CoreTiming::ScheduleEvent(audio_ticks, audio_event);
- }
+ buffer_event = Kernel::Event::Create(Kernel::ResetType::Sticky, "IAudioOutBufferReleased");
- ~IAudioOut() {
- CoreTiming::UnscheduleEvent(audio_event, 0);
+ stream = audio_core.OpenStream(audio_params.sample_rate, audio_params.channel_count,
+ "IAudioOut", [=]() { buffer_event->Signal(); });
}
private:
+ struct AudioBuffer {
+ u64_le next;
+ u64_le buffer;
+ u64_le buffer_capacity;
+ u64_le buffer_size;
+ u64_le offset;
+ };
+ static_assert(sizeof(AudioBuffer) == 0x28, "AudioBuffer is an invalid size");
+
void GetAudioOutState(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
- rb.Push(static_cast<u32>(audio_out_state));
+ rb.Push(static_cast<u32>(stream->IsPlaying() ? AudioState::Started : AudioState::Stopped));
}
void StartAudioOut(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_Audio, "(STUBBED) called");
+ LOG_DEBUG(Service_Audio, "called");
- // Start audio
- audio_out_state = AudioState::Started;
+ if (stream->IsPlaying()) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultCode(ErrorModule::Audio, ErrCodes::ErrorUnknown));
+ return;
+ }
+
+ audio_core.StartStream(stream);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void StopAudioOut(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_Audio, "(STUBBED) called");
-
- // Stop audio
- audio_out_state = AudioState::Stopped;
+ LOG_DEBUG(Service_Audio, "called");
- queue_keys.clear();
+ audio_core.StopStream(stream);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void RegisterBufferEvent(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_Audio, "(STUBBED) called");
+ LOG_DEBUG(Service_Audio, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
@@ -99,101 +103,107 @@ private:
}
void AppendAudioOutBufferImpl(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_Audio, "(STUBBED) called");
+ LOG_DEBUG(Service_Audio, "(STUBBED) called {}", ctx.Description());
IPC::RequestParser rp{ctx};
- const u64 key{rp.Pop<u64>()};
- queue_keys.insert(queue_keys.begin(), key);
+ const auto& input_buffer{ctx.ReadBuffer()};
+ ASSERT_MSG(input_buffer.size() == sizeof(AudioBuffer),
+ "AudioBuffer input is an invalid size!");
+ AudioBuffer audio_buffer{};
+ std::memcpy(&audio_buffer, input_buffer.data(), sizeof(AudioBuffer));
+ const u64 tag{rp.Pop<u64>()};
+
+ std::vector<s16> samples(audio_buffer.buffer_size / sizeof(s16));
+ Memory::ReadBlock(audio_buffer.buffer, samples.data(), audio_buffer.buffer_size);
+
+ if (!audio_core.QueueBuffer(stream, tag, std::move(samples))) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultCode(ErrorModule::Audio, ErrCodes::BufferCountExceeded));
+ }
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void GetReleasedAudioOutBufferImpl(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_Audio, "(STUBBED) called");
-
- // TODO(st4rk): This is how libtransistor currently implements the
- // GetReleasedAudioOutBuffer, it should return the key (a VAddr) to the app and this address
- // is used to know which buffer should be filled with data and send again to the service
- // through AppendAudioOutBuffer. Check if this is the proper way to do it.
- u64 key{0};
-
- if (queue_keys.size()) {
- key = queue_keys.back();
- queue_keys.pop_back();
- }
+ LOG_DEBUG(Service_Audio, "called {}", ctx.Description());
+ IPC::RequestParser rp{ctx};
+ const u64 max_count{ctx.GetWriteBufferSize() / sizeof(u64)};
+ const auto released_buffers{audio_core.GetTagsAndReleaseBuffers(stream, max_count)};
- ctx.WriteBuffer(&key, sizeof(u64));
+ std::vector<u64> tags{released_buffers};
+ tags.resize(max_count);
+ ctx.WriteBuffer(tags);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
- // TODO(st4rk): This might be the total of released buffers, needs to be verified on
- // hardware
- rb.Push<u32>(static_cast<u32>(queue_keys.size()));
+ rb.Push<u32>(static_cast<u32>(released_buffers.size()));
}
- void UpdateAudioBuffersCallback() {
- if (audio_out_state != AudioState::Started) {
- return;
- }
-
- if (queue_keys.empty()) {
- return;
- }
+ void ContainsAudioOutBuffer(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Audio, "called");
+ IPC::RequestParser rp{ctx};
+ const u64 tag{rp.Pop<u64>()};
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push(stream->ContainsBuffer(tag));
+ }
- buffer_event->Signal();
+ void GetAudioOutBufferCount(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Audio, "called");
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push(static_cast<u32>(stream->GetQueueSize()));
}
- enum class AudioState : u32 {
- Started,
- Stopped,
- };
+ AudioCore::AudioOut& audio_core;
+ AudioCore::StreamPtr stream;
- /// This is used to trigger the audio event callback that is going to read the samples from the
- /// audio_buffer list and enqueue the samples using the sink (audio_core).
- CoreTiming::EventType* audio_event;
+ AudoutParams audio_params{};
/// This is the evend handle used to check if the audio buffer was released
Kernel::SharedPtr<Kernel::Event> buffer_event;
-
- /// (st4rk): This is just a temporary workaround for the future implementation. Libtransistor
- /// uses the key as an address in the App, so we need to return when the
- /// GetReleasedAudioOutBuffer_1 is called, otherwise we'll run in problems, because
- /// libtransistor uses the key returned as an pointer.
- std::vector<u64> queue_keys;
-
- AudioState audio_out_state;
};
void AudOutU::ListAudioOutsImpl(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_Audio, "(STUBBED) called");
+ LOG_DEBUG(Service_Audio, "called");
IPC::RequestParser rp{ctx};
- constexpr std::array<char, 15> audio_interface{{"AudioInterface"}};
- ctx.WriteBuffer(audio_interface);
+ ctx.WriteBuffer(DefaultDevice);
IPC::ResponseBuilder rb = rp.MakeBuilder(3, 0, 0);
rb.Push(RESULT_SUCCESS);
- // TODO(st4rk): We're currently returning only one audio interface (stringlist size). However,
- // it's highly possible to have more than one interface (despite that libtransistor requires
- // only one).
- rb.Push<u32>(1);
+ rb.Push<u32>(1); // Amount of audio devices
}
void AudOutU::OpenAudioOutImpl(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_Audio, "(STUBBED) called");
+ LOG_DEBUG(Service_Audio, "called");
- if (!audio_out_interface) {
- audio_out_interface = std::make_shared<IAudioOut>();
+ ctx.WriteBuffer(DefaultDevice);
+ IPC::RequestParser rp{ctx};
+ auto params{rp.PopRaw<AudoutParams>()};
+ if (params.channel_count <= 2) {
+ // Mono does not exist for audout
+ params.channel_count = 2;
+ } else {
+ params.channel_count = 6;
}
+ if (!params.sample_rate) {
+ params.sample_rate = DefaultSampleRate;
+ }
+
+ // TODO(bunnei): Support more than one IAudioOut interface. When we add this, ListAudioOutsImpl
+ // will likely need to be updated as well.
+ ASSERT_MSG(!audio_out_interface, "Unimplemented");
+ audio_out_interface = std::make_shared<IAudioOut>(params, *audio_core);
IPC::ResponseBuilder rb{ctx, 6, 0, 1};
rb.Push(RESULT_SUCCESS);
- rb.Push<u32>(sample_rate);
- rb.Push<u32>(audio_channels);
- rb.Push<u32>(static_cast<u32>(PcmFormat::Int16));
- rb.Push<u32>(0); // This field is unknown
+ rb.Push<u32>(DefaultSampleRate);
+ rb.Push<u32>(params.channel_count);
+ rb.Push<u32>(static_cast<u32>(AudioCore::Codec::PcmFormat::Int16));
+ rb.Push<u32>(static_cast<u32>(AudioState::Stopped));
rb.PushIpcInterface<Audio::IAudioOut>(audio_out_interface);
}
@@ -203,6 +213,7 @@ AudOutU::AudOutU() : ServiceFramework("audout:u") {
{2, &AudOutU::ListAudioOutsImpl, "ListAudioOutsAuto"},
{3, &AudOutU::OpenAudioOutImpl, "OpenAudioOutAuto"}};
RegisterHandlers(functions);
+ audio_core = std::make_unique<AudioCore::AudioOut>();
}
} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audout_u.h b/src/core/hle/service/audio/audout_u.h
index 847d86aa6..fd491f65d 100644
--- a/src/core/hle/service/audio/audout_u.h
+++ b/src/core/hle/service/audio/audout_u.h
@@ -4,6 +4,7 @@
#pragma once
+#include "audio_core/audio_out.h"
#include "core/hle/service/service.h"
namespace Kernel {
@@ -12,6 +13,18 @@ class HLERequestContext;
namespace Service::Audio {
+struct AudoutParams {
+ s32_le sample_rate;
+ u16_le channel_count;
+ INSERT_PADDING_BYTES(2);
+};
+static_assert(sizeof(AudoutParams) == 0x8, "AudoutParams is an invalid size");
+
+enum class AudioState : u32 {
+ Started,
+ Stopped,
+};
+
class IAudioOut;
class AudOutU final : public ServiceFramework<AudOutU> {
@@ -21,19 +34,10 @@ public:
private:
std::shared_ptr<IAudioOut> audio_out_interface;
+ std::unique_ptr<AudioCore::AudioOut> audio_core;
void ListAudioOutsImpl(Kernel::HLERequestContext& ctx);
void OpenAudioOutImpl(Kernel::HLERequestContext& ctx);
-
- enum class PcmFormat : u32 {
- Invalid = 0,
- Int8 = 1,
- Int16 = 2,
- Int24 = 3,
- Int32 = 4,
- PcmFloat = 5,
- Adpcm = 6,
- };
};
} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audrec_a.cpp b/src/core/hle/service/audio/audrec_a.cpp
new file mode 100644
index 000000000..016eabf53
--- /dev/null
+++ b/src/core/hle/service/audio/audrec_a.cpp
@@ -0,0 +1,20 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/audio/audrec_a.h"
+
+namespace Service::Audio {
+
+AudRecA::AudRecA() : ServiceFramework{"audrec:a"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RequestSuspendFinalOutputRecorders"},
+ {1, nullptr, "RequestResumeFinalOutputRecorders"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audrec_a.h b/src/core/hle/service/audio/audrec_a.h
new file mode 100644
index 000000000..9685047f2
--- /dev/null
+++ b/src/core/hle/service/audio/audrec_a.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::Audio {
+
+class AudRecA final : public ServiceFramework<AudRecA> {
+public:
+ explicit AudRecA();
+};
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audren_a.cpp b/src/core/hle/service/audio/audren_a.cpp
new file mode 100644
index 000000000..616ff3dc4
--- /dev/null
+++ b/src/core/hle/service/audio/audren_a.cpp
@@ -0,0 +1,26 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/audio/audren_a.h"
+
+namespace Service::Audio {
+
+AudRenA::AudRenA() : ServiceFramework{"audren:a"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RequestSuspendAudioRenderers"},
+ {1, nullptr, "RequestResumeAudioRenderers"},
+ {2, nullptr, "GetAudioRenderersProcessMasterVolume"},
+ {3, nullptr, "SetAudioRenderersProcessMasterVolume"},
+ {4, nullptr, "RegisterAppletResourceUserId"},
+ {5, nullptr, "UnregisterAppletResourceUserId"},
+ {6, nullptr, "GetAudioRenderersProcessRecordVolume"},
+ {7, nullptr, "SetAudioRenderersProcessRecordVolume"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audren_a.h b/src/core/hle/service/audio/audren_a.h
new file mode 100644
index 000000000..5ecf2e184
--- /dev/null
+++ b/src/core/hle/service/audio/audren_a.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::Audio {
+
+class AudRenA final : public ServiceFramework<AudRenA> {
+public:
+ explicit AudRenA();
+};
+
+} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 6aed9e2fa..9e75eb3a6 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -15,17 +15,14 @@
namespace Service::Audio {
-/// TODO(bunnei): Find a proper value for the audio_ticks
-constexpr u64 audio_ticks{static_cast<u64>(CoreTiming::BASE_CLOCK_RATE / 200)};
-
class IAudioRenderer final : public ServiceFramework<IAudioRenderer> {
public:
- explicit IAudioRenderer(AudioRendererParameter audren_params)
- : ServiceFramework("IAudioRenderer"), worker_params(audren_params) {
+ explicit IAudioRenderer(AudioCore::AudioRendererParameter audren_params)
+ : ServiceFramework("IAudioRenderer") {
static const FunctionInfo functions[] = {
- {0, nullptr, "GetAudioRendererSampleRate"},
- {1, nullptr, "GetAudioRendererSampleCount"},
- {2, nullptr, "GetAudioRendererMixBufferCount"},
+ {0, &IAudioRenderer::GetAudioRendererSampleRate, "GetAudioRendererSampleRate"},
+ {1, &IAudioRenderer::GetAudioRendererSampleCount, "GetAudioRendererSampleCount"},
+ {2, &IAudioRenderer::GetAudioRendererMixBufferCount, "GetAudioRendererMixBufferCount"},
{3, nullptr, "GetAudioRendererState"},
{4, &IAudioRenderer::RequestUpdateAudioRenderer, "RequestUpdateAudioRenderer"},
{5, &IAudioRenderer::StartAudioRenderer, "StartAudioRenderer"},
@@ -39,21 +36,8 @@ public:
RegisterHandlers(functions);
system_event =
- Kernel::Event::Create(Kernel::ResetType::OneShot, "IAudioRenderer:SystemEvent");
-
- // Register event callback to update the Audio Buffer
- audio_event = CoreTiming::RegisterEvent(
- "IAudioRenderer::UpdateAudioCallback", [this](u64 userdata, int cycles_late) {
- UpdateAudioCallback();
- CoreTiming::ScheduleEvent(audio_ticks - cycles_late, audio_event);
- });
-
- // Start the audio event
- CoreTiming::ScheduleEvent(audio_ticks, audio_event);
- voice_status_list.resize(worker_params.voice_count);
- }
- ~IAudioRenderer() {
- CoreTiming::UnscheduleEvent(audio_event, 0);
+ Kernel::Event::Create(Kernel::ResetType::Sticky, "IAudioRenderer:SystemEvent");
+ renderer = std::make_unique<AudioCore::AudioRenderer>(audren_params, system_event);
}
private:
@@ -61,61 +45,31 @@ private:
system_event->Signal();
}
- void RequestUpdateAudioRenderer(Kernel::HLERequestContext& ctx) {
- UpdateDataHeader config{};
- auto buf = ctx.ReadBuffer();
- std::memcpy(&config, buf.data(), sizeof(UpdateDataHeader));
- u32 memory_pool_count = worker_params.effect_count + (worker_params.voice_count * 4);
-
- std::vector<MemoryPoolInfo> mem_pool_info(memory_pool_count);
- std::memcpy(mem_pool_info.data(),
- buf.data() + sizeof(UpdateDataHeader) + config.behavior_size,
- memory_pool_count * sizeof(MemoryPoolInfo));
-
- std::vector<VoiceInfo> voice_info(worker_params.voice_count);
- std::memcpy(voice_info.data(),
- buf.data() + sizeof(UpdateDataHeader) + config.behavior_size +
- config.memory_pools_size + config.voice_resource_size,
- worker_params.voice_count * sizeof(VoiceInfo));
-
- UpdateDataHeader response_data{worker_params};
-
- ASSERT(ctx.GetWriteBufferSize() == response_data.total_size);
-
- std::vector<u8> output(response_data.total_size);
- std::memcpy(output.data(), &response_data, sizeof(UpdateDataHeader));
- std::vector<MemoryPoolEntry> memory_pool(memory_pool_count);
- for (unsigned i = 0; i < memory_pool.size(); i++) {
- if (mem_pool_info[i].pool_state == MemoryPoolStates::RequestAttach)
- memory_pool[i].state = MemoryPoolStates::Attached;
- else if (mem_pool_info[i].pool_state == MemoryPoolStates::RequestDetach)
- memory_pool[i].state = MemoryPoolStates::Detached;
- }
- std::memcpy(output.data() + sizeof(UpdateDataHeader), memory_pool.data(),
- response_data.memory_pools_size);
-
- for (unsigned i = 0; i < voice_info.size(); i++) {
- if (voice_info[i].is_new) {
- voice_status_list[i].played_sample_count = 0;
- voice_status_list[i].wave_buffer_consumed = 0;
- } else if (voice_info[i].play_state == (u8)PlayStates::Started) {
- for (u32 buff_idx = 0; buff_idx < voice_info[i].wave_buffer_count; buff_idx++) {
- voice_status_list[i].played_sample_count +=
- (voice_info[i].wave_buffer[buff_idx].end_sample_offset -
- voice_info[i].wave_buffer[buff_idx].start_sample_offset) /
- 2;
- voice_status_list[i].wave_buffer_consumed++;
- }
- }
- }
- std::memcpy(output.data() + sizeof(UpdateDataHeader) + response_data.memory_pools_size,
- voice_status_list.data(), response_data.voices_size);
+ void GetAudioRendererSampleRate(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push<u32>(renderer->GetSampleRate());
+ LOG_DEBUG(Service_Audio, "called");
+ }
+
+ void GetAudioRendererSampleCount(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push<u32>(renderer->GetSampleCount());
+ LOG_DEBUG(Service_Audio, "called");
+ }
- ctx.WriteBuffer(output);
+ void GetAudioRendererMixBufferCount(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push<u32>(renderer->GetMixBufferCount());
+ LOG_DEBUG(Service_Audio, "called");
+ }
+ void RequestUpdateAudioRenderer(Kernel::HLERequestContext& ctx) {
+ ctx.WriteBuffer(renderer->UpdateAudioRenderer(ctx.ReadBuffer()));
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
-
LOG_WARNING(Service_Audio, "(STUBBED) called");
}
@@ -136,8 +90,6 @@ private:
}
void QuerySystemEvent(Kernel::HLERequestContext& ctx) {
- // system_event->Signal();
-
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(system_event);
@@ -145,131 +97,8 @@ private:
LOG_WARNING(Service_Audio, "(STUBBED) called");
}
- enum class MemoryPoolStates : u32 { // Should be LE
- Invalid = 0x0,
- Unknown = 0x1,
- RequestDetach = 0x2,
- Detached = 0x3,
- RequestAttach = 0x4,
- Attached = 0x5,
- Released = 0x6,
- };
-
- enum class PlayStates : u8 {
- Started = 0,
- Stopped = 1,
- };
-
- struct MemoryPoolEntry {
- MemoryPoolStates state;
- u32_le unknown_4;
- u32_le unknown_8;
- u32_le unknown_c;
- };
- static_assert(sizeof(MemoryPoolEntry) == 0x10, "MemoryPoolEntry has wrong size");
-
- struct MemoryPoolInfo {
- u64_le pool_address;
- u64_le pool_size;
- MemoryPoolStates pool_state;
- INSERT_PADDING_WORDS(3); // Unknown
- };
- static_assert(sizeof(MemoryPoolInfo) == 0x20, "MemoryPoolInfo has wrong size");
-
- struct UpdateDataHeader {
- UpdateDataHeader() {}
-
- explicit UpdateDataHeader(const AudioRendererParameter& config) {
- revision = Common::MakeMagic('R', 'E', 'V', '4'); // 5.1.0 Revision
- behavior_size = 0xb0;
- memory_pools_size = (config.effect_count + (config.voice_count * 4)) * 0x10;
- voices_size = config.voice_count * 0x10;
- voice_resource_size = 0x0;
- effects_size = config.effect_count * 0x10;
- mixes_size = 0x0;
- sinks_size = config.sink_count * 0x20;
- performance_manager_size = 0x10;
- total_size = sizeof(UpdateDataHeader) + behavior_size + memory_pools_size +
- voices_size + effects_size + sinks_size + performance_manager_size;
- }
-
- u32_le revision;
- u32_le behavior_size;
- u32_le memory_pools_size;
- u32_le voices_size;
- u32_le voice_resource_size;
- u32_le effects_size;
- u32_le mixes_size;
- u32_le sinks_size;
- u32_le performance_manager_size;
- INSERT_PADDING_WORDS(6);
- u32_le total_size;
- };
- static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has wrong size");
-
- struct BiquadFilter {
- u8 enable;
- INSERT_PADDING_BYTES(1);
- s16_le numerator[3];
- s16_le denominator[2];
- };
- static_assert(sizeof(BiquadFilter) == 0xc, "BiquadFilter has wrong size");
-
- struct WaveBuffer {
- u64_le buffer_addr;
- u64_le buffer_sz;
- s32_le start_sample_offset;
- s32_le end_sample_offset;
- u8 loop;
- u8 end_of_stream;
- u8 sent_to_server;
- INSERT_PADDING_BYTES(5);
- u64 context_addr;
- u64 context_sz;
- INSERT_PADDING_BYTES(8);
- };
- static_assert(sizeof(WaveBuffer) == 0x38, "WaveBuffer has wrong size");
-
- struct VoiceInfo {
- u32_le id;
- u32_le node_id;
- u8 is_new;
- u8 is_in_use;
- u8 play_state;
- u8 sample_format;
- u32_le sample_rate;
- u32_le priority;
- u32_le sorting_order;
- u32_le channel_count;
- float_le pitch;
- float_le volume;
- BiquadFilter biquad_filter[2];
- u32_le wave_buffer_count;
- u16_le wave_buffer_head;
- INSERT_PADDING_BYTES(6);
- u64_le additional_params_addr;
- u64_le additional_params_sz;
- u32_le mix_id;
- u32_le splitter_info_id;
- WaveBuffer wave_buffer[4];
- u32_le voice_channel_resource_ids[6];
- INSERT_PADDING_BYTES(24);
- };
- static_assert(sizeof(VoiceInfo) == 0x170, "VoiceInfo is wrong size");
-
- struct VoiceOutStatus {
- u64_le played_sample_count;
- u32_le wave_buffer_consumed;
- INSERT_PADDING_WORDS(1);
- };
- static_assert(sizeof(VoiceOutStatus) == 0x10, "VoiceOutStatus has wrong size");
-
- /// This is used to trigger the audio event callback.
- CoreTiming::EventType* audio_event;
-
Kernel::SharedPtr<Kernel::Event> system_event;
- AudioRendererParameter worker_params;
- std::vector<VoiceOutStatus> voice_status_list;
+ std::unique_ptr<AudioCore::AudioRenderer> renderer;
};
class IAudioDevice final : public ServiceFramework<IAudioDevice> {
@@ -361,14 +190,15 @@ AudRenU::AudRenU() : ServiceFramework("audren:u") {
{1, &AudRenU::GetAudioRendererWorkBufferSize, "GetAudioRendererWorkBufferSize"},
{2, &AudRenU::GetAudioDevice, "GetAudioDevice"},
{3, nullptr, "OpenAudioRendererAuto"},
- {4, nullptr, "GetAudioDeviceServiceWithRevisionInfo"},
+ {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo,
+ "GetAudioDeviceServiceWithRevisionInfo"},
};
RegisterHandlers(functions);
}
void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- auto params = rp.PopRaw<AudioRendererParameter>();
+ auto params = rp.PopRaw<AudioCore::AudioRendererParameter>();
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
@@ -379,9 +209,9 @@ void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) {
void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
- auto params = rp.PopRaw<AudioRendererParameter>();
+ auto params = rp.PopRaw<AudioCore::AudioRendererParameter>();
- u64 buffer_sz = Common::AlignUp(4 * params.unknown_8, 0x40);
+ u64 buffer_sz = Common::AlignUp(4 * params.mix_buffer_count, 0x40);
buffer_sz += params.unknown_c * 1024;
buffer_sz += 0x940 * (params.unknown_c + 1);
buffer_sz += 0x3F0 * params.voice_count;
@@ -389,7 +219,7 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
buffer_sz += Common::AlignUp(8 * params.voice_count, 0x10);
buffer_sz +=
Common::AlignUp((0x3C0 * (params.sink_count + params.unknown_c) + 4 * params.sample_count) *
- (params.unknown_8 + 6),
+ (params.mix_buffer_count + 6),
0x40);
if (IsFeatureSupported(AudioFeatures::Splitter, params.revision)) {
@@ -445,6 +275,16 @@ void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");
}
+void AudRenU::GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<Audio::IAudioDevice>();
+
+ LOG_WARNING(Service_Audio, "(STUBBED) called"); // TODO(ogniK): Figure out what is different
+ // based on the current revision
+}
+
bool AudRenU::IsFeatureSupported(AudioFeatures feature, u32_le revision) const {
u32_be version_num = (revision - Common::MakeMagic('R', 'E', 'V', '0')); // Byte swap
switch (feature) {
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h
index b9b81db4f..8600ac6e4 100644
--- a/src/core/hle/service/audio/audren_u.h
+++ b/src/core/hle/service/audio/audren_u.h
@@ -4,6 +4,7 @@
#pragma once
+#include "audio_core/audio_renderer.h"
#include "core/hle/service/service.h"
namespace Kernel {
@@ -12,24 +13,6 @@ class HLERequestContext;
namespace Service::Audio {
-struct AudioRendererParameter {
- u32_le sample_rate;
- u32_le sample_count;
- u32_le unknown_8;
- u32_le unknown_c;
- u32_le voice_count;
- u32_le sink_count;
- u32_le effect_count;
- u32_le unknown_1c;
- u8 unknown_20;
- INSERT_PADDING_BYTES(3);
- u32_le splitter_count;
- u32_le unknown_2c;
- INSERT_PADDING_WORDS(1);
- u32_le revision;
-};
-static_assert(sizeof(AudioRendererParameter) == 52, "AudioRendererParameter is an invalid size");
-
class AudRenU final : public ServiceFramework<AudRenU> {
public:
explicit AudRenU();
@@ -39,6 +22,7 @@ private:
void OpenAudioRenderer(Kernel::HLERequestContext& ctx);
void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx);
void GetAudioDevice(Kernel::HLERequestContext& ctx);
+ void GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx);
enum class AudioFeatures : u32 {
Splitter,
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp
index 844df382c..371cd4997 100644
--- a/src/core/hle/service/audio/hwopus.cpp
+++ b/src/core/hle/service/audio/hwopus.cpp
@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <cstring>
+#include <opus.h>
#include "common/logging/log.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/hle_ipc.h"
@@ -9,19 +11,142 @@
namespace Service::Audio {
+struct OpusDeleter {
+ void operator()(void* ptr) const {
+ operator delete(ptr);
+ }
+};
+
+class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> {
+public:
+ IHardwareOpusDecoderManager(std::unique_ptr<OpusDecoder, OpusDeleter> decoder, u32 sample_rate,
+ u32 channel_count)
+ : ServiceFramework("IHardwareOpusDecoderManager"), decoder(std::move(decoder)),
+ sample_rate(sample_rate), channel_count(channel_count) {
+ static const FunctionInfo functions[] = {
+ {0, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"},
+ {1, nullptr, "SetContext"},
+ {2, nullptr, "DecodeInterleavedForMultiStream"},
+ {3, nullptr, "SetContextForMultiStream"},
+ {4, nullptr, "Unknown4"},
+ {5, nullptr, "Unknown5"},
+ {6, nullptr, "Unknown6"},
+ {7, nullptr, "Unknown7"},
+ };
+ RegisterHandlers(functions);
+ }
+
+private:
+ void DecodeInterleaved(Kernel::HLERequestContext& ctx) {
+ u32 consumed = 0;
+ u32 sample_count = 0;
+ std::vector<opus_int16> samples(ctx.GetWriteBufferSize() / sizeof(opus_int16));
+ if (!Decoder_DecodeInterleaved(consumed, sample_count, ctx.ReadBuffer(), samples)) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ // TODO(ogniK): Use correct error code
+ rb.Push(ResultCode(-1));
+ return;
+ }
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push<u32>(consumed);
+ rb.Push<u32>(sample_count);
+ ctx.WriteBuffer(samples.data(), samples.size() * sizeof(s16));
+ }
+
+ bool Decoder_DecodeInterleaved(u32& consumed, u32& sample_count, const std::vector<u8>& input,
+ std::vector<opus_int16>& output) {
+ size_t raw_output_sz = output.size() * sizeof(opus_int16);
+ if (sizeof(OpusHeader) > input.size())
+ return false;
+ OpusHeader hdr{};
+ std::memcpy(&hdr, input.data(), sizeof(OpusHeader));
+ if (sizeof(OpusHeader) + static_cast<u32>(hdr.sz) > input.size()) {
+ return false;
+ }
+ auto frame = input.data() + sizeof(OpusHeader);
+ auto decoded_sample_count = opus_packet_get_nb_samples(
+ frame, static_cast<opus_int32>(input.size() - sizeof(OpusHeader)),
+ static_cast<opus_int32>(sample_rate));
+ if (decoded_sample_count * channel_count * sizeof(u16) > raw_output_sz)
+ return false;
+ auto out_sample_count =
+ opus_decode(decoder.get(), frame, hdr.sz, output.data(),
+ (static_cast<int>(raw_output_sz / sizeof(s16) / channel_count)), 0);
+ if (out_sample_count < 0)
+ return false;
+ sample_count = out_sample_count;
+ consumed = static_cast<u32>(sizeof(OpusHeader) + hdr.sz);
+ return true;
+ }
+
+ struct OpusHeader {
+ u32_be sz; // Needs to be BE for some odd reason
+ INSERT_PADDING_WORDS(1);
+ };
+ static_assert(sizeof(OpusHeader) == 0x8, "OpusHeader is an invalid size");
+
+ std::unique_ptr<OpusDecoder, OpusDeleter> decoder;
+ u32 sample_rate;
+ u32 channel_count;
+};
+
+static size_t WorkerBufferSize(u32 channel_count) {
+ ASSERT_MSG(channel_count == 1 || channel_count == 2, "Invalid channel count");
+ return opus_decoder_get_size(static_cast<int>(channel_count));
+}
+
void HwOpus::GetWorkBufferSize(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_Audio, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ auto sample_rate = rp.Pop<u32>();
+ auto channel_count = rp.Pop<u32>();
+ ASSERT_MSG(sample_rate == 48000 || sample_rate == 24000 || sample_rate == 16000 ||
+ sample_rate == 12000 || sample_rate == 8000,
+ "Invalid sample rate");
+ ASSERT_MSG(channel_count == 1 || channel_count == 2, "Invalid channel count");
+ u32 worker_buffer_sz = static_cast<u32>(WorkerBufferSize(channel_count));
+ LOG_DEBUG(Audio, "called worker_buffer_sz={}", worker_buffer_sz);
+
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
- rb.Push<u32>(0x4000);
+ rb.Push<u32>(worker_buffer_sz);
+}
+
+void HwOpus::OpenOpusDecoder(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ auto sample_rate = rp.Pop<u32>();
+ auto channel_count = rp.Pop<u32>();
+ auto buffer_sz = rp.Pop<u32>();
+ LOG_DEBUG(Audio, "called sample_rate={}, channel_count={}, buffer_size={}", sample_rate,
+ channel_count, buffer_sz);
+ ASSERT_MSG(sample_rate == 48000 || sample_rate == 24000 || sample_rate == 16000 ||
+ sample_rate == 12000 || sample_rate == 8000,
+ "Invalid sample rate");
+ ASSERT_MSG(channel_count == 1 || channel_count == 2, "Invalid channel count");
+
+ size_t worker_sz = WorkerBufferSize(channel_count);
+ ASSERT_MSG(buffer_sz < worker_sz, "Worker buffer too large");
+ std::unique_ptr<OpusDecoder, OpusDeleter> decoder{
+ static_cast<OpusDecoder*>(operator new(worker_sz))};
+ if (opus_decoder_init(decoder.get(), sample_rate, channel_count)) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ // TODO(ogniK): Use correct error code
+ rb.Push(ResultCode(-1));
+ return;
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IHardwareOpusDecoderManager>(std::move(decoder), sample_rate,
+ channel_count);
}
HwOpus::HwOpus() : ServiceFramework("hwopus") {
static const FunctionInfo functions[] = {
- {0, nullptr, "Initialize"},
+ {0, &HwOpus::OpenOpusDecoder, "OpenOpusDecoder"},
{1, &HwOpus::GetWorkBufferSize, "GetWorkBufferSize"},
- {2, nullptr, "InitializeMultiStream"},
- {3, nullptr, "GetWorkBufferSizeMultiStream"},
+ {2, nullptr, "OpenOpusDecoderForMultiStream"},
+ {3, nullptr, "GetWorkBufferSizeForMultiStream"},
};
RegisterHandlers(functions);
}
diff --git a/src/core/hle/service/audio/hwopus.h b/src/core/hle/service/audio/hwopus.h
index 090b8c825..5258d59f3 100644
--- a/src/core/hle/service/audio/hwopus.h
+++ b/src/core/hle/service/audio/hwopus.h
@@ -14,6 +14,7 @@ public:
~HwOpus() = default;
private:
+ void OpenOpusDecoder(Kernel::HLERequestContext& ctx);
void GetWorkBufferSize(Kernel::HLERequestContext& ctx);
};
diff --git a/src/core/hle/service/bpc/bpc.cpp b/src/core/hle/service/bpc/bpc.cpp
new file mode 100644
index 000000000..1c1ecdb60
--- /dev/null
+++ b/src/core/hle/service/bpc/bpc.cpp
@@ -0,0 +1,57 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "core/hle/service/bpc/bpc.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::BPC {
+
+class BPC final : public ServiceFramework<BPC> {
+public:
+ explicit BPC() : ServiceFramework{"bpc"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "ShutdownSystem"},
+ {1, nullptr, "RebootSystem"},
+ {2, nullptr, "GetWakeupReason"},
+ {3, nullptr, "GetShutdownReason"},
+ {4, nullptr, "GetAcOk"},
+ {5, nullptr, "GetBoardPowerControlEvent"},
+ {6, nullptr, "GetSleepButtonState"},
+ {7, nullptr, "GetPowerEvent"},
+ {8, nullptr, "Unknown1"},
+ {9, nullptr, "Unknown2"},
+ {10, nullptr, "Unknown3"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class BPC_R final : public ServiceFramework<BPC_R> {
+public:
+ explicit BPC_R() : ServiceFramework{"bpc:r"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetExternalRtcValue"},
+ {1, nullptr, "SetExternalRtcValue"},
+ {2, nullptr, "ReadExternalRtcResetFlag"},
+ {3, nullptr, "ClearExternalRtcResetFlag"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<BPC>()->InstallAsService(sm);
+ std::make_shared<BPC_R>()->InstallAsService(sm);
+}
+
+} // namespace Service::BPC
diff --git a/src/core/hle/service/bpc/bpc.h b/src/core/hle/service/bpc/bpc.h
new file mode 100644
index 000000000..eaa37be8d
--- /dev/null
+++ b/src/core/hle/service/bpc/bpc.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::BPC {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::BPC
diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp
new file mode 100644
index 000000000..d0a15cc4c
--- /dev/null
+++ b/src/core/hle/service/btdrv/btdrv.cpp
@@ -0,0 +1,72 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/btdrv/btdrv.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::BtDrv {
+
+class BtDrv final : public ServiceFramework<BtDrv> {
+public:
+ explicit BtDrv() : ServiceFramework{"btdrv"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown"},
+ {1, nullptr, "Init"},
+ {2, nullptr, "Enable"},
+ {3, nullptr, "Disable"},
+ {4, nullptr, "CleanupAndShutdown"},
+ {5, nullptr, "GetAdapterProperties"},
+ {6, nullptr, "GetAdapterProperty"},
+ {7, nullptr, "SetAdapterProperty"},
+ {8, nullptr, "StartDiscovery"},
+ {9, nullptr, "CancelDiscovery"},
+ {10, nullptr, "CreateBond"},
+ {11, nullptr, "RemoveBond"},
+ {12, nullptr, "CancelBond"},
+ {13, nullptr, "PinReply"},
+ {14, nullptr, "SspReply"},
+ {15, nullptr, "Unknown2"},
+ {16, nullptr, "InitInterfaces"},
+ {17, nullptr, "HidHostInterface_Connect"},
+ {18, nullptr, "HidHostInterface_Disconnect"},
+ {19, nullptr, "HidHostInterface_SendData"},
+ {20, nullptr, "HidHostInterface_SendData2"},
+ {21, nullptr, "HidHostInterface_SetReport"},
+ {22, nullptr, "HidHostInterface_GetReport"},
+ {23, nullptr, "HidHostInterface_WakeController"},
+ {24, nullptr, "HidHostInterface_AddPairedDevice"},
+ {25, nullptr, "HidHostInterface_GetPairedDevice"},
+ {26, nullptr, "HidHostInterface_CleanupAndShutdown"},
+ {27, nullptr, "Unknown3"},
+ {28, nullptr, "ExtInterface_SetTSI"},
+ {29, nullptr, "ExtInterface_SetBurstMode"},
+ {30, nullptr, "ExtInterface_SetZeroRetran"},
+ {31, nullptr, "ExtInterface_SetMcMode"},
+ {32, nullptr, "ExtInterface_StartLlrMode"},
+ {33, nullptr, "ExtInterface_ExitLlrMode"},
+ {34, nullptr, "ExtInterface_SetRadio"},
+ {35, nullptr, "ExtInterface_SetVisibility"},
+ {36, nullptr, "Unknown4"},
+ {37, nullptr, "Unknown5"},
+ {38, nullptr, "HidHostInterface_GetLatestPlr"},
+ {39, nullptr, "ExtInterface_GetPendingConnections"},
+ {40, nullptr, "HidHostInterface_GetChannelMap"},
+ {41, nullptr, "SetIsBluetoothBoostEnabled"},
+ {42, nullptr, "GetIsBluetoothBoostEnabled"},
+ {43, nullptr, "SetIsBluetoothAfhEnabled"},
+ {44, nullptr, "GetIsBluetoothAfhEnabled"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<BtDrv>()->InstallAsService(sm);
+}
+
+} // namespace Service::BtDrv
diff --git a/src/core/hle/service/btdrv/btdrv.h b/src/core/hle/service/btdrv/btdrv.h
new file mode 100644
index 000000000..164e56f43
--- /dev/null
+++ b/src/core/hle/service/btdrv/btdrv.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::BtDrv {
+
+/// Registers all BtDrv services with the specified service manager.
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::BtDrv
diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp
new file mode 100644
index 000000000..b949bfabd
--- /dev/null
+++ b/src/core/hle/service/btm/btm.cpp
@@ -0,0 +1,121 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "common/logging/log.h"
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/service/btm/btm.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::BTM {
+
+class BTM final : public ServiceFramework<BTM> {
+public:
+ explicit BTM() : ServiceFramework{"btm"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown1"},
+ {1, nullptr, "Unknown2"},
+ {2, nullptr, "RegisterSystemEventForConnectedDeviceConditionImpl"},
+ {3, nullptr, "Unknown3"},
+ {4, nullptr, "Unknown4"},
+ {5, nullptr, "Unknown5"},
+ {6, nullptr, "Unknown6"},
+ {7, nullptr, "Unknown7"},
+ {8, nullptr, "RegisterSystemEventForRegisteredDeviceInfoImpl"},
+ {9, nullptr, "Unknown8"},
+ {10, nullptr, "Unknown9"},
+ {11, nullptr, "Unknown10"},
+ {12, nullptr, "Unknown11"},
+ {13, nullptr, "Unknown12"},
+ {14, nullptr, "EnableRadioImpl"},
+ {15, nullptr, "DisableRadioImpl"},
+ {16, nullptr, "Unknown13"},
+ {17, nullptr, "Unknown14"},
+ {18, nullptr, "Unknown15"},
+ {19, nullptr, "Unknown16"},
+ {20, nullptr, "Unknown17"},
+ {21, nullptr, "Unknown18"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class BTM_DBG final : public ServiceFramework<BTM_DBG> {
+public:
+ explicit BTM_DBG() : ServiceFramework{"btm:dbg"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RegisterSystemEventForDiscoveryImpl"},
+ {1, nullptr, "Unknown1"},
+ {2, nullptr, "Unknown2"},
+ {3, nullptr, "Unknown3"},
+ {4, nullptr, "Unknown4"},
+ {5, nullptr, "Unknown5"},
+ {6, nullptr, "Unknown6"},
+ {7, nullptr, "Unknown7"},
+ {8, nullptr, "Unknown8"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class IBtmSystemCore final : public ServiceFramework<IBtmSystemCore> {
+public:
+ explicit IBtmSystemCore() : ServiceFramework{"IBtmSystemCore"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "StartGamepadPairingImpl"},
+ {1, nullptr, "CancelGamepadPairingImpl"},
+ {2, nullptr, "ClearGamepadPairingDatabaseImpl"},
+ {3, nullptr, "GetPairedGamepadCountImpl"},
+ {4, nullptr, "EnableRadioImpl"},
+ {5, nullptr, "DisableRadioImpl"},
+ {6, nullptr, "GetRadioOnOffImpl"},
+ {7, nullptr, "AcquireRadioEventImpl"},
+ {8, nullptr, "AcquireGamepadPairingEventImpl"},
+ {9, nullptr, "IsGamepadPairingStartedImpl"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class BTM_SYS final : public ServiceFramework<BTM_SYS> {
+public:
+ explicit BTM_SYS() : ServiceFramework{"btm:sys"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &BTM_SYS::GetCoreImpl, "GetCoreImpl"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void GetCoreImpl(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IBtmSystemCore>();
+
+ LOG_DEBUG(Service_BTM, "called");
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<BTM>()->InstallAsService(sm);
+ std::make_shared<BTM_DBG>()->InstallAsService(sm);
+ std::make_shared<BTM_SYS>()->InstallAsService(sm);
+}
+
+} // namespace Service::BTM
diff --git a/src/core/hle/service/btm/btm.h b/src/core/hle/service/btm/btm.h
new file mode 100644
index 000000000..e6425a7e3
--- /dev/null
+++ b/src/core/hle/service/btm/btm.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::BTM {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::BTM
diff --git a/src/core/hle/service/caps/caps.cpp b/src/core/hle/service/caps/caps.cpp
new file mode 100644
index 000000000..ae7b0720b
--- /dev/null
+++ b/src/core/hle/service/caps/caps.cpp
@@ -0,0 +1,152 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "core/hle/service/caps/caps.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::Capture {
+
+class CAPS_A final : public ServiceFramework<CAPS_A> {
+public:
+ explicit CAPS_A() : ServiceFramework{"caps:a"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown1"},
+ {1, nullptr, "Unknown2"},
+ {2, nullptr, "Unknown3"},
+ {3, nullptr, "Unknown4"},
+ {4, nullptr, "Unknown5"},
+ {5, nullptr, "Unknown6"},
+ {6, nullptr, "Unknown7"},
+ {7, nullptr, "Unknown8"},
+ {8, nullptr, "Unknown9"},
+ {9, nullptr, "Unknown10"},
+ {10, nullptr, "Unknown11"},
+ {11, nullptr, "Unknown12"},
+ {12, nullptr, "Unknown13"},
+ {13, nullptr, "Unknown14"},
+ {14, nullptr, "Unknown15"},
+ {301, nullptr, "Unknown16"},
+ {401, nullptr, "Unknown17"},
+ {501, nullptr, "Unknown18"},
+ {1001, nullptr, "Unknown19"},
+ {1002, nullptr, "Unknown20"},
+ {8001, nullptr, "Unknown21"},
+ {8002, nullptr, "Unknown22"},
+ {8011, nullptr, "Unknown23"},
+ {8012, nullptr, "Unknown24"},
+ {8021, nullptr, "Unknown25"},
+ {10011, nullptr, "Unknown26"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class CAPS_C final : public ServiceFramework<CAPS_C> {
+public:
+ explicit CAPS_C() : ServiceFramework{"caps:c"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {2001, nullptr, "Unknown1"},
+ {2002, nullptr, "Unknown2"},
+ {2011, nullptr, "Unknown3"},
+ {2012, nullptr, "Unknown4"},
+ {2013, nullptr, "Unknown5"},
+ {2014, nullptr, "Unknown6"},
+ {2101, nullptr, "Unknown7"},
+ {2102, nullptr, "Unknown8"},
+ {2201, nullptr, "Unknown9"},
+ {2301, nullptr, "Unknown10"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class CAPS_SC final : public ServiceFramework<CAPS_SC> {
+public:
+ explicit CAPS_SC() : ServiceFramework{"caps:sc"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {1, nullptr, "Unknown1"},
+ {2, nullptr, "Unknown2"},
+ {1001, nullptr, "Unknown3"},
+ {1002, nullptr, "Unknown4"},
+ {1003, nullptr, "Unknown5"},
+ {1011, nullptr, "Unknown6"},
+ {1012, nullptr, "Unknown7"},
+ {1201, nullptr, "Unknown8"},
+ {1202, nullptr, "Unknown9"},
+ {1203, nullptr, "Unknown10"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class CAPS_SS final : public ServiceFramework<CAPS_SS> {
+public:
+ explicit CAPS_SS() : ServiceFramework{"caps:ss"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {201, nullptr, "Unknown1"},
+ {202, nullptr, "Unknown2"},
+ {203, nullptr, "Unknown3"},
+ {204, nullptr, "Unknown4"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class CAPS_SU final : public ServiceFramework<CAPS_SU> {
+public:
+ explicit CAPS_SU() : ServiceFramework{"caps:su"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {201, nullptr, "SaveScreenShot"},
+ {203, nullptr, "SaveScreenShotEx0"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class CAPS_U final : public ServiceFramework<CAPS_U> {
+public:
+ explicit CAPS_U() : ServiceFramework{"caps:u"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {102, nullptr, "GetAlbumFileListByAruid"},
+ {103, nullptr, "DeleteAlbumFileByAruid"},
+ {104, nullptr, "GetAlbumFileSizeByAruid"},
+ {110, nullptr, "LoadAlbumScreenShotImageByAruid"},
+ {120, nullptr, "LoadAlbumScreenShotThumbnailImageByAruid"},
+ {60002, nullptr, "OpenAccessorSessionForApplication"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<CAPS_A>()->InstallAsService(sm);
+ std::make_shared<CAPS_C>()->InstallAsService(sm);
+ std::make_shared<CAPS_SC>()->InstallAsService(sm);
+ std::make_shared<CAPS_SS>()->InstallAsService(sm);
+ std::make_shared<CAPS_SU>()->InstallAsService(sm);
+ std::make_shared<CAPS_U>()->InstallAsService(sm);
+}
+
+} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps.h b/src/core/hle/service/caps/caps.h
new file mode 100644
index 000000000..471185dfa
--- /dev/null
+++ b/src/core/hle/service/caps/caps.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::Capture {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::Capture
diff --git a/src/core/hle/service/fgm/fgm.cpp b/src/core/hle/service/fgm/fgm.cpp
new file mode 100644
index 000000000..566fbf924
--- /dev/null
+++ b/src/core/hle/service/fgm/fgm.cpp
@@ -0,0 +1,75 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/service/fgm/fgm.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::FGM {
+
+class IRequest final : public ServiceFramework<IRequest> {
+public:
+ explicit IRequest() : ServiceFramework{"IRequest"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Initialize"},
+ {1, nullptr, "Set"},
+ {2, nullptr, "Get"},
+ {3, nullptr, "Cancel"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class FGM final : public ServiceFramework<FGM> {
+public:
+ explicit FGM(const char* name) : ServiceFramework{name} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &FGM::Initialize, "Initialize"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void Initialize(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IRequest>();
+
+ LOG_DEBUG(Service_FGM, "called");
+ }
+};
+
+class FGM_DBG final : public ServiceFramework<FGM_DBG> {
+public:
+ explicit FGM_DBG() : ServiceFramework{"fgm:dbg"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Initialize"},
+ {1, nullptr, "Read"},
+ {2, nullptr, "Cancel"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<FGM>("fgm")->InstallAsService(sm);
+ std::make_shared<FGM>("fgm:0")->InstallAsService(sm);
+ std::make_shared<FGM>("fgm:9")->InstallAsService(sm);
+ std::make_shared<FGM_DBG>()->InstallAsService(sm);
+}
+
+} // namespace Service::FGM
diff --git a/src/core/hle/service/fgm/fgm.h b/src/core/hle/service/fgm/fgm.h
new file mode 100644
index 000000000..e59691264
--- /dev/null
+++ b/src/core/hle/service/fgm/fgm.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::FGM {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::FGM
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index fdd2fda18..da658cbe6 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -14,6 +14,8 @@
#include "core/file_sys/vfs_offset.h"
#include "core/file_sys/vfs_real.h"
#include "core/hle/service/filesystem/filesystem.h"
+#include "core/hle/service/filesystem/fsp_ldr.h"
+#include "core/hle/service/filesystem/fsp_pr.h"
#include "core/hle/service/filesystem/fsp_srv.h"
namespace Service::FileSystem {
@@ -57,7 +59,7 @@ ResultCode VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64
ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) const {
std::string path(FileUtil::SanitizePath(path_));
auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(path));
- if (path == "/" || path == "\\") {
+ if (path.empty()) {
// TODO(DarkLordZach): Why do games call this and what should it do? Works as is but...
return RESULT_SUCCESS;
}
@@ -224,6 +226,7 @@ ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType(
static std::unique_ptr<FileSys::RomFSFactory> romfs_factory;
static std::unique_ptr<FileSys::SaveDataFactory> save_data_factory;
static std::unique_ptr<FileSys::SDMCFactory> sdmc_factory;
+static std::unique_ptr<FileSys::BISFactory> bis_factory;
ResultCode RegisterRomFS(std::unique_ptr<FileSys::RomFSFactory>&& factory) {
ASSERT_MSG(romfs_factory == nullptr, "Tried to register a second RomFS");
@@ -246,6 +249,13 @@ ResultCode RegisterSDMC(std::unique_ptr<FileSys::SDMCFactory>&& factory) {
return RESULT_SUCCESS;
}
+ResultCode RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory) {
+ ASSERT_MSG(bis_factory == nullptr, "Tried to register a second BIS");
+ bis_factory = std::move(factory);
+ LOG_DEBUG(Service_FS, "Registred BIS");
+ return RESULT_SUCCESS;
+}
+
ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id) {
LOG_TRACE(Service_FS, "Opening RomFS for title_id={:016X}", title_id);
@@ -279,15 +289,26 @@ ResultVal<FileSys::VirtualDir> OpenSDMC() {
return sdmc_factory->Open();
}
-void RegisterFileSystems() {
+std::shared_ptr<FileSys::RegisteredCache> GetSystemNANDContents() {
+ return bis_factory->GetSystemNANDContents();
+}
+
+std::shared_ptr<FileSys::RegisteredCache> GetUserNANDContents() {
+ return bis_factory->GetUserNANDContents();
+}
+
+void RegisterFileSystems(const FileSys::VirtualFilesystem& vfs) {
romfs_factory = nullptr;
save_data_factory = nullptr;
sdmc_factory = nullptr;
- auto nand_directory = std::make_shared<FileSys::RealVfsDirectory>(
- FileUtil::GetUserPath(FileUtil::UserPath::NANDDir), FileSys::Mode::ReadWrite);
- auto sd_directory = std::make_shared<FileSys::RealVfsDirectory>(
- FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), FileSys::Mode::ReadWrite);
+ auto nand_directory = vfs->OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir),
+ FileSys::Mode::ReadWrite);
+ auto sd_directory = vfs->OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir),
+ FileSys::Mode::ReadWrite);
+
+ if (bis_factory == nullptr)
+ bis_factory = std::make_unique<FileSys::BISFactory>(nand_directory);
auto savedata = std::make_unique<FileSys::SaveDataFactory>(std::move(nand_directory));
save_data_factory = std::move(savedata);
@@ -296,8 +317,10 @@ void RegisterFileSystems() {
sdmc_factory = std::move(sdcard);
}
-void InstallInterfaces(SM::ServiceManager& service_manager) {
- RegisterFileSystems();
+void InstallInterfaces(SM::ServiceManager& service_manager, const FileSys::VirtualFilesystem& vfs) {
+ RegisterFileSystems(vfs);
+ std::make_shared<FSP_LDR>()->InstallAsService(service_manager);
+ std::make_shared<FSP_PR>()->InstallAsService(service_manager);
std::make_shared<FSP_SRV>()->InstallAsService(service_manager);
}
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index d4483daa5..1d6f922dd 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -6,6 +6,7 @@
#include <memory>
#include "common/common_types.h"
+#include "core/file_sys/bis_factory.h"
#include "core/file_sys/directory.h"
#include "core/file_sys/mode.h"
#include "core/file_sys/romfs_factory.h"
@@ -24,19 +25,18 @@ namespace FileSystem {
ResultCode RegisterRomFS(std::unique_ptr<FileSys::RomFSFactory>&& factory);
ResultCode RegisterSaveData(std::unique_ptr<FileSys::SaveDataFactory>&& factory);
ResultCode RegisterSDMC(std::unique_ptr<FileSys::SDMCFactory>&& factory);
+ResultCode RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory);
-// TODO(DarkLordZach): BIS Filesystem
-// ResultCode RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory);
ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id);
ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space,
FileSys::SaveDataDescriptor save_struct);
ResultVal<FileSys::VirtualDir> OpenSDMC();
-// TODO(DarkLordZach): BIS Filesystem
-// ResultVal<std::unique_ptr<FileSys::FileSystemBackend>> OpenBIS();
+std::shared_ptr<FileSys::RegisteredCache> GetSystemNANDContents();
+std::shared_ptr<FileSys::RegisteredCache> GetUserNANDContents();
/// Registers all Filesystem services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager);
+void InstallInterfaces(SM::ServiceManager& service_manager, const FileSys::VirtualFilesystem& vfs);
// A class that wraps a VfsDirectory with methods that return ResultVal and ResultCode instead of
// pointers and booleans. This makes using a VfsDirectory with switch services much easier and
diff --git a/src/core/hle/service/filesystem/fsp_ldr.cpp b/src/core/hle/service/filesystem/fsp_ldr.cpp
new file mode 100644
index 000000000..0ab9c2606
--- /dev/null
+++ b/src/core/hle/service/filesystem/fsp_ldr.cpp
@@ -0,0 +1,22 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/filesystem/fsp_ldr.h"
+#include "core/hle/service/service.h"
+
+namespace Service::FileSystem {
+
+FSP_LDR::FSP_LDR() : ServiceFramework{"fsp:ldr"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "OpenCodeFileSystem"},
+ {1, nullptr, "IsArchivedProgram"},
+ {2, nullptr, "SetCurrentProcess"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::FileSystem
diff --git a/src/core/hle/service/filesystem/fsp_ldr.h b/src/core/hle/service/filesystem/fsp_ldr.h
new file mode 100644
index 000000000..fa8e11b4c
--- /dev/null
+++ b/src/core/hle/service/filesystem/fsp_ldr.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::FileSystem {
+
+class FSP_LDR final : public ServiceFramework<FSP_LDR> {
+public:
+ explicit FSP_LDR();
+};
+
+} // namespace Service::FileSystem
diff --git a/src/core/hle/service/filesystem/fsp_pr.cpp b/src/core/hle/service/filesystem/fsp_pr.cpp
new file mode 100644
index 000000000..32b0ae454
--- /dev/null
+++ b/src/core/hle/service/filesystem/fsp_pr.cpp
@@ -0,0 +1,23 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/filesystem/fsp_pr.h"
+#include "core/hle/service/service.h"
+
+namespace Service::FileSystem {
+
+FSP_PR::FSP_PR() : ServiceFramework{"fsp:pr"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RegisterProgram"},
+ {1, nullptr, "UnregisterProgram"},
+ {2, nullptr, "SetCurrentProcess"},
+ {256, nullptr, "SetEnabledProgramVerification"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::FileSystem
diff --git a/src/core/hle/service/filesystem/fsp_pr.h b/src/core/hle/service/filesystem/fsp_pr.h
new file mode 100644
index 000000000..62edcd08a
--- /dev/null
+++ b/src/core/hle/service/filesystem/fsp_pr.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::FileSystem {
+
+class FSP_PR final : public ServiceFramework<FSP_PR> {
+public:
+ explicit FSP_PR();
+};
+
+} // namespace Service::FileSystem
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index e7ffb6bd1..1470f9017 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -193,13 +193,10 @@ private:
template <typename T>
static void BuildEntryIndex(std::vector<FileSys::Entry>& entries, const std::vector<T>& new_data,
FileSys::EntryType type) {
+ entries.reserve(entries.size() + new_data.size());
+
for (const auto& new_entry : new_data) {
- FileSys::Entry entry;
- entry.filename[0] = '\0';
- std::strncat(entry.filename, new_entry->GetName().c_str(), FileSys::FILENAME_LENGTH - 1);
- entry.type = type;
- entry.file_size = new_entry->GetSize();
- entries.emplace_back(std::move(entry));
+ entries.emplace_back(new_entry->GetName(), type, new_entry->GetSize());
}
}
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp
index fb4d89068..f2b0e509a 100644
--- a/src/core/hle/service/friend/friend.cpp
+++ b/src/core/hle/service/friend/friend.cpp
@@ -9,10 +9,110 @@
namespace Service::Friend {
+class IFriendService final : public ServiceFramework<IFriendService> {
+public:
+ IFriendService() : ServiceFramework("IFriendService") {
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetCompletionEvent"},
+ {1, nullptr, "Cancel"},
+ {10100, nullptr, "GetFriendListIds"},
+ {10101, nullptr, "GetFriendList"},
+ {10102, nullptr, "UpdateFriendInfo"},
+ {10110, nullptr, "GetFriendProfileImage"},
+ {10200, nullptr, "SendFriendRequestForApplication"},
+ {10211, nullptr, "AddFacedFriendRequestForApplication"},
+ {10400, nullptr, "GetBlockedUserListIds"},
+ {10500, nullptr, "GetProfileList"},
+ {10600, nullptr, "DeclareOpenOnlinePlaySession"},
+ {10601, &IFriendService::DeclareCloseOnlinePlaySession,
+ "DeclareCloseOnlinePlaySession"},
+ {10610, &IFriendService::UpdateUserPresence, "UpdateUserPresence"},
+ {10700, nullptr, "GetPlayHistoryRegistrationKey"},
+ {10701, nullptr, "GetPlayHistoryRegistrationKeyWithNetworkServiceAccountId"},
+ {10702, nullptr, "AddPlayHistory"},
+ {11000, nullptr, "GetProfileImageUrl"},
+ {20100, nullptr, "GetFriendCount"},
+ {20101, nullptr, "GetNewlyFriendCount"},
+ {20102, nullptr, "GetFriendDetailedInfo"},
+ {20103, nullptr, "SyncFriendList"},
+ {20104, nullptr, "RequestSyncFriendList"},
+ {20110, nullptr, "LoadFriendSetting"},
+ {20200, nullptr, "GetReceivedFriendRequestCount"},
+ {20201, nullptr, "GetFriendRequestList"},
+ {20300, nullptr, "GetFriendCandidateList"},
+ {20301, nullptr, "GetNintendoNetworkIdInfo"},
+ {20302, nullptr, "GetSnsAccountLinkage"},
+ {20303, nullptr, "GetSnsAccountProfile"},
+ {20304, nullptr, "GetSnsAccountFriendList"},
+ {20400, nullptr, "GetBlockedUserList"},
+ {20401, nullptr, "SyncBlockedUserList"},
+ {20500, nullptr, "GetProfileExtraList"},
+ {20501, nullptr, "GetRelationship"},
+ {20600, nullptr, "GetUserPresenceView"},
+ {20700, nullptr, "GetPlayHistoryList"},
+ {20701, nullptr, "GetPlayHistoryStatistics"},
+ {20800, nullptr, "LoadUserSetting"},
+ {20801, nullptr, "SyncUserSetting"},
+ {20900, nullptr, "RequestListSummaryOverlayNotification"},
+ {21000, nullptr, "GetExternalApplicationCatalog"},
+ {30100, nullptr, "DropFriendNewlyFlags"},
+ {30101, nullptr, "DeleteFriend"},
+ {30110, nullptr, "DropFriendNewlyFlag"},
+ {30120, nullptr, "ChangeFriendFavoriteFlag"},
+ {30121, nullptr, "ChangeFriendOnlineNotificationFlag"},
+ {30200, nullptr, "SendFriendRequest"},
+ {30201, nullptr, "SendFriendRequestWithApplicationInfo"},
+ {30202, nullptr, "CancelFriendRequest"},
+ {30203, nullptr, "AcceptFriendRequest"},
+ {30204, nullptr, "RejectFriendRequest"},
+ {30205, nullptr, "ReadFriendRequest"},
+ {30210, nullptr, "GetFacedFriendRequestRegistrationKey"},
+ {30211, nullptr, "AddFacedFriendRequest"},
+ {30212, nullptr, "CancelFacedFriendRequest"},
+ {30213, nullptr, "GetFacedFriendRequestProfileImage"},
+ {30214, nullptr, "GetFacedFriendRequestProfileImageFromPath"},
+ {30215, nullptr, "SendFriendRequestWithExternalApplicationCatalogId"},
+ {30216, nullptr, "ResendFacedFriendRequest"},
+ {30217, nullptr, "SendFriendRequestWithNintendoNetworkIdInfo"},
+ {30300, nullptr, "GetSnsAccountLinkPageUrl"},
+ {30301, nullptr, "UnlinkSnsAccount"},
+ {30400, nullptr, "BlockUser"},
+ {30401, nullptr, "BlockUserWithApplicationInfo"},
+ {30402, nullptr, "UnblockUser"},
+ {30500, nullptr, "GetProfileExtraFromFriendCode"},
+ {30700, nullptr, "DeletePlayHistory"},
+ {30810, nullptr, "ChangePresencePermission"},
+ {30811, nullptr, "ChangeFriendRequestReception"},
+ {30812, nullptr, "ChangePlayLogPermission"},
+ {30820, nullptr, "IssueFriendCode"},
+ {30830, nullptr, "ClearPlayLog"},
+ {49900, nullptr, "DeleteNetworkServiceAccountCache"},
+ };
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void DeclareCloseOnlinePlaySession(Kernel::HLERequestContext& ctx) {
+ // Stub used by Splatoon 2
+ LOG_WARNING(Service_ACC, "(STUBBED) called");
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ }
+
+ void UpdateUserPresence(Kernel::HLERequestContext& ctx) {
+ // Stub used by Retro City Rampage
+ LOG_WARNING(Service_ACC, "(STUBBED) called");
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ }
+};
+
void Module::Interface::CreateFriendService(Kernel::HLERequestContext& ctx) {
- IPC::ResponseBuilder rb{ctx, 2};
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
- LOG_WARNING(Service_Friend, "(STUBBED) called");
+ rb.PushIpcInterface<IFriendService>();
+ LOG_DEBUG(Service_ACC, "called");
}
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
diff --git a/src/core/hle/service/grc/grc.cpp b/src/core/hle/service/grc/grc.cpp
new file mode 100644
index 000000000..24910ac6c
--- /dev/null
+++ b/src/core/hle/service/grc/grc.cpp
@@ -0,0 +1,31 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "core/hle/service/grc/grc.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::GRC {
+
+class GRC final : public ServiceFramework<GRC> {
+public:
+ explicit GRC() : ServiceFramework{"grc:c"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {1, nullptr, "OpenContinuousRecorder"},
+ {2, nullptr, "OpenGameMovieTrimmer"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<GRC>()->InstallAsService(sm);
+}
+
+} // namespace Service::GRC
diff --git a/src/core/hle/service/grc/grc.h b/src/core/hle/service/grc/grc.h
new file mode 100644
index 000000000..e0d29e70d
--- /dev/null
+++ b/src/core/hle/service/grc/grc.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::GRC {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::GRC
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 9a02ba686..970942d3f 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -14,6 +14,8 @@
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/service/hid/hid.h"
+#include "core/hle/service/hid/irs.h"
+#include "core/hle/service/hid/xcd.h"
#include "core/hle/service/service.h"
namespace Service::HID {
@@ -289,6 +291,7 @@ private:
class Hid final : public ServiceFramework<Hid> {
public:
Hid() : ServiceFramework("hid") {
+ // clang-format off
static const FunctionInfo functions[] = {
{0, &Hid::CreateAppletResource, "CreateAppletResource"},
{1, &Hid::ActivateDebugPad, "ActivateDebugPad"},
@@ -324,24 +327,23 @@ public:
{79, &Hid::SetGyroscopeZeroDriftMode, "SetGyroscopeZeroDriftMode"},
{80, nullptr, "GetGyroscopeZeroDriftMode"},
{81, nullptr, "ResetGyroscopeZeroDriftMode"},
- {82, nullptr, "IsSixAxisSensorAtRest"},
+ {82, &Hid::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"},
{91, nullptr, "ActivateGesture"},
{100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"},
{101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"},
{102, &Hid::SetSupportedNpadIdType, "SetSupportedNpadIdType"},
{103, &Hid::ActivateNpad, "ActivateNpad"},
{104, nullptr, "DeactivateNpad"},
- {106, &Hid::AcquireNpadStyleSetUpdateEventHandle,
- "AcquireNpadStyleSetUpdateEventHandle"},
- {107, nullptr, "DisconnectNpad"},
+ {106, &Hid::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"},
+ {107, &Hid::DisconnectNpad, "DisconnectNpad"},
{108, &Hid::GetPlayerLedPattern, "GetPlayerLedPattern"},
+ {109, nullptr, "ActivateNpadWithRevision"},
{120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
{121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
- {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault,
- "SetNpadJoyAssignmentModeSingleByDefault"},
+ {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault, "SetNpadJoyAssignmentModeSingleByDefault"},
{123, nullptr, "SetNpadJoyAssignmentModeSingleByDefault"},
{124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"},
- {125, nullptr, "MergeSingleJoyAsDualJoy"},
+ {125, &Hid::MergeSingleJoyAsDualJoy, "MergeSingleJoyAsDualJoy"},
{126, nullptr, "StartLrAssignmentMode"},
{127, nullptr, "StopLrAssignmentMode"},
{128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"},
@@ -395,6 +397,8 @@ public:
{1000, nullptr, "SetNpadCommunicationMode"},
{1001, nullptr, "GetNpadCommunicationMode"},
};
+ // clang-format on
+
RegisterHandlers(functions);
event = Kernel::Event::Create(Kernel::ResetType::OneShot, "hid:EventHandle");
@@ -453,6 +457,14 @@ private:
LOG_WARNING(Service_HID, "(STUBBED) called");
}
+ void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ // TODO (Hexagon12): Properly implement reading gyroscope values from controllers.
+ rb.Push(true);
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+ }
+
void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -485,6 +497,12 @@ private:
LOG_WARNING(Service_HID, "(STUBBED) called");
}
+ void DisconnectNpad(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+ }
+
void GetPlayerLedPattern(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -528,6 +546,12 @@ private:
LOG_WARNING(Service_HID, "(STUBBED) called");
}
+ void MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+ }
+
void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -555,10 +579,233 @@ private:
}
};
+class HidDbg final : public ServiceFramework<HidDbg> {
+public:
+ explicit HidDbg() : ServiceFramework{"hid:dbg"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "DeactivateDebugPad"},
+ {1, nullptr, "SetDebugPadAutoPilotState"},
+ {2, nullptr, "UnsetDebugPadAutoPilotState"},
+ {10, nullptr, "DeactivateTouchScreen"},
+ {11, nullptr, "SetTouchScreenAutoPilotState"},
+ {12, nullptr, "UnsetTouchScreenAutoPilotState"},
+ {20, nullptr, "DeactivateMouse"},
+ {21, nullptr, "SetMouseAutoPilotState"},
+ {22, nullptr, "UnsetMouseAutoPilotState"},
+ {30, nullptr, "DeactivateKeyboard"},
+ {31, nullptr, "SetKeyboardAutoPilotState"},
+ {32, nullptr, "UnsetKeyboardAutoPilotState"},
+ {50, nullptr, "DeactivateXpad"},
+ {51, nullptr, "SetXpadAutoPilotState"},
+ {52, nullptr, "UnsetXpadAutoPilotState"},
+ {60, nullptr, "DeactivateJoyXpad"},
+ {91, nullptr, "DeactivateGesture"},
+ {110, nullptr, "DeactivateHomeButton"},
+ {111, nullptr, "SetHomeButtonAutoPilotState"},
+ {112, nullptr, "UnsetHomeButtonAutoPilotState"},
+ {120, nullptr, "DeactivateSleepButton"},
+ {121, nullptr, "SetSleepButtonAutoPilotState"},
+ {122, nullptr, "UnsetSleepButtonAutoPilotState"},
+ {123, nullptr, "DeactivateInputDetector"},
+ {130, nullptr, "DeactivateCaptureButton"},
+ {131, nullptr, "SetCaptureButtonAutoPilotState"},
+ {132, nullptr, "UnsetCaptureButtonAutoPilotState"},
+ {133, nullptr, "SetShiftAccelerometerCalibrationValue"},
+ {134, nullptr, "GetShiftAccelerometerCalibrationValue"},
+ {135, nullptr, "SetShiftGyroscopeCalibrationValue"},
+ {136, nullptr, "GetShiftGyroscopeCalibrationValue"},
+ {140, nullptr, "DeactivateConsoleSixAxisSensor"},
+ {141, nullptr, "GetConsoleSixAxisSensorSamplingFrequency"},
+ {142, nullptr, "DeactivateSevenSixAxisSensor"},
+ {201, nullptr, "ActivateFirmwareUpdate"},
+ {202, nullptr, "DeactivateFirmwareUpdate"},
+ {203, nullptr, "StartFirmwareUpdate"},
+ {204, nullptr, "GetFirmwareUpdateStage"},
+ {205, nullptr, "GetFirmwareVersion"},
+ {206, nullptr, "GetDestinationFirmwareVersion"},
+ {207, nullptr, "DiscardFirmwareInfoCacheForRevert"},
+ {208, nullptr, "StartFirmwareUpdateForRevert"},
+ {209, nullptr, "GetAvailableFirmwareVersionForRevert"},
+ {210, nullptr, "IsFirmwareUpdatingDevice"},
+ {221, nullptr, "UpdateControllerColor"},
+ {222, nullptr, "ConnectUsbPadsAsync"},
+ {223, nullptr, "DisconnectUsbPadsAsync"},
+ {224, nullptr, "UpdateDesignInfo"},
+ {225, nullptr, "GetUniquePadDriverState"},
+ {226, nullptr, "GetSixAxisSensorDriverStates"},
+ {301, nullptr, "GetAbstractedPadHandles"},
+ {302, nullptr, "GetAbstractedPadState"},
+ {303, nullptr, "GetAbstractedPadsState"},
+ {321, nullptr, "SetAutoPilotVirtualPadState"},
+ {322, nullptr, "UnsetAutoPilotVirtualPadState"},
+ {323, nullptr, "UnsetAllAutoPilotVirtualPadState"},
+ {350, nullptr, "AddRegisteredDevice"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class HidSys final : public ServiceFramework<HidSys> {
+public:
+ explicit HidSys() : ServiceFramework{"hid:sys"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {31, nullptr, "SendKeyboardLockKeyEvent"},
+ {101, nullptr, "AcquireHomeButtonEventHandle"},
+ {111, nullptr, "ActivateHomeButton"},
+ {121, nullptr, "AcquireSleepButtonEventHandle"},
+ {131, nullptr, "ActivateSleepButton"},
+ {141, nullptr, "AcquireCaptureButtonEventHandle"},
+ {151, nullptr, "ActivateCaptureButton"},
+ {210, nullptr, "AcquireNfcDeviceUpdateEventHandle"},
+ {211, nullptr, "GetNpadsWithNfc"},
+ {212, nullptr, "AcquireNfcActivateEventHandle"},
+ {213, nullptr, "ActivateNfc"},
+ {214, nullptr, "GetXcdHandleForNpadWithNfc"},
+ {215, nullptr, "IsNfcActivated"},
+ {230, nullptr, "AcquireIrSensorEventHandle"},
+ {231, nullptr, "ActivateIrSensor"},
+ {301, nullptr, "ActivateNpadSystem"},
+ {303, nullptr, "ApplyNpadSystemCommonPolicy"},
+ {304, nullptr, "EnableAssigningSingleOnSlSrPress"},
+ {305, nullptr, "DisableAssigningSingleOnSlSrPress"},
+ {306, nullptr, "GetLastActiveNpad"},
+ {307, nullptr, "GetNpadSystemExtStyle"},
+ {308, nullptr, "ApplyNpadSystemCommonPolicyFull"},
+ {309, nullptr, "GetNpadFullKeyGripColor"},
+ {311, nullptr, "SetNpadPlayerLedBlinkingDevice"},
+ {321, nullptr, "GetUniquePadsFromNpad"},
+ {322, nullptr, "GetIrSensorState"},
+ {323, nullptr, "GetXcdHandleForNpadWithIrSensor"},
+ {500, nullptr, "SetAppletResourceUserId"},
+ {501, nullptr, "RegisterAppletResourceUserId"},
+ {502, nullptr, "UnregisterAppletResourceUserId"},
+ {503, nullptr, "EnableAppletToGetInput"},
+ {504, nullptr, "SetAruidValidForVibration"},
+ {505, nullptr, "EnableAppletToGetSixAxisSensor"},
+ {510, nullptr, "SetVibrationMasterVolume"},
+ {511, nullptr, "GetVibrationMasterVolume"},
+ {512, nullptr, "BeginPermitVibrationSession"},
+ {513, nullptr, "EndPermitVibrationSession"},
+ {520, nullptr, "EnableHandheldHids"},
+ {521, nullptr, "DisableHandheldHids"},
+ {540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"},
+ {541, nullptr, "GetPlayReportControllerUsages"},
+ {542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"},
+ {543, nullptr, "GetRegisteredDevicesOld"},
+ {544, nullptr, "AcquireConnectionTriggerTimeoutEvent"},
+ {545, nullptr, "SendConnectionTrigger"},
+ {546, nullptr, "AcquireDeviceRegisteredEventForControllerSupport"},
+ {547, nullptr, "GetAllowedBluetoothLinksCount"},
+ {548, nullptr, "GetRegisteredDevices"},
+ {700, nullptr, "ActivateUniquePad"},
+ {702, nullptr, "AcquireUniquePadConnectionEventHandle"},
+ {703, nullptr, "GetUniquePadIds"},
+ {751, nullptr, "AcquireJoyDetachOnBluetoothOffEventHandle"},
+ {800, nullptr, "ListSixAxisSensorHandles"},
+ {801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
+ {802, nullptr, "ResetSixAxisSensorCalibrationValues"},
+ {803, nullptr, "StartSixAxisSensorUserCalibration"},
+ {804, nullptr, "CancelSixAxisSensorUserCalibration"},
+ {805, nullptr, "GetUniquePadBluetoothAddress"},
+ {806, nullptr, "DisconnectUniquePad"},
+ {807, nullptr, "GetUniquePadType"},
+ {808, nullptr, "GetUniquePadInterface"},
+ {809, nullptr, "GetUniquePadSerialNumber"},
+ {810, nullptr, "GetUniquePadControllerNumber"},
+ {811, nullptr, "GetSixAxisSensorUserCalibrationStage"},
+ {821, nullptr, "StartAnalogStickManualCalibration"},
+ {822, nullptr, "RetryCurrentAnalogStickManualCalibrationStage"},
+ {823, nullptr, "CancelAnalogStickManualCalibration"},
+ {824, nullptr, "ResetAnalogStickManualCalibration"},
+ {825, nullptr, "GetAnalogStickState"},
+ {826, nullptr, "GetAnalogStickManualCalibrationStage"},
+ {827, nullptr, "IsAnalogStickButtonPressed"},
+ {828, nullptr, "IsAnalogStickInReleasePosition"},
+ {829, nullptr, "IsAnalogStickInCircumference"},
+ {850, nullptr, "IsUsbFullKeyControllerEnabled"},
+ {851, nullptr, "EnableUsbFullKeyController"},
+ {852, nullptr, "IsUsbConnected"},
+ {900, nullptr, "ActivateInputDetector"},
+ {901, nullptr, "NotifyInputDetector"},
+ {1000, nullptr, "InitializeFirmwareUpdate"},
+ {1001, nullptr, "GetFirmwareVersion"},
+ {1002, nullptr, "GetAvailableFirmwareVersion"},
+ {1003, nullptr, "IsFirmwareUpdateAvailable"},
+ {1004, nullptr, "CheckFirmwareUpdateRequired"},
+ {1005, nullptr, "StartFirmwareUpdate"},
+ {1006, nullptr, "AbortFirmwareUpdate"},
+ {1007, nullptr, "GetFirmwareUpdateState"},
+ {1008, nullptr, "ActivateAudioControl"},
+ {1009, nullptr, "AcquireAudioControlEventHandle"},
+ {1010, nullptr, "GetAudioControlStates"},
+ {1011, nullptr, "DeactivateAudioControl"},
+ {1050, nullptr, "IsSixAxisSensorAccurateUserCalibrationSupported"},
+ {1051, nullptr, "StartSixAxisSensorAccurateUserCalibration"},
+ {1052, nullptr, "CancelSixAxisSensorAccurateUserCalibration"},
+ {1053, nullptr, "GetSixAxisSensorAccurateUserCalibrationState"},
+ {1100, nullptr, "GetHidbusSystemServiceObject"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class HidTmp final : public ServiceFramework<HidTmp> {
+public:
+ explicit HidTmp() : ServiceFramework{"hid:tmp"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetConsoleSixAxisSensorCalibrationValues"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class HidBus final : public ServiceFramework<HidBus> {
+public:
+ explicit HidBus() : ServiceFramework{"hidbus"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {1, nullptr, "GetBusHandle"},
+ {2, nullptr, "IsExternalDeviceConnected"},
+ {3, nullptr, "Initialize"},
+ {4, nullptr, "Finalize"},
+ {5, nullptr, "EnableExternalDevice"},
+ {6, nullptr, "GetExternalDeviceId"},
+ {7, nullptr, "SendCommandAsync"},
+ {8, nullptr, "GetSendCommandAsynceResult"},
+ {9, nullptr, "SetEventForSendCommandAsycResult"},
+ {10, nullptr, "GetSharedMemoryHandle"},
+ {11, nullptr, "EnableJoyPollingReceiveMode"},
+ {12, nullptr, "DisableJoyPollingReceiveMode"},
+ {13, nullptr, "GetPollingData"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
void ReloadInputDevices() {}
void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<Hid>()->InstallAsService(service_manager);
+ std::make_shared<HidBus>()->InstallAsService(service_manager);
+ std::make_shared<HidDbg>()->InstallAsService(service_manager);
+ std::make_shared<HidSys>()->InstallAsService(service_manager);
+ std::make_shared<HidTmp>()->InstallAsService(service_manager);
+
+ std::make_shared<IRS>()->InstallAsService(service_manager);
+ std::make_shared<IRS_SYS>()->InstallAsService(service_manager);
+
+ std::make_shared<XCD_SYS>()->InstallAsService(service_manager);
}
} // namespace Service::HID
diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp
new file mode 100644
index 000000000..aaf311912
--- /dev/null
+++ b/src/core/hle/service/hid/irs.cpp
@@ -0,0 +1,49 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/hid/irs.h"
+
+namespace Service::HID {
+
+IRS::IRS() : ServiceFramework{"irs"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {302, nullptr, "ActivateIrsensor"},
+ {303, nullptr, "DeactivateIrsensor"},
+ {304, nullptr, "GetIrsensorSharedMemoryHandle"},
+ {305, nullptr, "StopImageProcessor"},
+ {306, nullptr, "RunMomentProcessor"},
+ {307, nullptr, "RunClusteringProcessor"},
+ {308, nullptr, "RunImageTransferProcessor"},
+ {309, nullptr, "GetImageTransferProcessorState"},
+ {310, nullptr, "RunTeraPluginProcessor"},
+ {311, nullptr, "GetNpadIrCameraHandle"},
+ {312, nullptr, "RunPointingProcessor"},
+ {313, nullptr, "SuspendImageProcessor"},
+ {314, nullptr, "CheckFirmwareVersion"},
+ {315, nullptr, "SetFunctionLevel"},
+ {316, nullptr, "RunImageTransferExProcessor"},
+ {317, nullptr, "RunIrLedProcessor"},
+ {318, nullptr, "StopImageProcessorAsync"},
+ {319, nullptr, "ActivateIrsensorWithFunctionLevel"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IRS_SYS::IRS_SYS() : ServiceFramework{"irs:sys"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {500, nullptr, "SetAppletResourceUserId"},
+ {501, nullptr, "RegisterAppletResourceUserId"},
+ {502, nullptr, "UnregisterAppletResourceUserId"},
+ {503, nullptr, "EnableAppletToGetInput"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/irs.h b/src/core/hle/service/hid/irs.h
new file mode 100644
index 000000000..a8be701c7
--- /dev/null
+++ b/src/core/hle/service/hid/irs.h
@@ -0,0 +1,21 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::HID {
+
+class IRS final : public ServiceFramework<IRS> {
+public:
+ explicit IRS();
+};
+
+class IRS_SYS final : public ServiceFramework<IRS_SYS> {
+public:
+ explicit IRS_SYS();
+};
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/xcd.cpp b/src/core/hle/service/hid/xcd.cpp
new file mode 100644
index 000000000..49f733f60
--- /dev/null
+++ b/src/core/hle/service/hid/xcd.cpp
@@ -0,0 +1,37 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/hid/xcd.h"
+
+namespace Service::HID {
+
+XCD_SYS::XCD_SYS() : ServiceFramework{"xcd:sys"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetDataFormat"},
+ {1, nullptr, "SetDataFormat"},
+ {2, nullptr, "GetMcuState"},
+ {3, nullptr, "SetMcuState"},
+ {4, nullptr, "GetMcuVersionForNfc"},
+ {5, nullptr, "CheckNfcDevicePower"},
+ {10, nullptr, "SetNfcEvent"},
+ {11, nullptr, "GetNfcInfo"},
+ {12, nullptr, "StartNfcDiscovery"},
+ {13, nullptr, "StopNfcDiscovery"},
+ {14, nullptr, "StartNtagRead"},
+ {15, nullptr, "StartNtagWrite"},
+ {16, nullptr, "SendNfcRawData"},
+ {17, nullptr, "RegisterMifareKey"},
+ {18, nullptr, "ClearMifareKey"},
+ {19, nullptr, "StartMifareRead"},
+ {20, nullptr, "StartMifareWrite"},
+ {101, nullptr, "GetAwakeTriggerReasonForLeftRail"},
+ {102, nullptr, "GetAwakeTriggerReasonForRightRail"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/xcd.h b/src/core/hle/service/hid/xcd.h
new file mode 100644
index 000000000..232a044df
--- /dev/null
+++ b/src/core/hle/service/hid/xcd.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::HID {
+
+class XCD_SYS final : public ServiceFramework<XCD_SYS> {
+public:
+ explicit XCD_SYS();
+};
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/lbl/lbl.cpp b/src/core/hle/service/lbl/lbl.cpp
new file mode 100644
index 000000000..8fc8b1057
--- /dev/null
+++ b/src/core/hle/service/lbl/lbl.cpp
@@ -0,0 +1,90 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "common/logging/log.h"
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/service/lbl/lbl.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::LBL {
+
+class LBL final : public ServiceFramework<LBL> {
+public:
+ explicit LBL() : ServiceFramework{"lbl"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown1"},
+ {1, nullptr, "Unknown2"},
+ {2, nullptr, "Unknown3"},
+ {3, nullptr, "Unknown4"},
+ {4, nullptr, "Unknown5"},
+ {5, nullptr, "Unknown6"},
+ {6, nullptr, "TurnOffBacklight"},
+ {7, nullptr, "TurnOnBacklight"},
+ {8, nullptr, "GetBacklightStatus"},
+ {9, nullptr, "Unknown7"},
+ {10, nullptr, "Unknown8"},
+ {11, nullptr, "Unknown9"},
+ {12, nullptr, "Unknown10"},
+ {13, nullptr, "Unknown11"},
+ {14, nullptr, "Unknown12"},
+ {15, nullptr, "Unknown13"},
+ {16, nullptr, "ReadRawLightSensor"},
+ {17, nullptr, "Unknown14"},
+ {18, nullptr, "Unknown15"},
+ {19, nullptr, "Unknown16"},
+ {20, nullptr, "Unknown17"},
+ {21, nullptr, "Unknown18"},
+ {22, nullptr, "Unknown19"},
+ {23, nullptr, "Unknown20"},
+ {24, nullptr, "Unknown21"},
+ {25, nullptr, "Unknown22"},
+ {26, &LBL::EnableVrMode, "EnableVrMode"},
+ {27, &LBL::DisableVrMode, "DisableVrMode"},
+ {28, &LBL::GetVrMode, "GetVrMode"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void EnableVrMode(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+
+ vr_mode_enabled = true;
+
+ LOG_DEBUG(Service_LBL, "called");
+ }
+
+ void DisableVrMode(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+
+ vr_mode_enabled = false;
+
+ LOG_DEBUG(Service_LBL, "called");
+ }
+
+ void GetVrMode(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push(vr_mode_enabled);
+
+ LOG_DEBUG(Service_LBL, "called");
+ }
+
+ bool vr_mode_enabled = false;
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<LBL>()->InstallAsService(sm);
+}
+
+} // namespace Service::LBL
diff --git a/src/core/hle/service/lbl/lbl.h b/src/core/hle/service/lbl/lbl.h
new file mode 100644
index 000000000..bf6f400f8
--- /dev/null
+++ b/src/core/hle/service/lbl/lbl.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::LBL {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::LBL
diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp
new file mode 100644
index 000000000..167f2c66a
--- /dev/null
+++ b/src/core/hle/service/ldn/ldn.cpp
@@ -0,0 +1,142 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/result.h"
+#include "core/hle/service/ldn/ldn.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::LDN {
+
+class IMonitorService final : public ServiceFramework<IMonitorService> {
+public:
+ explicit IMonitorService() : ServiceFramework{"IMonitorService"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetStateForMonitor"},
+ {1, nullptr, "GetNetworkInfoForMonitor"},
+ {2, nullptr, "GetIpv4AddressForMonitor"},
+ {3, nullptr, "GetDisconnectReasonForMonitor"},
+ {4, nullptr, "GetSecurityParameterForMonitor"},
+ {5, nullptr, "GetNetworkConfigForMonitor"},
+ {100, nullptr, "InitializeMonitor"},
+ {101, nullptr, "FinalizeMonitor"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class LDNM final : public ServiceFramework<LDNM> {
+public:
+ explicit LDNM() : ServiceFramework{"ldn:m"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &LDNM::CreateMonitorService, "CreateMonitorService"}
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+ void CreateMonitorService(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IMonitorService>();
+
+ LOG_DEBUG(Service_LDN, "called");
+ }
+};
+
+class ILocalCommunicationService final : public ServiceFramework<ILocalCommunicationService> {
+public:
+ explicit ILocalCommunicationService(const char* name) : ServiceFramework{name} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetState"},
+ {1, nullptr, "GetNetworkInfo"},
+ {2, nullptr, "GetIpv4Address"},
+ {3, nullptr, "GetDisconnectReason"},
+ {4, nullptr, "GetSecurityParameter"},
+ {5, nullptr, "GetNetworkConfig"},
+ {100, nullptr, "AttachStateChangeEvent"},
+ {101, nullptr, "GetNetworkInfoLatestUpdate"},
+ {102, nullptr, "Scan"},
+ {103, nullptr, "ScanPrivate"},
+ {200, nullptr, "OpenAccessPoint"},
+ {201, nullptr, "CloseAccessPoint"},
+ {202, nullptr, "CreateNetwork"},
+ {203, nullptr, "CreateNetworkPrivate"},
+ {204, nullptr, "DestroyNetwork"},
+ {205, nullptr, "Reject"},
+ {206, nullptr, "SetAdvertiseData"},
+ {207, nullptr, "SetStationAcceptPolicy"},
+ {208, nullptr, "AddAcceptFilterEntry"},
+ {209, nullptr, "ClearAcceptFilter"},
+ {300, nullptr, "OpenStation"},
+ {301, nullptr, "CloseStation"},
+ {302, nullptr, "Connect"},
+ {303, nullptr, "ConnectPrivate"},
+ {304, nullptr, "Disconnect"},
+ {400, nullptr, "InitializeSystem"},
+ {401, nullptr, "FinalizeSystem"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class LDNS final : public ServiceFramework<LDNS> {
+public:
+ explicit LDNS() : ServiceFramework{"ldn:s"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &LDNS::CreateSystemLocalCommunicationService, "CreateSystemLocalCommunicationService"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+ void CreateSystemLocalCommunicationService(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<ILocalCommunicationService>("ISystemLocalCommunicationService");
+
+ LOG_DEBUG(Service_LDN, "called");
+ }
+};
+
+class LDNU final : public ServiceFramework<LDNU> {
+public:
+ explicit LDNU() : ServiceFramework{"ldn:u"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &LDNU::CreateUserLocalCommunicationService, "CreateUserLocalCommunicationService"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+ void CreateUserLocalCommunicationService(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<ILocalCommunicationService>("IUserLocalCommunicationService");
+
+ LOG_DEBUG(Service_LDN, "called");
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<LDNM>()->InstallAsService(sm);
+ std::make_shared<LDNS>()->InstallAsService(sm);
+ std::make_shared<LDNU>()->InstallAsService(sm);
+}
+
+} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/ldn.h b/src/core/hle/service/ldn/ldn.h
new file mode 100644
index 000000000..6b2a3c2b2
--- /dev/null
+++ b/src/core/hle/service/ldn/ldn.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::LDN {
+
+/// Registers all LDN services with the specified service manager.
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::LDN
diff --git a/src/core/hle/service/lm/lm.cpp b/src/core/hle/service/lm/lm.cpp
index b497376d7..098da2a41 100644
--- a/src/core/hle/service/lm/lm.cpp
+++ b/src/core/hle/service/lm/lm.cpp
@@ -13,11 +13,11 @@
namespace Service::LM {
-class Logger final : public ServiceFramework<Logger> {
+class ILogger final : public ServiceFramework<ILogger> {
public:
- Logger() : ServiceFramework("Logger") {
+ ILogger() : ServiceFramework("ILogger") {
static const FunctionInfo functions[] = {
- {0x00000000, &Logger::Initialize, "Initialize"},
+ {0x00000000, &ILogger::Initialize, "Initialize"},
{0x00000001, nullptr, "SetDestination"},
};
RegisterHandlers(functions);
@@ -92,7 +92,11 @@ private:
// Parse out log metadata
u32 line{};
- std::string message, filename, function;
+ std::string module;
+ std::string message;
+ std::string filename;
+ std::string function;
+ std::string thread;
while (addr < end_addr) {
const Field field{static_cast<Field>(Memory::Read8(addr++))};
const size_t length{Memory::Read8(addr++)};
@@ -102,6 +106,8 @@ private:
}
switch (field) {
+ case Field::Skip:
+ break;
case Field::Message:
message = Memory::ReadCString(addr, length);
break;
@@ -114,6 +120,12 @@ private:
case Field::Function:
function = Memory::ReadCString(addr, length);
break;
+ case Field::Module:
+ module = Memory::ReadCString(addr, length);
+ break;
+ case Field::Thread:
+ thread = Memory::ReadCString(addr, length);
+ break;
}
addr += length;
@@ -128,12 +140,18 @@ private:
if (!filename.empty()) {
log_stream << filename << ':';
}
+ if (!module.empty()) {
+ log_stream << module << ':';
+ }
if (!function.empty()) {
log_stream << function << ':';
}
if (line) {
log_stream << std::to_string(line) << ':';
}
+ if (!thread.empty()) {
+ log_stream << thread << ':';
+ }
if (log_stream.str().length() > 0 && log_stream.str().back() == ':') {
log_stream << ' ';
}
@@ -142,7 +160,7 @@ private:
if (header.IsTailLog()) {
switch (header.severity) {
case MessageHeader::Severity::Trace:
- LOG_TRACE(Debug_Emulated, "{}", log_stream.str());
+ LOG_DEBUG(Debug_Emulated, "{}", log_stream.str());
break;
case MessageHeader::Severity::Info:
LOG_INFO(Debug_Emulated, "{}", log_stream.str());
@@ -182,7 +200,7 @@ public:
void OpenLogger(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
- rb.PushIpcInterface<Logger>();
+ rb.PushIpcInterface<ILogger>();
LOG_DEBUG(Service_LM, "called");
}
diff --git a/src/core/hle/service/mig/mig.cpp b/src/core/hle/service/mig/mig.cpp
new file mode 100644
index 000000000..d16367f2c
--- /dev/null
+++ b/src/core/hle/service/mig/mig.cpp
@@ -0,0 +1,34 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "core/hle/service/mig/mig.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::Migration {
+
+class MIG_USR final : public ServiceFramework<MIG_USR> {
+public:
+ explicit MIG_USR() : ServiceFramework{"mig:usr"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {10, nullptr, "TryGetLastMigrationInfo"},
+ {100, nullptr, "CreateServer"},
+ {101, nullptr, "ResumeServer"},
+ {200, nullptr, "CreateClient"},
+ {201, nullptr, "ResumeClient"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<MIG_USR>()->InstallAsService(sm);
+}
+
+} // namespace Service::Migration
diff --git a/src/core/hle/service/mig/mig.h b/src/core/hle/service/mig/mig.h
new file mode 100644
index 000000000..288c1c1b3
--- /dev/null
+++ b/src/core/hle/service/mig/mig.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::Migration {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::Migration
diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp
new file mode 100644
index 000000000..a6197124a
--- /dev/null
+++ b/src/core/hle/service/mii/mii.cpp
@@ -0,0 +1,107 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "common/logging/log.h"
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/service/mii/mii.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::Mii {
+
+class IDatabaseService final : public ServiceFramework<IDatabaseService> {
+public:
+ explicit IDatabaseService() : ServiceFramework{"IDatabaseService"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "IsUpdated"},
+ {1, nullptr, "IsFullDatabase"},
+ {2, nullptr, "GetCount"},
+ {3, nullptr, "Get"},
+ {4, nullptr, "Get1"},
+ {5, nullptr, "UpdateLatest"},
+ {6, nullptr, "BuildRandom"},
+ {7, nullptr, "BuildDefault"},
+ {8, nullptr, "Get2"},
+ {9, nullptr, "Get3"},
+ {10, nullptr, "UpdateLatest1"},
+ {11, nullptr, "FindIndex"},
+ {12, nullptr, "Move"},
+ {13, nullptr, "AddOrReplace"},
+ {14, nullptr, "Delete"},
+ {15, nullptr, "DestroyFile"},
+ {16, nullptr, "DeleteFile"},
+ {17, nullptr, "Format"},
+ {18, nullptr, "Import"},
+ {19, nullptr, "Export"},
+ {20, nullptr, "IsBrokenDatabaseWithClearFlag"},
+ {21, nullptr, "GetIndex"},
+ {22, nullptr, "SetInterfaceVersion"},
+ {23, nullptr, "Convert"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class MiiDBModule final : public ServiceFramework<MiiDBModule> {
+public:
+ explicit MiiDBModule(const char* name) : ServiceFramework{name} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void GetDatabaseService(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IDatabaseService>();
+
+ LOG_DEBUG(Service_Mii, "called");
+ }
+};
+
+class MiiImg final : public ServiceFramework<MiiImg> {
+public:
+ explicit MiiImg() : ServiceFramework{"miiimg"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Initialize"},
+ {10, nullptr, "Reload"},
+ {11, nullptr, "GetCount"},
+ {12, nullptr, "IsEmpty"},
+ {13, nullptr, "IsFull"},
+ {14, nullptr, "GetAttribute"},
+ {15, nullptr, "LoadImage"},
+ {16, nullptr, "AddOrUpdateImage"},
+ {17, nullptr, "DeleteImages"},
+ {100, nullptr, "DeleteFile"},
+ {101, nullptr, "DestroyFile"},
+ {102, nullptr, "ImportFile"},
+ {103, nullptr, "ExportFile"},
+ {104, nullptr, "ForceInitialize"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<MiiDBModule>("mii:e")->InstallAsService(sm);
+ std::make_shared<MiiDBModule>("mii:u")->InstallAsService(sm);
+
+ std::make_shared<MiiImg>()->InstallAsService(sm);
+}
+
+} // namespace Service::Mii
diff --git a/src/core/hle/service/mii/mii.h b/src/core/hle/service/mii/mii.h
new file mode 100644
index 000000000..7ce9be50e
--- /dev/null
+++ b/src/core/hle/service/mii/mii.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::Mii {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::Mii
diff --git a/src/core/hle/service/mm/mm_u.cpp b/src/core/hle/service/mm/mm_u.cpp
index 08f45b78a..7b91bb258 100644
--- a/src/core/hle/service/mm/mm_u.cpp
+++ b/src/core/hle/service/mm/mm_u.cpp
@@ -9,42 +9,63 @@
namespace Service::MM {
-void InstallInterfaces(SM::ServiceManager& service_manager) {
- std::make_shared<MM_U>()->InstallAsService(service_manager);
-}
+class MM_U final : public ServiceFramework<MM_U> {
+public:
+ explicit MM_U() : ServiceFramework{"mm:u"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &MM_U::Initialize, "InitializeOld"},
+ {1, &MM_U::Finalize, "FinalizeOld"},
+ {2, &MM_U::SetAndWait, "SetAndWaitOld"},
+ {3, &MM_U::Get, "GetOld"},
+ {4, &MM_U::Initialize, "Initialize"},
+ {5, &MM_U::Finalize, "Finalize"},
+ {6, &MM_U::SetAndWait, "SetAndWait"},
+ {7, &MM_U::Get, "Get"},
+ };
+ // clang-format on
-void MM_U::Initialize(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_MM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(RESULT_SUCCESS);
-}
+ RegisterHandlers(functions);
+ }
-void MM_U::SetAndWait(Kernel::HLERequestContext& ctx) {
- IPC::RequestParser rp{ctx};
- min = rp.Pop<u32>();
- max = rp.Pop<u32>();
- current = min;
+private:
+ void Initialize(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_MM, "(STUBBED) called");
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ }
- LOG_WARNING(Service_MM, "(STUBBED) called, min=0x{:X}, max=0x{:X}", min, max);
- IPC::ResponseBuilder rb{ctx, 2};
- rb.Push(RESULT_SUCCESS);
-}
+ void Finalize(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_MM, "(STUBBED) called");
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ }
-void MM_U::Get(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_MM, "(STUBBED) called");
- IPC::ResponseBuilder rb{ctx, 3};
- rb.Push(RESULT_SUCCESS);
- rb.Push(current);
-}
+ void SetAndWait(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ min = rp.Pop<u32>();
+ max = rp.Pop<u32>();
+ current = min;
-MM_U::MM_U() : ServiceFramework("mm:u") {
- static const FunctionInfo functions[] = {
- {0, nullptr, "InitializeOld"}, {1, nullptr, "FinalizeOld"},
- {2, nullptr, "SetAndWaitOld"}, {3, nullptr, "GetOld"},
- {4, &MM_U::Initialize, "Initialize"}, {5, nullptr, "Finalize"},
- {6, &MM_U::SetAndWait, "SetAndWait"}, {7, &MM_U::Get, "Get"},
- };
- RegisterHandlers(functions);
+ LOG_WARNING(Service_MM, "(STUBBED) called, min=0x{:X}, max=0x{:X}", min, max);
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ }
+
+ void Get(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_MM, "(STUBBED) called");
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push(current);
+ }
+
+ u32 min{0};
+ u32 max{0};
+ u32 current{0};
+};
+
+void InstallInterfaces(SM::ServiceManager& service_manager) {
+ std::make_shared<MM_U>()->InstallAsService(service_manager);
}
} // namespace Service::MM
diff --git a/src/core/hle/service/mm/mm_u.h b/src/core/hle/service/mm/mm_u.h
index 79eeedf9c..5439fa653 100644
--- a/src/core/hle/service/mm/mm_u.h
+++ b/src/core/hle/service/mm/mm_u.h
@@ -8,21 +8,6 @@
namespace Service::MM {
-class MM_U final : public ServiceFramework<MM_U> {
-public:
- MM_U();
- ~MM_U() = default;
-
-private:
- void Initialize(Kernel::HLERequestContext& ctx);
- void SetAndWait(Kernel::HLERequestContext& ctx);
- void Get(Kernel::HLERequestContext& ctx);
-
- u32 min{0};
- u32 max{0};
- u32 current{0};
-};
-
/// Registers all MM services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
diff --git a/src/core/hle/service/ncm/ncm.cpp b/src/core/hle/service/ncm/ncm.cpp
new file mode 100644
index 000000000..0297edca0
--- /dev/null
+++ b/src/core/hle/service/ncm/ncm.cpp
@@ -0,0 +1,59 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "core/hle/service/ncm/ncm.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::NCM {
+
+class LocationResolver final : public ServiceFramework<LocationResolver> {
+public:
+ explicit LocationResolver() : ServiceFramework{"lr"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "OpenLocationResolver"},
+ {1, nullptr, "OpenRegisteredLocationResolver"},
+ {2, nullptr, "RefreshLocationResolver"},
+ {3, nullptr, "OpenAddOnContentLocationResolver"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class NCM final : public ServiceFramework<NCM> {
+public:
+ explicit NCM() : ServiceFramework{"ncm"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "CreateContentStorage"},
+ {1, nullptr, "CreateContentMetaDatabase"},
+ {2, nullptr, "VerifyContentStorage"},
+ {3, nullptr, "VerifyContentMetaDatabase"},
+ {4, nullptr, "OpenContentStorage"},
+ {5, nullptr, "OpenContentMetaDatabase"},
+ {6, nullptr, "CloseContentStorageForcibly"},
+ {7, nullptr, "CloseContentMetaDatabaseForcibly"},
+ {8, nullptr, "CleanupContentMetaDatabase"},
+ {9, nullptr, "OpenContentStorage2"},
+ {10, nullptr, "CloseContentStorage"},
+ {11, nullptr, "OpenContentMetaDatabase2"},
+ {12, nullptr, "CloseContentMetaDatabase"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<LocationResolver>()->InstallAsService(sm);
+ std::make_shared<NCM>()->InstallAsService(sm);
+}
+
+} // namespace Service::NCM
diff --git a/src/core/hle/service/ncm/ncm.h b/src/core/hle/service/ncm/ncm.h
new file mode 100644
index 000000000..7bc8518a6
--- /dev/null
+++ b/src/core/hle/service/ncm/ncm.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::NCM {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::NCM
diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp
new file mode 100644
index 000000000..8fec97db8
--- /dev/null
+++ b/src/core/hle/service/nfc/nfc.cpp
@@ -0,0 +1,222 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "common/logging/log.h"
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/service/nfc/nfc.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::NFC {
+
+class IAm final : public ServiceFramework<IAm> {
+public:
+ explicit IAm() : ServiceFramework{"IAm"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Initialize"},
+ {1, nullptr, "Finalize"},
+ {2, nullptr, "NotifyForegroundApplet"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class NFC_AM final : public ServiceFramework<NFC_AM> {
+public:
+ explicit NFC_AM() : ServiceFramework{"nfc:am"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &NFC_AM::CreateAmInterface, "CreateAmInterface"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void CreateAmInterface(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IAm>();
+
+ LOG_DEBUG(Service_NFC, "called");
+ }
+};
+
+class MFIUser final : public ServiceFramework<MFIUser> {
+public:
+ explicit MFIUser() : ServiceFramework{"IUser"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Initialize"},
+ {1, nullptr, "Finalize"},
+ {2, nullptr, "ListDevices"},
+ {3, nullptr, "StartDetection"},
+ {4, nullptr, "StopDetection"},
+ {5, nullptr, "Read"},
+ {6, nullptr, "Write"},
+ {7, nullptr, "GetTagInfo"},
+ {8, nullptr, "GetActivateEventHandle"},
+ {9, nullptr, "GetDeactivateEventHandle"},
+ {10, nullptr, "GetState"},
+ {11, nullptr, "GetDeviceState"},
+ {12, nullptr, "GetNpadId"},
+ {13, nullptr, "GetAvailabilityChangeEventHandle"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class NFC_MF_U final : public ServiceFramework<NFC_MF_U> {
+public:
+ explicit NFC_MF_U() : ServiceFramework{"nfc:mf:u"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &NFC_MF_U::CreateUserInterface, "CreateUserInterface"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void CreateUserInterface(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<MFIUser>();
+
+ LOG_DEBUG(Service_NFC, "called");
+ }
+};
+
+class IUser final : public ServiceFramework<IUser> {
+public:
+ explicit IUser() : ServiceFramework{"IUser"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Initialize"},
+ {1, nullptr, "Finalize"},
+ {2, nullptr, "GetState"},
+ {3, nullptr, "IsNfcEnabled"},
+ {400, nullptr, "Initialize"},
+ {401, nullptr, "Finalize"},
+ {402, nullptr, "GetState"},
+ {403, nullptr, "IsNfcEnabled"},
+ {404, nullptr, "ListDevices"},
+ {405, nullptr, "GetDeviceState"},
+ {406, nullptr, "GetNpadId"},
+ {407, nullptr, "AttachAvailabilityChangeEvent"},
+ {408, nullptr, "StartDetection"},
+ {409, nullptr, "StopDetection"},
+ {410, nullptr, "GetTagInfo"},
+ {411, nullptr, "AttachActivateEvent"},
+ {412, nullptr, "AttachDeactivateEvent"},
+ {1000, nullptr, "ReadMifare"},
+ {1001, nullptr, "WriteMifare"},
+ {1300, nullptr, "SendCommandByPassThrough"},
+ {1301, nullptr, "KeepPassThroughSession"},
+ {1302, nullptr, "ReleasePassThroughSession"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class NFC_U final : public ServiceFramework<NFC_U> {
+public:
+ explicit NFC_U() : ServiceFramework{"nfc:u"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &NFC_U::CreateUserInterface, "CreateUserInterface"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void CreateUserInterface(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IUser>();
+
+ LOG_DEBUG(Service_NFC, "called");
+ }
+};
+
+class ISystem final : public ServiceFramework<ISystem> {
+public:
+ explicit ISystem() : ServiceFramework{"ISystem"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Initialize"},
+ {1, nullptr, "Finalize"},
+ {2, nullptr, "GetState"},
+ {3, nullptr, "IsNfcEnabled"},
+ {100, nullptr, "SetNfcEnabled"},
+ {400, nullptr, "InitializeSystem"},
+ {401, nullptr, "FinalizeSystem"},
+ {402, nullptr, "GetState"},
+ {403, nullptr, "IsNfcEnabled"},
+ {404, nullptr, "ListDevices"},
+ {405, nullptr, "GetDeviceState"},
+ {406, nullptr, "GetNpadId"},
+ {407, nullptr, "AttachAvailabilityChangeEvent"},
+ {408, nullptr, "StartDetection"},
+ {409, nullptr, "StopDetection"},
+ {410, nullptr, "GetTagInfo"},
+ {411, nullptr, "AttachActivateEvent"},
+ {412, nullptr, "AttachDeactivateEvent"},
+ {500, nullptr, "SetNfcEnabled"},
+ {1000, nullptr, "ReadMifare"},
+ {1001, nullptr, "WriteMifare"},
+ {1300, nullptr, "SendCommandByPassThrough"},
+ {1301, nullptr, "KeepPassThroughSession"},
+ {1302, nullptr, "ReleasePassThroughSession"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class NFC_SYS final : public ServiceFramework<NFC_SYS> {
+public:
+ explicit NFC_SYS() : ServiceFramework{"nfc:sys"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &NFC_SYS::CreateSystemInterface, "CreateSystemInterface"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void CreateSystemInterface(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<ISystem>();
+
+ LOG_DEBUG(Service_NFC, "called");
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<NFC_AM>()->InstallAsService(sm);
+ std::make_shared<NFC_MF_U>()->InstallAsService(sm);
+ std::make_shared<NFC_U>()->InstallAsService(sm);
+ std::make_shared<NFC_SYS>()->InstallAsService(sm);
+}
+
+} // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/nfc.h b/src/core/hle/service/nfc/nfc.h
new file mode 100644
index 000000000..4d2d815f9
--- /dev/null
+++ b/src/core/hle/service/nfc/nfc.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::NFC {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::NFC
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp
new file mode 100644
index 000000000..bd05b0a70
--- /dev/null
+++ b/src/core/hle/service/nim/nim.cpp
@@ -0,0 +1,124 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/nim/nim.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::NIM {
+
+class NIM final : public ServiceFramework<NIM> {
+public:
+ explicit NIM() : ServiceFramework{"nim"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "CreateSystemUpdateTask"},
+ {1, nullptr, "DestroySystemUpdateTask"},
+ {2, nullptr, "ListSystemUpdateTask"},
+ {3, nullptr, "RequestSystemUpdateTaskRun"},
+ {4, nullptr, "GetSystemUpdateTaskInfo"},
+ {5, nullptr, "CommitSystemUpdateTask"},
+ {6, nullptr, "CreateNetworkInstallTask"},
+ {7, nullptr, "DestroyNetworkInstallTask"},
+ {8, nullptr, "ListNetworkInstallTask"},
+ {9, nullptr, "RequestNetworkInstallTaskRun"},
+ {10, nullptr, "GetNetworkInstallTaskInfo"},
+ {11, nullptr, "CommitNetworkInstallTask"},
+ {12, nullptr, "RequestLatestSystemUpdateMeta"},
+ {14, nullptr, "ListApplicationNetworkInstallTask"},
+ {15, nullptr, "ListNetworkInstallTaskContentMeta"},
+ {16, nullptr, "RequestLatestVersion"},
+ {17, nullptr, "SetNetworkInstallTaskAttribute"},
+ {18, nullptr, "AddNetworkInstallTaskContentMeta"},
+ {19, nullptr, "GetDownloadedSystemDataPath"},
+ {20, nullptr, "CalculateNetworkInstallTaskRequiredSize"},
+ {21, nullptr, "IsExFatDriverIncluded"},
+ {22, nullptr, "GetBackgroundDownloadStressTaskInfo"},
+ {23, nullptr, "RequestDeviceAuthenticationToken"},
+ {24, nullptr, "RequestGameCardRegistrationStatus"},
+ {25, nullptr, "RequestRegisterGameCard"},
+ {26, nullptr, "RequestRegisterNotificationToken"},
+ {27, nullptr, "RequestDownloadTaskList"},
+ {28, nullptr, "RequestApplicationControl"},
+ {29, nullptr, "RequestLatestApplicationControl"},
+ {30, nullptr, "RequestVersionList"},
+ {31, nullptr, "CreateApplyDeltaTask"},
+ {32, nullptr, "DestroyApplyDeltaTask"},
+ {33, nullptr, "ListApplicationApplyDeltaTask"},
+ {34, nullptr, "RequestApplyDeltaTaskRun"},
+ {35, nullptr, "GetApplyDeltaTaskInfo"},
+ {36, nullptr, "ListApplyDeltaTask"},
+ {37, nullptr, "CommitApplyDeltaTask"},
+ {38, nullptr, "CalculateApplyDeltaTaskRequiredSize"},
+ {39, nullptr, "PrepareShutdown"},
+ {40, nullptr, "ListApplyDeltaTask"},
+ {41, nullptr, "ClearNotEnoughSpaceStateOfApplyDeltaTask"},
+ {42, nullptr, "Unknown1"},
+ {43, nullptr, "Unknown2"},
+ {44, nullptr, "Unknown3"},
+ {45, nullptr, "Unknown4"},
+ {46, nullptr, "Unknown5"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class NIM_SHP final : public ServiceFramework<NIM_SHP> {
+public:
+ explicit NIM_SHP() : ServiceFramework{"nim:shp"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RequestDeviceAuthenticationToken"},
+ {1, nullptr, "RequestCachedDeviceAuthenticationToken"},
+ {100, nullptr, "RequestRegisterDeviceAccount"},
+ {101, nullptr, "RequestUnregisterDeviceAccount"},
+ {102, nullptr, "RequestDeviceAccountStatus"},
+ {103, nullptr, "GetDeviceAccountInfo"},
+ {104, nullptr, "RequestDeviceRegistrationInfo"},
+ {105, nullptr, "RequestTransferDeviceAccount"},
+ {106, nullptr, "RequestSyncRegistration"},
+ {107, nullptr, "IsOwnDeviceId"},
+ {200, nullptr, "RequestRegisterNotificationToken"},
+ {300, nullptr, "RequestUnlinkDevice"},
+ {301, nullptr, "RequestUnlinkDeviceIntegrated"},
+ {302, nullptr, "RequestLinkDevice"},
+ {303, nullptr, "HasDeviceLink"},
+ {304, nullptr, "RequestUnlinkDeviceAll"},
+ {305, nullptr, "RequestCreateVirtualAccount"},
+ {306, nullptr, "RequestDeviceLinkStatus"},
+ {400, nullptr, "GetAccountByVirtualAccount"},
+ {500, nullptr, "RequestSyncTicket"},
+ {501, nullptr, "RequestDownloadTicket"},
+ {502, nullptr, "RequestDownloadTicketForPrepurchasedContents"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class NTC final : public ServiceFramework<NTC> {
+public:
+ explicit NTC() : ServiceFramework{"ntc"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "OpenEnsureNetworkClockAvailabilityService"},
+ {100, nullptr, "SuspendAutonomicTimeCorrection"},
+ {101, nullptr, "ResumeAutonomicTimeCorrection"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<NIM>()->InstallAsService(sm);
+ std::make_shared<NIM_SHP>()->InstallAsService(sm);
+ std::make_shared<NTC>()->InstallAsService(sm);
+}
+
+} // namespace Service::NIM
diff --git a/src/core/hle/service/nim/nim.h b/src/core/hle/service/nim/nim.h
new file mode 100644
index 000000000..2a2a92df0
--- /dev/null
+++ b/src/core/hle/service/nim/nim.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::NIM {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::NIM
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp
index 89c703310..98017267c 100644
--- a/src/core/hle/service/ns/ns.cpp
+++ b/src/core/hle/service/ns/ns.cpp
@@ -2,12 +2,459 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/service/ns/ns.h"
#include "core/hle/service/ns/pl_u.h"
namespace Service::NS {
+class IAccountProxyInterface final : public ServiceFramework<IAccountProxyInterface> {
+public:
+ explicit IAccountProxyInterface() : ServiceFramework{"IAccountProxyInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "CreateUserAccount"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> {
+public:
+ explicit IApplicationManagerInterface() : ServiceFramework{"IApplicationManagerInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "ListApplicationRecord"},
+ {1, nullptr, "GenerateApplicationRecordCount"},
+ {2, nullptr, "GetApplicationRecordUpdateSystemEvent"},
+ {3, nullptr, "GetApplicationViewDeprecated"},
+ {4, nullptr, "DeleteApplicationEntity"},
+ {5, nullptr, "DeleteApplicationCompletely"},
+ {6, nullptr, "IsAnyApplicationEntityRedundant"},
+ {7, nullptr, "DeleteRedundantApplicationEntity"},
+ {8, nullptr, "IsApplicationEntityMovable"},
+ {9, nullptr, "MoveApplicationEntity"},
+ {11, nullptr, "CalculateApplicationOccupiedSize"},
+ {16, nullptr, "PushApplicationRecord"},
+ {17, nullptr, "ListApplicationRecordContentMeta"},
+ {19, nullptr, "LaunchApplication"},
+ {21, nullptr, "GetApplicationContentPath"},
+ {22, nullptr, "TerminateApplication"},
+ {23, nullptr, "ResolveApplicationContentPath"},
+ {26, nullptr, "BeginInstallApplication"},
+ {27, nullptr, "DeleteApplicationRecord"},
+ {30, nullptr, "RequestApplicationUpdateInfo"},
+ {32, nullptr, "CancelApplicationDownload"},
+ {33, nullptr, "ResumeApplicationDownload"},
+ {35, nullptr, "UpdateVersionList"},
+ {36, nullptr, "PushLaunchVersion"},
+ {37, nullptr, "ListRequiredVersion"},
+ {38, nullptr, "CheckApplicationLaunchVersion"},
+ {39, nullptr, "CheckApplicationLaunchRights"},
+ {40, nullptr, "GetApplicationLogoData"},
+ {41, nullptr, "CalculateApplicationDownloadRequiredSize"},
+ {42, nullptr, "CleanupSdCard"},
+ {43, nullptr, "CheckSdCardMountStatus"},
+ {44, nullptr, "GetSdCardMountStatusChangedEvent"},
+ {45, nullptr, "GetGameCardAttachmentEvent"},
+ {46, nullptr, "GetGameCardAttachmentInfo"},
+ {47, nullptr, "GetTotalSpaceSize"},
+ {48, nullptr, "GetFreeSpaceSize"},
+ {49, nullptr, "GetSdCardRemovedEvent"},
+ {52, nullptr, "GetGameCardUpdateDetectionEvent"},
+ {53, nullptr, "DisableApplicationAutoDelete"},
+ {54, nullptr, "EnableApplicationAutoDelete"},
+ {55, nullptr, "GetApplicationDesiredLanguage"},
+ {56, nullptr, "SetApplicationTerminateResult"},
+ {57, nullptr, "ClearApplicationTerminateResult"},
+ {58, nullptr, "GetLastSdCardMountUnexpectedResult"},
+ {59, nullptr, "ConvertApplicationLanguageToLanguageCode"},
+ {60, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
+ {61, nullptr, "GetBackgroundDownloadStressTaskInfo"},
+ {62, nullptr, "GetGameCardStopper"},
+ {63, nullptr, "IsSystemProgramInstalled"},
+ {64, nullptr, "StartApplyDeltaTask"},
+ {65, nullptr, "GetRequestServerStopper"},
+ {66, nullptr, "GetBackgroundApplyDeltaStressTaskInfo"},
+ {67, nullptr, "CancelApplicationApplyDelta"},
+ {68, nullptr, "ResumeApplicationApplyDelta"},
+ {69, nullptr, "CalculateApplicationApplyDeltaRequiredSize"},
+ {70, nullptr, "ResumeAll"},
+ {71, nullptr, "GetStorageSize"},
+ {80, nullptr, "RequestDownloadApplication"},
+ {81, nullptr, "RequestDownloadAddOnContent"},
+ {82, nullptr, "DownloadApplication"},
+ {83, nullptr, "CheckApplicationResumeRights"},
+ {84, nullptr, "GetDynamicCommitEvent"},
+ {85, nullptr, "RequestUpdateApplication2"},
+ {86, nullptr, "EnableApplicationCrashReport"},
+ {87, nullptr, "IsApplicationCrashReportEnabled"},
+ {90, nullptr, "BoostSystemMemoryResourceLimit"},
+ {100, nullptr, "ResetToFactorySettings"},
+ {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"},
+ {102, nullptr, "ResetToFactorySettingsForRefurbishment"},
+ {200, nullptr, "CalculateUserSaveDataStatistics"},
+ {201, nullptr, "DeleteUserSaveDataAll"},
+ {210, nullptr, "DeleteUserSystemSaveData"},
+ {220, nullptr, "UnregisterNetworkServiceAccount"},
+ {300, nullptr, "GetApplicationShellEvent"},
+ {301, nullptr, "PopApplicationShellEventInfo"},
+ {302, nullptr, "LaunchLibraryApplet"},
+ {303, nullptr, "TerminateLibraryApplet"},
+ {304, nullptr, "LaunchSystemApplet"},
+ {305, nullptr, "TerminateSystemApplet"},
+ {306, nullptr, "LaunchOverlayApplet"},
+ {307, nullptr, "TerminateOverlayApplet"},
+ {400, nullptr, "GetApplicationControlData"},
+ {401, nullptr, "InvalidateAllApplicationControlCache"},
+ {402, nullptr, "RequestDownloadApplicationControlData"},
+ {403, nullptr, "GetMaxApplicationControlCacheCount"},
+ {404, nullptr, "InvalidateApplicationControlCache"},
+ {405, nullptr, "ListApplicationControlCacheEntryInfo"},
+ {502, nullptr, "RequestCheckGameCardRegistration"},
+ {503, nullptr, "RequestGameCardRegistrationGoldPoint"},
+ {504, nullptr, "RequestRegisterGameCard"},
+ {505, nullptr, "GetGameCardMountFailureEvent"},
+ {506, nullptr, "IsGameCardInserted"},
+ {507, nullptr, "EnsureGameCardAccess"},
+ {508, nullptr, "GetLastGameCardMountFailureResult"},
+ {509, nullptr, "ListApplicationIdOnGameCard"},
+ {600, nullptr, "CountApplicationContentMeta"},
+ {601, nullptr, "ListApplicationContentMetaStatus"},
+ {602, nullptr, "ListAvailableAddOnContent"},
+ {603, nullptr, "GetOwnedApplicationContentMetaStatus"},
+ {604, nullptr, "RegisterContentsExternalKey"},
+ {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
+ {606, nullptr, "GetContentMetaStorage"},
+ {700, nullptr, "PushDownloadTaskList"},
+ {701, nullptr, "ClearTaskStatusList"},
+ {702, nullptr, "RequestDownloadTaskList"},
+ {703, nullptr, "RequestEnsureDownloadTask"},
+ {704, nullptr, "ListDownloadTaskStatus"},
+ {705, nullptr, "RequestDownloadTaskListData"},
+ {800, nullptr, "RequestVersionList"},
+ {801, nullptr, "ListVersionList"},
+ {802, nullptr, "RequestVersionListData"},
+ {900, nullptr, "GetApplicationRecord"},
+ {901, nullptr, "GetApplicationRecordProperty"},
+ {902, nullptr, "EnableApplicationAutoUpdate"},
+ {903, nullptr, "DisableApplicationAutoUpdate"},
+ {904, nullptr, "TouchApplication"},
+ {905, nullptr, "RequestApplicationUpdate"},
+ {906, nullptr, "IsApplicationUpdateRequested"},
+ {907, nullptr, "WithdrawApplicationUpdateRequest"},
+ {908, nullptr, "ListApplicationRecordInstalledContentMeta"},
+ {909, nullptr, "WithdrawCleanupAddOnContentsWithNoRightsRecommendation"},
+ {1000, nullptr, "RequestVerifyApplicationDeprecated"},
+ {1001, nullptr, "CorruptApplicationForDebug"},
+ {1002, nullptr, "RequestVerifyAddOnContentsRights"},
+ {1003, nullptr, "RequestVerifyApplication"},
+ {1004, nullptr, "CorruptContentForDebug"},
+ {1200, nullptr, "NeedsUpdateVulnerability"},
+ {1300, nullptr, "IsAnyApplicationEntityInstalled"},
+ {1301, nullptr, "DeleteApplicationContentEntities"},
+ {1302, nullptr, "CleanupUnrecordedApplicationEntity"},
+ {1303, nullptr, "CleanupAddOnContentsWithNoRights"},
+ {1304, nullptr, "DeleteApplicationContentEntity"},
+ {1305, nullptr, "TryDeleteRunningApplicationEntity"},
+ {1306, nullptr, "TryDeleteRunningApplicationCompletely"},
+ {1307, nullptr, "TryDeleteRunningApplicationContentEntities"},
+ {1400, nullptr, "PrepareShutdown"},
+ {1500, nullptr, "FormatSdCard"},
+ {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"},
+ {1502, nullptr, "GetLastSdCardFormatUnexpectedResult"},
+ {1504, nullptr, "InsertSdCard"},
+ {1505, nullptr, "RemoveSdCard"},
+ {1600, nullptr, "GetSystemSeedForPseudoDeviceId"},
+ {1601, nullptr, "ResetSystemSeedForPseudoDeviceId"},
+ {1700, nullptr, "ListApplicationDownloadingContentMeta"},
+ {1701, nullptr, "GetApplicationView"},
+ {1702, nullptr, "GetApplicationDownloadTaskStatus"},
+ {1703, nullptr, "GetApplicationViewDownloadErrorContext"},
+ {1800, nullptr, "IsNotificationSetupCompleted"},
+ {1801, nullptr, "GetLastNotificationInfoCount"},
+ {1802, nullptr, "ListLastNotificationInfo"},
+ {1803, nullptr, "ListNotificationTask"},
+ {1900, nullptr, "IsActiveAccount"},
+ {1901, nullptr, "RequestDownloadApplicationPrepurchasedRights"},
+ {1902, nullptr, "GetApplicationTicketInfo"},
+ {2000, nullptr, "GetSystemDeliveryInfo"},
+ {2001, nullptr, "SelectLatestSystemDeliveryInfo"},
+ {2002, nullptr, "VerifyDeliveryProtocolVersion"},
+ {2003, nullptr, "GetApplicationDeliveryInfo"},
+ {2004, nullptr, "HasAllContentsToDeliver"},
+ {2005, nullptr, "CompareApplicationDeliveryInfo"},
+ {2006, nullptr, "CanDeliverApplication"},
+ {2007, nullptr, "ListContentMetaKeyToDeliverApplication"},
+ {2008, nullptr, "NeedsSystemUpdateToDeliverApplication"},
+ {2009, nullptr, "EstimateRequiredSize"},
+ {2010, nullptr, "RequestReceiveApplication"},
+ {2011, nullptr, "CommitReceiveApplication"},
+ {2012, nullptr, "GetReceiveApplicationProgress"},
+ {2013, nullptr, "RequestSendApplication"},
+ {2014, nullptr, "GetSendApplicationProgress"},
+ {2015, nullptr, "CompareSystemDeliveryInfo"},
+ {2016, nullptr, "ListNotCommittedContentMeta"},
+ {2017, nullptr, "CreateDownloadTask"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> {
+public:
+ explicit IApplicationVersionInterface() : ServiceFramework{"IApplicationVersionInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetLaunchRequiredVersion"},
+ {1, nullptr, "UpgradeLaunchRequiredVersion"},
+ {35, nullptr, "UpdateVersionList"},
+ {36, nullptr, "PushLaunchVersion"},
+ {37, nullptr, "ListRequiredVersion"},
+ {800, nullptr, "RequestVersionList"},
+ {801, nullptr, "ListVersionList"},
+ {802, nullptr, "RequestVersionListData"},
+ {1000, nullptr, "PerformAutoUpdate"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class IContentManagerInterface final : public ServiceFramework<IContentManagerInterface> {
+public:
+ explicit IContentManagerInterface() : ServiceFramework{"IContentManagerInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {11, nullptr, "CalculateApplicationOccupiedSize"},
+ {43, nullptr, "CheckSdCardMountStatus"},
+ {47, nullptr, "GetTotalSpaceSize"},
+ {48, nullptr, "GetFreeSpaceSize"},
+ {600, nullptr, "CountApplicationContentMeta"},
+ {601, nullptr, "ListApplicationContentMetaStatus"},
+ {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
+ {607, nullptr, "IsAnyApplicationRunning"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class IDocumentInterface final : public ServiceFramework<IDocumentInterface> {
+public:
+ explicit IDocumentInterface() : ServiceFramework{"IDocumentInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {21, nullptr, "GetApplicationContentPath"},
+ {23, nullptr, "ResolveApplicationContentPath"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterface> {
+public:
+ explicit IDownloadTaskInterface() : ServiceFramework{"IDownloadTaskInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {701, nullptr, "ClearTaskStatusList"},
+ {702, nullptr, "RequestDownloadTaskList"},
+ {703, nullptr, "RequestEnsureDownloadTask"},
+ {704, nullptr, "ListDownloadTaskStatus"},
+ {705, nullptr, "RequestDownloadTaskListData"},
+ {706, nullptr, "TryCommitCurrentApplicationDownloadTask"},
+ {707, nullptr, "EnableAutoCommit"},
+ {708, nullptr, "DisableAutoCommit"},
+ {709, nullptr, "TriggerDynamicCommitEvent"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class IECommerceInterface final : public ServiceFramework<IECommerceInterface> {
+public:
+ explicit IECommerceInterface() : ServiceFramework{"IECommerceInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RequestLinkDevice"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class IFactoryResetInterface final : public ServiceFramework<IFactoryResetInterface> {
+public:
+ explicit IFactoryResetInterface() : ServiceFramework{"IFactoryResetInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {100, nullptr, "ResetToFactorySettings"},
+ {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"},
+ {102, nullptr, "ResetToFactorySettingsForRefurbishment "},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class NS final : public ServiceFramework<NS> {
+public:
+ explicit NS(const char* name) : ServiceFramework{name} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"},
+ {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"},
+ {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"},
+ {7995, &NS::PushInterface<IAccountProxyInterface>, "GetAccountProxyInterface"},
+ {7996, &NS::PushInterface<IApplicationManagerInterface>, "GetApplicationManagerInterface"},
+ {7997, &NS::PushInterface<IDownloadTaskInterface>, "GetDownloadTaskInterface"},
+ {7998, &NS::PushInterface<IContentManagerInterface>, "GetContentManagementInterface"},
+ {7999, &NS::PushInterface<IDocumentInterface>, "GetDocumentInterface"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ template <typename T>
+ void PushInterface(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<T>();
+
+ LOG_DEBUG(Service_NS, "called");
+ }
+};
+
+class NS_DEV final : public ServiceFramework<NS_DEV> {
+public:
+ explicit NS_DEV() : ServiceFramework{"ns:dev"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "LaunchProgram"},
+ {1, nullptr, "TerminateProcess"},
+ {2, nullptr, "TerminateProgram"},
+ {3, nullptr, "GetShellEventHandle"},
+ {4, nullptr, "GetShellEventInfo"},
+ {5, nullptr, "TerminateApplication"},
+ {6, nullptr, "PrepareLaunchProgramFromHost"},
+ {7, nullptr, "LaunchApplication"},
+ {8, nullptr, "LaunchApplicationWithStorageId"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class ISystemUpdateControl final : public ServiceFramework<ISystemUpdateControl> {
+public:
+ explicit ISystemUpdateControl() : ServiceFramework{"ISystemUpdateControl"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "HasDownloaded"},
+ {1, nullptr, "RequestCheckLatestUpdate"},
+ {2, nullptr, "RequestDownloadLatestUpdate"},
+ {3, nullptr, "GetDownloadProgress"},
+ {4, nullptr, "ApplyDownloadedUpdate"},
+ {5, nullptr, "RequestPrepareCardUpdate"},
+ {6, nullptr, "GetPrepareCardUpdateProgress"},
+ {7, nullptr, "HasPreparedCardUpdate"},
+ {8, nullptr, "ApplyCardUpdate"},
+ {9, nullptr, "GetDownloadedEulaDataSize"},
+ {10, nullptr, "GetDownloadedEulaData"},
+ {11, nullptr, "SetupCardUpdate"},
+ {12, nullptr, "GetPreparedCardUpdateEulaDataSize"},
+ {13, nullptr, "GetPreparedCardUpdateEulaData"},
+ {14, nullptr, "SetupCardUpdateViaSystemUpdater"},
+ {15, nullptr, "HasReceived"},
+ {16, nullptr, "RequestReceiveSystemUpdate"},
+ {17, nullptr, "GetReceiveProgress"},
+ {18, nullptr, "ApplyReceivedUpdate"},
+ {19, nullptr, "GetReceivedEulaDataSize"},
+ {20, nullptr, "GetReceivedEulaData"},
+ {21, nullptr, "SetupToReceiveSystemUpdate"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class NS_SU final : public ServiceFramework<NS_SU> {
+public:
+ explicit NS_SU() : ServiceFramework{"ns:su"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetBackgroundNetworkUpdateState"},
+ {1, &NS_SU::OpenSystemUpdateControl, "OpenSystemUpdateControl"},
+ {2, nullptr, "NotifyExFatDriverRequired"},
+ {3, nullptr, "ClearExFatDriverStatusForDebug"},
+ {4, nullptr, "RequestBackgroundNetworkUpdate"},
+ {5, nullptr, "NotifyBackgroundNetworkUpdate"},
+ {6, nullptr, "NotifyExFatDriverDownloadedForDebug"},
+ {9, nullptr, "GetSystemUpdateNotificationEventForContentDelivery"},
+ {10, nullptr, "NotifySystemUpdateForContentDelivery"},
+ {11, nullptr, "PrepareShutdown"},
+ {16, nullptr, "DestroySystemUpdateTask"},
+ {17, nullptr, "RequestSendSystemUpdate"},
+ {18, nullptr, "GetSendSystemUpdateProgress"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void OpenSystemUpdateControl(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<ISystemUpdateControl>();
+
+ LOG_DEBUG(Service_NS, "called");
+ }
+};
+
+class NS_VM final : public ServiceFramework<NS_VM> {
+public:
+ explicit NS_VM() : ServiceFramework{"ns:vm"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {1200, nullptr, "NeedsUpdateVulnerability"},
+ {1201, nullptr, "UpdateSafeSystemVersionForDebug"},
+ {1202, nullptr, "GetSafeSystemVersion"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
void InstallInterfaces(SM::ServiceManager& service_manager) {
+ std::make_shared<NS>("ns:am2")->InstallAsService(service_manager);
+ std::make_shared<NS>("ns:ec")->InstallAsService(service_manager);
+ std::make_shared<NS>("ns:rid")->InstallAsService(service_manager);
+ std::make_shared<NS>("ns:rt")->InstallAsService(service_manager);
+ std::make_shared<NS>("ns:web")->InstallAsService(service_manager);
+
+ std::make_shared<NS_DEV>()->InstallAsService(service_manager);
+ std::make_shared<NS_SU>()->InstallAsService(service_manager);
+ std::make_shared<NS_VM>()->InstallAsService(service_manager);
+
std::make_shared<PL_U>()->InstallAsService(service_manager);
}
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
index ed69a4325..8bc49935a 100644
--- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp
@@ -7,8 +7,8 @@
#include "core/core.h"
#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
#include "core/hle/service/nvdrv/devices/nvmap.h"
+#include "video_core/gpu.h"
#include "video_core/renderer_base.h"
-#include "video_core/video_core.h"
namespace Service::Nvidia::Devices {
@@ -30,9 +30,9 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3
addr, offset, width, height, stride, static_cast<PixelFormat>(format),
transform, crop_rect};
- Core::System::GetInstance().perf_stats.EndGameFrame();
-
- VideoCore::g_renderer->SwapBuffers(framebuffer);
+ auto& instance = Core::System::GetInstance();
+ instance.perf_stats.EndGameFrame();
+ instance.Renderer().SwapBuffers(framebuffer);
}
} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
index 57b128b40..be2b79256 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
@@ -2,14 +2,15 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <cinttypes>
+#include <cstring>
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h"
#include "core/hle/service/nvdrv/devices/nvmap.h"
+#include "video_core/memory_manager.h"
+#include "video_core/rasterizer_interface.h"
#include "video_core/renderer_base.h"
-#include "video_core/video_core.h"
namespace Service::Nvidia::Devices {
@@ -150,15 +151,16 @@ u32 nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& ou
LOG_DEBUG(Service_NVDRV, "called, offset=0x{:X}", params.offset);
- auto& gpu = Core::System::GetInstance().GPU();
-
- auto itr = buffer_mappings.find(params.offset);
-
+ const auto itr = buffer_mappings.find(params.offset);
ASSERT_MSG(itr != buffer_mappings.end(), "Tried to unmap invalid mapping");
+ auto& system_instance = Core::System::GetInstance();
+
// Remove this memory region from the rasterizer cache.
- VideoCore::g_renderer->Rasterizer()->FlushAndInvalidateRegion(params.offset, itr->second.size);
+ system_instance.Renderer().Rasterizer().FlushAndInvalidateRegion(params.offset,
+ itr->second.size);
+ auto& gpu = system_instance.GPU();
params.offset = gpu.memory_manager->UnmapBuffer(params.offset, itr->second.size);
buffer_mappings.erase(itr->second.offset);
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
index 671b092e1..5685eb2be 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.cpp
@@ -2,6 +2,9 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <cstdlib>
+#include <cstring>
+
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/hle/service/nvdrv/devices/nvhost_ctrl.h"
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
index 090261a60..6b496e9fe 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl.h
@@ -5,8 +5,6 @@
#pragma once
#include <array>
-#include <cstdlib>
-#include <cstring>
#include <vector>
#include "common/common_types.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
index 44e062f50..ae421247d 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp
@@ -2,7 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <cinttypes>
+#include <cstring>
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h"
@@ -97,7 +97,9 @@ u32 nvhost_ctrl_gpu::GetTPCMasks(const std::vector<u8>& input, std::vector<u8>&
u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called");
IoctlActiveSlotMask params{};
- std::memcpy(&params, input.data(), input.size());
+ if (input.size() > 0) {
+ std::memcpy(&params, input.data(), input.size());
+ }
params.slot = 0x07;
params.mask = 0x01;
std::memcpy(output.data(), &params, output.size());
@@ -107,7 +109,9 @@ u32 nvhost_ctrl_gpu::GetActiveSlotMask(const std::vector<u8>& input, std::vector
u32 nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called");
IoctlZcullGetCtxSize params{};
- std::memcpy(&params, input.data(), input.size());
+ if (input.size() > 0) {
+ std::memcpy(&params, input.data(), input.size());
+ }
params.size = 0x1;
std::memcpy(output.data(), &params, output.size());
return 0;
@@ -116,7 +120,11 @@ u32 nvhost_ctrl_gpu::ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u
u32 nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_DEBUG(Service_NVDRV, "called");
IoctlNvgpuGpuZcullGetInfoArgs params{};
- std::memcpy(&params, input.data(), input.size());
+
+ if (input.size() > 0) {
+ std::memcpy(&params, input.data(), input.size());
+ }
+
params.width_align_pixels = 0x20;
params.height_align_pixels = 0x20;
params.pixel_squares_by_aliquots = 0x400;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
index 126782573..4cdf7f613 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
@@ -2,12 +2,14 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <cinttypes>
-#include <map>
+#include <cstring>
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/service/nvdrv/devices/nvhost_gpu.h"
+#include "core/memory.h"
+#include "video_core/gpu.h"
+#include "video_core/memory_manager.h"
namespace Service::Nvidia::Devices {
@@ -132,9 +134,12 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}",
params.address, params.num_entries, params.flags);
- auto entries = std::vector<IoctlGpfifoEntry>();
- entries.resize(params.num_entries);
- std::memcpy(&entries[0], &input.data()[sizeof(IoctlSubmitGpfifo)],
+ ASSERT_MSG(input.size() ==
+ sizeof(IoctlSubmitGpfifo) + params.num_entries * sizeof(IoctlGpfifoEntry),
+ "Incorrect input size");
+
+ std::vector<IoctlGpfifoEntry> entries(params.num_entries);
+ std::memcpy(entries.data(), &input[sizeof(IoctlSubmitGpfifo)],
params.num_entries * sizeof(IoctlGpfifoEntry));
for (auto entry : entries) {
Tegra::GPUVAddr va_addr = entry.Address();
@@ -142,7 +147,7 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
}
params.fence_out.id = 0;
params.fence_out.value = 0;
- std::memcpy(output.data(), &params, output.size());
+ std::memcpy(output.data(), &params, sizeof(IoctlSubmitGpfifo));
return 0;
}
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
index aa8df2e6e..650ed8fbc 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
@@ -6,6 +6,7 @@
#include <memory>
#include <vector>
+#include "common/bit_field.h"
#include "common/common_types.h"
#include "common/swap.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
index b51c73ee8..364619e67 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <cstring>
+
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/hle/service/nvdrv/devices/nvhost_nvdec.h"
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
index 0192aecdd..6ad74421b 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.h
@@ -4,11 +4,9 @@
#pragma once
-#include <array>
-#include <cstdlib>
-#include <cstring>
#include <vector>
#include "common/common_types.h"
+#include "common/swap.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"
namespace Service::Nvidia::Devices {
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
new file mode 100644
index 000000000..51f01077b
--- /dev/null
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.cpp
@@ -0,0 +1,34 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <cstring>
+
+#include "common/assert.h"
+#include "common/logging/log.h"
+#include "core/hle/service/nvdrv/devices/nvhost_nvjpg.h"
+
+namespace Service::Nvidia::Devices {
+
+u32 nvhost_nvjpg::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
+ LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
+ command.raw, input.size(), output.size());
+
+ switch (static_cast<IoctlCommand>(command.raw)) {
+ case IoctlCommand::IocSetNVMAPfdCommand:
+ return SetNVMAPfd(input, output);
+ }
+
+ UNIMPLEMENTED_MSG("Unimplemented ioctl");
+ return 0;
+}
+
+u32 nvhost_nvjpg::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) {
+ IoctlSetNvmapFD params{};
+ std::memcpy(&params, input.data(), input.size());
+ LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
+ nvmap_fd = params.nvmap_fd;
+ return 0;
+}
+
+} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
new file mode 100644
index 000000000..2b0eb43ee
--- /dev/null
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvjpg.h
@@ -0,0 +1,36 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <vector>
+#include "common/common_types.h"
+#include "common/swap.h"
+#include "core/hle/service/nvdrv/devices/nvdevice.h"
+
+namespace Service::Nvidia::Devices {
+
+class nvhost_nvjpg final : public nvdevice {
+public:
+ nvhost_nvjpg() = default;
+ ~nvhost_nvjpg() override = default;
+
+ u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
+
+private:
+ enum class IoctlCommand : u32_le {
+ IocSetNVMAPfdCommand = 0x40044801,
+ };
+
+ struct IoctlSetNvmapFD {
+ u32_le nvmap_fd;
+ };
+ static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size");
+
+ u32_le nvmap_fd{};
+
+ u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output);
+};
+
+} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
new file mode 100644
index 000000000..fcb488d50
--- /dev/null
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
@@ -0,0 +1,34 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <cstring>
+
+#include "common/assert.h"
+#include "common/logging/log.h"
+#include "core/hle/service/nvdrv/devices/nvhost_vic.h"
+
+namespace Service::Nvidia::Devices {
+
+u32 nvhost_vic::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) {
+ LOG_DEBUG(Service_NVDRV, "called, command=0x{:08X}, input_size=0x{:X}, output_size=0x{:X}",
+ command.raw, input.size(), output.size());
+
+ switch (static_cast<IoctlCommand>(command.raw)) {
+ case IoctlCommand::IocSetNVMAPfdCommand:
+ return SetNVMAPfd(input, output);
+ }
+
+ UNIMPLEMENTED_MSG("Unimplemented ioctl");
+ return 0;
+}
+
+u32 nvhost_vic::SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output) {
+ IoctlSetNvmapFD params{};
+ std::memcpy(&params, input.data(), input.size());
+ LOG_DEBUG(Service_NVDRV, "called, fd={}", params.nvmap_fd);
+ nvmap_fd = params.nvmap_fd;
+ return 0;
+}
+
+} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.h b/src/core/hle/service/nvdrv/devices/nvhost_vic.h
new file mode 100644
index 000000000..c7d681e52
--- /dev/null
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.h
@@ -0,0 +1,36 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <vector>
+#include "common/common_types.h"
+#include "common/swap.h"
+#include "core/hle/service/nvdrv/devices/nvdevice.h"
+
+namespace Service::Nvidia::Devices {
+
+class nvhost_vic final : public nvdevice {
+public:
+ nvhost_vic() = default;
+ ~nvhost_vic() override = default;
+
+ u32 ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& output) override;
+
+private:
+ enum class IoctlCommand : u32_le {
+ IocSetNVMAPfdCommand = 0x40044801,
+ };
+
+ struct IoctlSetNvmapFD {
+ u32_le nvmap_fd;
+ };
+ static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size");
+
+ u32_le nvmap_fd{};
+
+ u32 SetNVMAPfd(const std::vector<u8>& input, std::vector<u8>& output);
+};
+
+} // namespace Service::Nvidia::Devices
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index 724eeb139..e9305bfb3 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -3,7 +3,7 @@
// Refer to the license.txt file included.
#include <algorithm>
-#include <cinttypes>
+#include <cstring>
#include "common/assert.h"
#include "common/logging/log.h"
diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/interface.h
index 959b5ba29..1c3529bb6 100644
--- a/src/core/hle/service/nvdrv/interface.h
+++ b/src/core/hle/service/nvdrv/interface.h
@@ -5,7 +5,6 @@
#pragma once
#include <memory>
-#include <string>
#include "core/hle/kernel/event.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/service.h"
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index 1555ea806..2de39822f 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -12,23 +12,24 @@
#include "core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h"
#include "core/hle/service/nvdrv/devices/nvhost_gpu.h"
#include "core/hle/service/nvdrv/devices/nvhost_nvdec.h"
+#include "core/hle/service/nvdrv/devices/nvhost_nvjpg.h"
+#include "core/hle/service/nvdrv/devices/nvhost_vic.h"
#include "core/hle/service/nvdrv/devices/nvmap.h"
#include "core/hle/service/nvdrv/interface.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/nvdrv/nvmemp.h"
+#include "core/hle/service/nvflinger/nvflinger.h"
namespace Service::Nvidia {
-std::weak_ptr<Module> nvdrv;
-
-void InstallInterfaces(SM::ServiceManager& service_manager) {
+void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger) {
auto module_ = std::make_shared<Module>();
std::make_shared<NVDRV>(module_, "nvdrv")->InstallAsService(service_manager);
std::make_shared<NVDRV>(module_, "nvdrv:a")->InstallAsService(service_manager);
std::make_shared<NVDRV>(module_, "nvdrv:s")->InstallAsService(service_manager);
std::make_shared<NVDRV>(module_, "nvdrv:t")->InstallAsService(service_manager);
std::make_shared<NVMEMP>()->InstallAsService(service_manager);
- nvdrv = module_;
+ nvflinger.SetNVDrvInstance(module_);
}
Module::Module() {
@@ -40,6 +41,8 @@ Module::Module() {
devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(nvmap_dev);
devices["/dev/nvhost-ctrl"] = std::make_shared<Devices::nvhost_ctrl>();
devices["/dev/nvhost-nvdec"] = std::make_shared<Devices::nvhost_nvdec>();
+ devices["/dev/nvhost-nvjpg"] = std::make_shared<Devices::nvhost_nvjpg>();
+ devices["/dev/nvhost-vic"] = std::make_shared<Devices::nvhost_vic>();
}
u32 Module::Open(const std::string& device_name) {
@@ -54,7 +57,7 @@ u32 Module::Open(const std::string& device_name) {
return fd;
}
-u32 Module::Ioctl(u32 fd, u32_le command, const std::vector<u8>& input, std::vector<u8>& output) {
+u32 Module::Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output) {
auto itr = open_files.find(fd);
ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device");
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h
index 184f3c9fc..99eb1128a 100644
--- a/src/core/hle/service/nvdrv/nvdrv.h
+++ b/src/core/hle/service/nvdrv/nvdrv.h
@@ -10,6 +10,10 @@
#include "common/common_types.h"
#include "core/hle/service/service.h"
+namespace Service::NVFlinger {
+class NVFlinger;
+}
+
namespace Service::Nvidia {
namespace Devices {
@@ -56,8 +60,6 @@ private:
};
/// Registers all NVDRV services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager);
-
-extern std::weak_ptr<Module> nvdrv;
+void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger);
} // namespace Service::Nvidia
diff --git a/src/core/hle/service/nvdrv/nvmemp.cpp b/src/core/hle/service/nvdrv/nvmemp.cpp
index 9ca6e5512..0e8e21bad 100644
--- a/src/core/hle/service/nvdrv/nvmemp.cpp
+++ b/src/core/hle/service/nvdrv/nvmemp.cpp
@@ -4,8 +4,6 @@
#include "common/assert.h"
#include "common/logging/log.h"
-#include "core/hle/ipc_helpers.h"
-#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/nvdrv/nvmemp.h"
namespace Service::Nvidia {
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index 7132b18ad..ef5713a71 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -4,9 +4,8 @@
#include <algorithm>
-#include "common/alignment.h"
-#include "common/scope_exit.h"
-#include "core/core_timing.h"
+#include "common/assert.h"
+#include "common/logging/log.h"
#include "core/hle/service/nvflinger/buffer_queue.h"
namespace Service {
@@ -17,7 +16,7 @@ BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {
Kernel::Event::Create(Kernel::ResetType::Sticky, "BufferQueue NativeHandle");
}
-void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) {
+void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) {
Buffer buffer{};
buffer.slot = slot;
buffer.igbp_buffer = igbp_buffer;
diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h
index 004170538..db2e17c0c 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.h
+++ b/src/core/hle/service/nvflinger/buffer_queue.h
@@ -6,6 +6,7 @@
#include <vector>
#include <boost/optional.hpp>
+#include "common/common_funcs.h"
#include "common/math_util.h"
#include "common/swap.h"
#include "core/hle/kernel/event.h"
@@ -72,7 +73,7 @@ public:
MathUtil::Rectangle<int> crop_rect;
};
- void SetPreallocatedBuffer(u32 slot, IGBPBuffer& buffer);
+ void SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer);
boost::optional<u32> DequeueBuffer(u32 width, u32 height);
const IGBPBuffer& RequestBuffer(u32 slot) const;
void QueueBuffer(u32 slot, BufferTransformFlags transform,
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index 5344441e1..a26a5f812 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -3,8 +3,11 @@
// Refer to the license.txt file included.
#include <algorithm>
+#include <boost/optional.hpp>
#include "common/alignment.h"
+#include "common/assert.h"
+#include "common/logging/log.h"
#include "common/microprofile.h"
#include "common/scope_exit.h"
#include "core/core.h"
@@ -31,7 +34,7 @@ NVFlinger::NVFlinger() {
// Schedule the screen composition events
composition_event =
- CoreTiming::RegisterEvent("ScreenCompositioin", [this](u64 userdata, int cycles_late) {
+ CoreTiming::RegisterEvent("ScreenComposition", [this](u64 userdata, int cycles_late) {
Compose();
CoreTiming::ScheduleEvent(frame_ticks - cycles_late, composition_event);
});
@@ -43,7 +46,11 @@ NVFlinger::~NVFlinger() {
CoreTiming::UnscheduleEvent(composition_event, 0);
}
-u64 NVFlinger::OpenDisplay(const std::string& name) {
+void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
+ nvdrv = std::move(instance);
+}
+
+u64 NVFlinger::OpenDisplay(std::string_view name) {
LOG_WARNING(Service, "Opening display {}", name);
// TODO(Subv): Currently we only support the Default display.
@@ -127,18 +134,17 @@ void NVFlinger::Compose() {
MicroProfileFlip();
if (buffer == boost::none) {
+ auto& system_instance = Core::System::GetInstance();
+
// There was no queued buffer to draw, render previous frame
- Core::System::GetInstance().perf_stats.EndGameFrame();
- VideoCore::g_renderer->SwapBuffers({});
+ system_instance.perf_stats.EndGameFrame();
+ system_instance.Renderer().SwapBuffers({});
continue;
}
auto& igbp_buffer = buffer->igbp_buffer;
// Now send the buffer to the GPU for drawing.
- auto nvdrv = Nvidia::nvdrv.lock();
- ASSERT(nvdrv);
-
// TODO(Subv): Support more than just disp0. The display device selection is probably based
// on which display we're drawing (Default, Internal, External, etc)
auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>("/dev/nvdisp_disp0");
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index 2c908297b..f7112949f 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -5,13 +5,21 @@
#pragma once
#include <memory>
-#include <boost/optional.hpp>
+#include <string>
+#include <string_view>
+#include <vector>
+
+#include "common/common_types.h"
#include "core/hle/kernel/event.h"
namespace CoreTiming {
struct EventType;
}
+namespace Service::Nvidia {
+class Module;
+}
+
namespace Service::NVFlinger {
class BufferQueue;
@@ -40,8 +48,11 @@ public:
NVFlinger();
~NVFlinger();
+ /// Sets the NVDrv module instance to use to send buffers to the GPU.
+ void SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance);
+
/// Opens the specified display and returns the id.
- u64 OpenDisplay(const std::string& name);
+ u64 OpenDisplay(std::string_view name);
/// Creates a layer on the specified display and returns the layer id.
u64 CreateLayer(u64 display_id);
@@ -66,6 +77,8 @@ private:
/// Returns the layer identified by the specified id in the desired display.
Layer& GetLayer(u64 display_id, u64 layer_id);
+ std::shared_ptr<Nvidia::Module> nvdrv;
+
std::vector<Display> displays;
std::vector<std::shared_ptr<BufferQueue>> buffer_queues;
diff --git a/src/core/hle/service/pcie/pcie.cpp b/src/core/hle/service/pcie/pcie.cpp
new file mode 100644
index 000000000..39cf05eba
--- /dev/null
+++ b/src/core/hle/service/pcie/pcie.cpp
@@ -0,0 +1,64 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "core/hle/service/pcie/pcie.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::PCIe {
+
+class ISession final : public ServiceFramework<ISession> {
+public:
+ explicit ISession() : ServiceFramework{"ISession"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "QueryFunctions"},
+ {1, nullptr, "AcquireFunction"},
+ {2, nullptr, "ReleaseFunction"},
+ {3, nullptr, "GetFunctionState"},
+ {4, nullptr, "GetBarProfile"},
+ {5, nullptr, "ReadConfig"},
+ {6, nullptr, "WriteConfig"},
+ {7, nullptr, "ReadBarRegion"},
+ {8, nullptr, "WriteBarRegion"},
+ {9, nullptr, "FindCapability"},
+ {10, nullptr, "FindExtendedCapability"},
+ {11, nullptr, "MapDma"},
+ {12, nullptr, "UnmapDma"},
+ {13, nullptr, "UnmapDmaBusAddress"},
+ {14, nullptr, "GetDmaBusAddress"},
+ {15, nullptr, "GetDmaBusAddressRange"},
+ {16, nullptr, "SetDmaEnable"},
+ {17, nullptr, "AcquireIrq"},
+ {18, nullptr, "ReleaseIrq"},
+ {19, nullptr, "SetIrqEnable"},
+ {20, nullptr, "SetAspmEnable"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class PCIe final : public ServiceFramework<PCIe> {
+public:
+ explicit PCIe() : ServiceFramework{"pcie"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RegisterClassDriver"},
+ {1, nullptr, "QueryFunctionsUnregistered"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<PCIe>()->InstallAsService(sm);
+}
+
+} // namespace Service::PCIe
diff --git a/src/core/hle/service/pcie/pcie.h b/src/core/hle/service/pcie/pcie.h
new file mode 100644
index 000000000..59c22ca45
--- /dev/null
+++ b/src/core/hle/service/pcie/pcie.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::PCIe {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::PCIe
diff --git a/src/core/hle/service/pcv/pcv.cpp b/src/core/hle/service/pcv/pcv.cpp
new file mode 100644
index 000000000..d6891a659
--- /dev/null
+++ b/src/core/hle/service/pcv/pcv.cpp
@@ -0,0 +1,84 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "core/hle/service/pcv/pcv.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::PCV {
+
+class PCV final : public ServiceFramework<PCV> {
+public:
+ explicit PCV() : ServiceFramework{"pcv"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "SetPowerEnabled"},
+ {1, nullptr, "SetClockEnabled"},
+ {2, nullptr, "SetClockRate"},
+ {3, nullptr, "GetClockRate"},
+ {4, nullptr, "GetState"},
+ {5, nullptr, "GetPossibleClockRates"},
+ {6, nullptr, "SetMinVClockRate"},
+ {7, nullptr, "SetReset"},
+ {8, nullptr, "SetVoltageEnabled"},
+ {9, nullptr, "GetVoltageEnabled"},
+ {10, nullptr, "GetVoltageRange"},
+ {11, nullptr, "SetVoltageValue"},
+ {12, nullptr, "GetVoltageValue"},
+ {13, nullptr, "GetTemperatureThresholds"},
+ {14, nullptr, "SetTemperature"},
+ {15, nullptr, "Initialize"},
+ {16, nullptr, "IsInitialized"},
+ {17, nullptr, "Finalize"},
+ {18, nullptr, "PowerOn"},
+ {19, nullptr, "PowerOff"},
+ {20, nullptr, "ChangeVoltage"},
+ {21, nullptr, "GetPowerClockInfoEvent"},
+ {22, nullptr, "GetOscillatorClock"},
+ {23, nullptr, "GetDvfsTable"},
+ {24, nullptr, "GetModuleStateTable"},
+ {25, nullptr, "GetPowerDomainStateTable"},
+ {26, nullptr, "GetFuseInfo"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class PCV_ARB final : public ServiceFramework<PCV_ARB> {
+public:
+ explicit PCV_ARB() : ServiceFramework{"pcv:arb"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "ReleaseControl"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class PCV_IMM final : public ServiceFramework<PCV_IMM> {
+public:
+ explicit PCV_IMM() : ServiceFramework{"pcv:imm"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "SetClockRate"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<PCV>()->InstallAsService(sm);
+ std::make_shared<PCV_ARB>()->InstallAsService(sm);
+ std::make_shared<PCV_IMM>()->InstallAsService(sm);
+}
+
+} // namespace Service::PCV
diff --git a/src/core/hle/service/pcv/pcv.h b/src/core/hle/service/pcv/pcv.h
new file mode 100644
index 000000000..219a893c3
--- /dev/null
+++ b/src/core/hle/service/pcv/pcv.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::PCV {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::PCV
diff --git a/src/core/hle/service/psc/psc.cpp b/src/core/hle/service/psc/psc.cpp
new file mode 100644
index 000000000..bbad870a2
--- /dev/null
+++ b/src/core/hle/service/psc/psc.cpp
@@ -0,0 +1,77 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "common/logging/log.h"
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/service/psc/psc.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::PSC {
+
+class PSC_C final : public ServiceFramework<PSC_C> {
+public:
+ explicit PSC_C() : ServiceFramework{"psc:c"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown1"},
+ {1, nullptr, "Unknown2"},
+ {2, nullptr, "Unknown3"},
+ {3, nullptr, "Unknown4"},
+ {4, nullptr, "Unknown5"},
+ {5, nullptr, "Unknown6"},
+ {6, nullptr, "Unknown7"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class IPmModule final : public ServiceFramework<IPmModule> {
+public:
+ explicit IPmModule() : ServiceFramework{"IPmModule"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Initialize"},
+ {1, nullptr, "GetRequest"},
+ {2, nullptr, "Acknowledge"},
+ {3, nullptr, "Unknown1"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class PSC_M final : public ServiceFramework<PSC_M> {
+public:
+ explicit PSC_M() : ServiceFramework{"psc:m"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &PSC_M::GetPmModule, "GetPmModule"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void GetPmModule(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IPmModule>();
+
+ LOG_DEBUG(Service_PSC, "called");
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<PSC_C>()->InstallAsService(sm);
+ std::make_shared<PSC_M>()->InstallAsService(sm);
+}
+
+} // namespace Service::PSC
diff --git a/src/core/hle/service/psc/psc.h b/src/core/hle/service/psc/psc.h
new file mode 100644
index 000000000..5052eb02c
--- /dev/null
+++ b/src/core/hle/service/psc/psc.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::PSC {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::PSC
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 482989ea7..11951adaf 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -19,25 +19,42 @@
#include "core/hle/service/am/am.h"
#include "core/hle/service/aoc/aoc_u.h"
#include "core/hle/service/apm/apm.h"
+#include "core/hle/service/arp/arp.h"
#include "core/hle/service/audio/audio.h"
#include "core/hle/service/bcat/bcat.h"
+#include "core/hle/service/bpc/bpc.h"
+#include "core/hle/service/btdrv/btdrv.h"
+#include "core/hle/service/btm/btm.h"
+#include "core/hle/service/caps/caps.h"
#include "core/hle/service/erpt/erpt.h"
#include "core/hle/service/es/es.h"
#include "core/hle/service/eupld/eupld.h"
#include "core/hle/service/fatal/fatal.h"
+#include "core/hle/service/fgm/fgm.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/friend/friend.h"
+#include "core/hle/service/grc/grc.h"
#include "core/hle/service/hid/hid.h"
+#include "core/hle/service/lbl/lbl.h"
+#include "core/hle/service/ldn/ldn.h"
#include "core/hle/service/ldr/ldr.h"
#include "core/hle/service/lm/lm.h"
+#include "core/hle/service/mig/mig.h"
+#include "core/hle/service/mii/mii.h"
#include "core/hle/service/mm/mm_u.h"
+#include "core/hle/service/ncm/ncm.h"
+#include "core/hle/service/nfc/nfc.h"
#include "core/hle/service/nfp/nfp.h"
#include "core/hle/service/nifm/nifm.h"
+#include "core/hle/service/nim/nim.h"
#include "core/hle/service/ns/ns.h"
#include "core/hle/service/nvdrv/nvdrv.h"
+#include "core/hle/service/pcie/pcie.h"
#include "core/hle/service/pctl/pctl.h"
+#include "core/hle/service/pcv/pcv.h"
#include "core/hle/service/pm/pm.h"
#include "core/hle/service/prepo/prepo.h"
+#include "core/hle/service/psc/psc.h"
#include "core/hle/service/service.h"
#include "core/hle/service/set/settings.h"
#include "core/hle/service/sm/controller.h"
@@ -46,7 +63,9 @@
#include "core/hle/service/spl/module.h"
#include "core/hle/service/ssl/ssl.h"
#include "core/hle/service/time/time.h"
+#include "core/hle/service/usb/usb.h"
#include "core/hle/service/vi/vi.h"
+#include "core/hle/service/wlan/wlan.h"
using Kernel::ClientPort;
using Kernel::ServerPort;
@@ -179,7 +198,7 @@ void AddNamedPort(std::string name, SharedPtr<ClientPort> port) {
}
/// Initialize ServiceManager
-void Init(std::shared_ptr<SM::ServiceManager>& sm) {
+void Init(std::shared_ptr<SM::ServiceManager>& sm, const FileSys::VirtualFilesystem& rfs) {
// NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it
// here and pass it into the respective InstallInterfaces functions.
auto nv_flinger = std::make_shared<NVFlinger::NVFlinger>();
@@ -190,31 +209,50 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm) {
AM::InstallInterfaces(*sm, nv_flinger);
AOC::InstallInterfaces(*sm);
APM::InstallInterfaces(*sm);
- BCAT::InstallInterfaces(*sm);
+ ARP::InstallInterfaces(*sm);
Audio::InstallInterfaces(*sm);
+ BCAT::InstallInterfaces(*sm);
+ BPC::InstallInterfaces(*sm);
+ BtDrv::InstallInterfaces(*sm);
+ BTM::InstallInterfaces(*sm);
+ Capture::InstallInterfaces(*sm);
ERPT::InstallInterfaces(*sm);
ES::InstallInterfaces(*sm);
EUPLD::InstallInterfaces(*sm);
Fatal::InstallInterfaces(*sm);
- FileSystem::InstallInterfaces(*sm);
+ FGM::InstallInterfaces(*sm);
+ FileSystem::InstallInterfaces(*sm, rfs);
Friend::InstallInterfaces(*sm);
+ GRC::InstallInterfaces(*sm);
HID::InstallInterfaces(*sm);
+ LBL::InstallInterfaces(*sm);
+ LDN::InstallInterfaces(*sm);
LDR::InstallInterfaces(*sm);
LM::InstallInterfaces(*sm);
+ Migration::InstallInterfaces(*sm);
+ Mii::InstallInterfaces(*sm);
MM::InstallInterfaces(*sm);
+ NCM::InstallInterfaces(*sm);
+ NFC::InstallInterfaces(*sm);
NFP::InstallInterfaces(*sm);
NIFM::InstallInterfaces(*sm);
+ NIM::InstallInterfaces(*sm);
NS::InstallInterfaces(*sm);
- Nvidia::InstallInterfaces(*sm);
+ Nvidia::InstallInterfaces(*sm, *nv_flinger);
+ PCIe::InstallInterfaces(*sm);
PCTL::InstallInterfaces(*sm);
+ PCV::InstallInterfaces(*sm);
PlayReport::InstallInterfaces(*sm);
PM::InstallInterfaces(*sm);
+ PSC::InstallInterfaces(*sm);
+ Set::InstallInterfaces(*sm);
Sockets::InstallInterfaces(*sm);
SPL::InstallInterfaces(*sm);
SSL::InstallInterfaces(*sm);
Time::InstallInterfaces(*sm);
+ USB::InstallInterfaces(*sm);
VI::InstallInterfaces(*sm, nv_flinger);
- Set::InstallInterfaces(*sm);
+ WLAN::InstallInterfaces(*sm);
LOG_DEBUG(Service, "initialized OK");
}
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index 180f22703..cd9c74f3d 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -8,10 +8,9 @@
#include <string>
#include <unordered_map>
#include <boost/container/flat_map.hpp>
-#include "common/bit_field.h"
#include "common/common_types.h"
#include "core/hle/kernel/hle_ipc.h"
-#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/object.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
// Namespace Service
@@ -23,6 +22,10 @@ class ServerSession;
class HLERequestContext;
} // namespace Kernel
+namespace FileSys {
+class VfsFilesystem;
+}
+
namespace Service {
namespace SM {
@@ -178,7 +181,8 @@ private:
};
/// Initialize ServiceManager
-void Init(std::shared_ptr<SM::ServiceManager>& sm);
+void Init(std::shared_ptr<SM::ServiceManager>& sm,
+ const std::shared_ptr<FileSys::VfsFilesystem>& vfs);
/// Shutdown ServiceManager
void Shutdown();
diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp
index 1651f6122..a461e72ec 100644
--- a/src/core/hle/service/set/set.cpp
+++ b/src/core/hle/service/set/set.cpp
@@ -8,6 +8,7 @@
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h"
#include "core/hle/service/set/set.h"
+#include "core/settings.h"
namespace Service::Set {
@@ -31,6 +32,10 @@ constexpr std::array<LanguageCode, 17> available_language_codes = {{
LanguageCode::ZH_HANT,
}};
+LanguageCode GetLanguageCodeFromIndex(size_t index) {
+ return available_language_codes.at(index);
+}
+
void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) {
ctx.WriteBuffer(available_language_codes);
@@ -49,9 +54,17 @@ void SET::GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
}
+void SET::GetLanguageCode(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push(static_cast<u64>(available_language_codes[Settings::values.language_index]));
+
+ LOG_DEBUG(Service_SET, "called {}", Settings::values.language_index);
+}
+
SET::SET() : ServiceFramework("set") {
static const FunctionInfo functions[] = {
- {0, nullptr, "GetLanguageCode"},
+ {0, &SET::GetLanguageCode, "GetLanguageCode"},
{1, &SET::GetAvailableLanguageCodes, "GetAvailableLanguageCodes"},
{2, nullptr, "MakeLanguageCode"},
{3, &SET::GetAvailableLanguageCodeCount, "GetAvailableLanguageCodeCount"},
diff --git a/src/core/hle/service/set/set.h b/src/core/hle/service/set/set.h
index a2472ec4c..4232b6162 100644
--- a/src/core/hle/service/set/set.h
+++ b/src/core/hle/service/set/set.h
@@ -28,6 +28,7 @@ enum class LanguageCode : u64 {
ZH_HANS = 0x00736E61482D687A,
ZH_HANT = 0x00746E61482D687A,
};
+LanguageCode GetLanguageCodeFromIndex(size_t idx);
class SET final : public ServiceFramework<SET> {
public:
@@ -35,6 +36,7 @@ public:
~SET() = default;
private:
+ void GetLanguageCode(Kernel::HLERequestContext& ctx);
void GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx);
void GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx);
};
diff --git a/src/core/hle/service/sm/controller.cpp b/src/core/hle/service/sm/controller.cpp
index 518a0cc46..1cef73216 100644
--- a/src/core/hle/service/sm/controller.cpp
+++ b/src/core/hle/service/sm/controller.cpp
@@ -10,7 +10,7 @@
namespace Service::SM {
void Controller::ConvertSessionToDomain(Kernel::HLERequestContext& ctx) {
- ASSERT_MSG(!ctx.Session()->IsDomain(), "session is alread a domain");
+ ASSERT_MSG(ctx.Session()->IsSession(), "Session is already a domain");
ctx.Session()->ConvertToDomain();
IPC::ResponseBuilder rb{ctx, 3};
@@ -41,7 +41,7 @@ void Controller::DuplicateSessionEx(Kernel::HLERequestContext& ctx) {
void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
- rb.Push<u32>(0x500);
+ rb.Push<u16>(0x500);
LOG_WARNING(Service, "(STUBBED) called");
}
diff --git a/src/core/hle/service/sm/sm.h b/src/core/hle/service/sm/sm.h
index e2a00e4f6..e8ea62f08 100644
--- a/src/core/hle/service/sm/sm.h
+++ b/src/core/hle/service/sm/sm.h
@@ -4,9 +4,11 @@
#pragma once
+#include <memory>
#include <string>
#include <unordered_map>
-#include "core/hle/kernel/kernel.h"
+
+#include "core/hle/kernel/object.h"
#include "core/hle/result.h"
#include "core/hle/service/service.h"
@@ -19,6 +21,8 @@ class SessionRequestHandler;
namespace Service::SM {
+class Controller;
+
/// Interface to "sm:" service
class SM final : public ServiceFramework<SM> {
public:
@@ -32,8 +36,6 @@ private:
std::shared_ptr<ServiceManager> service_manager;
};
-class Controller;
-
constexpr ResultCode ERR_SERVICE_NOT_REGISTERED(-1);
constexpr ResultCode ERR_MAX_CONNECTIONS_REACHED(-1);
constexpr ResultCode ERR_INVALID_NAME_SIZE(-1);
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp
index 6aa1e2511..3211a8346 100644
--- a/src/core/hle/service/sockets/bsd.cpp
+++ b/src/core/hle/service/sockets/bsd.cpp
@@ -109,4 +109,26 @@ BSD::BSD(const char* name) : ServiceFramework(name) {
RegisterHandlers(functions);
}
+BSDCFG::BSDCFG() : ServiceFramework{"bsdcfg"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "SetIfUp"},
+ {1, nullptr, "SetIfUpWithEvent"},
+ {2, nullptr, "CancelIf"},
+ {3, nullptr, "SetIfDown"},
+ {4, nullptr, "GetIfState"},
+ {5, nullptr, "DhcpRenew"},
+ {6, nullptr, "AddStaticArpEntry"},
+ {7, nullptr, "RemoveArpEntry"},
+ {8, nullptr, "LookupArpEntry"},
+ {9, nullptr, "LookupArpEntry2"},
+ {10, nullptr, "ClearArpEntries"},
+ {11, nullptr, "ClearArpEntries2"},
+ {12, nullptr, "PrintArpEntries"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
} // namespace Service::Sockets
diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h
index a6b1ca7d0..c1da59b24 100644
--- a/src/core/hle/service/sockets/bsd.h
+++ b/src/core/hle/service/sockets/bsd.h
@@ -26,4 +26,9 @@ private:
u32 next_fd = 1;
};
+class BSDCFG final : public ServiceFramework<BSDCFG> {
+public:
+ explicit BSDCFG();
+};
+
} // namespace Service::Sockets
diff --git a/src/core/hle/service/sockets/ethc.cpp b/src/core/hle/service/sockets/ethc.cpp
new file mode 100644
index 000000000..d53c25eec
--- /dev/null
+++ b/src/core/hle/service/sockets/ethc.cpp
@@ -0,0 +1,38 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/sockets/ethc.h"
+
+namespace Service::Sockets {
+
+ETHC_C::ETHC_C() : ServiceFramework{"ethc:c"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Initialize"},
+ {1, nullptr, "Cancel"},
+ {2, nullptr, "GetResult"},
+ {3, nullptr, "GetMediaList"},
+ {4, nullptr, "SetMediaType"},
+ {5, nullptr, "GetMediaType"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+ETHC_I::ETHC_I() : ServiceFramework{"ethc:i"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetReadableHandle"},
+ {1, nullptr, "Cancel"},
+ {2, nullptr, "GetResult"},
+ {3, nullptr, "GetInterfaceList"},
+ {4, nullptr, "GetInterfaceCount"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::Sockets
diff --git a/src/core/hle/service/sockets/ethc.h b/src/core/hle/service/sockets/ethc.h
new file mode 100644
index 000000000..9a3c88100
--- /dev/null
+++ b/src/core/hle/service/sockets/ethc.h
@@ -0,0 +1,21 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::Sockets {
+
+class ETHC_C final : public ServiceFramework<ETHC_C> {
+public:
+ explicit ETHC_C();
+};
+
+class ETHC_I final : public ServiceFramework<ETHC_I> {
+public:
+ explicit ETHC_I();
+};
+
+} // namespace Service::Sockets
diff --git a/src/core/hle/service/sockets/sockets.cpp b/src/core/hle/service/sockets/sockets.cpp
index 05bd10d35..08d2d306a 100644
--- a/src/core/hle/service/sockets/sockets.cpp
+++ b/src/core/hle/service/sockets/sockets.cpp
@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include "core/hle/service/sockets/bsd.h"
+#include "core/hle/service/sockets/ethc.h"
#include "core/hle/service/sockets/nsd.h"
#include "core/hle/service/sockets/sfdnsres.h"
#include "core/hle/service/sockets/sockets.h"
@@ -12,8 +13,14 @@ namespace Service::Sockets {
void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<BSD>("bsd:s")->InstallAsService(service_manager);
std::make_shared<BSD>("bsd:u")->InstallAsService(service_manager);
+ std::make_shared<BSDCFG>()->InstallAsService(service_manager);
+
+ std::make_shared<ETHC_C>()->InstallAsService(service_manager);
+ std::make_shared<ETHC_I>()->InstallAsService(service_manager);
+
std::make_shared<NSD>("nsd:a")->InstallAsService(service_manager);
std::make_shared<NSD>("nsd:u")->InstallAsService(service_manager);
+
std::make_shared<SFDNSRES>()->InstallAsService(service_manager);
}
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index 37b58bb77..2172c681b 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -80,8 +80,8 @@ public:
{5, nullptr, "GetTimeZoneRuleVersion"},
{100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"},
{101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
- {200, nullptr, "ToPosixTime"},
- {201, nullptr, "ToPosixTimeWithMyRule"},
+ {201, nullptr, "ToPosixTime"},
+ {202, nullptr, "ToPosixTimeWithMyRule"},
};
RegisterHandlers(functions);
}
diff --git a/src/core/hle/service/usb/usb.cpp b/src/core/hle/service/usb/usb.cpp
new file mode 100644
index 000000000..e7fb5a419
--- /dev/null
+++ b/src/core/hle/service/usb/usb.cpp
@@ -0,0 +1,238 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "common/logging/log.h"
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+#include "core/hle/service/usb/usb.h"
+
+namespace Service::USB {
+
+class IDsInterface final : public ServiceFramework<IDsInterface> {
+public:
+ explicit IDsInterface() : ServiceFramework{"IDsInterface"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetDsEndpoint"},
+ {1, nullptr, "GetSetupEvent"},
+ {2, nullptr, "Unknown"},
+ {3, nullptr, "EnableInterface"},
+ {4, nullptr, "DisableInterface"},
+ {5, nullptr, "CtrlInPostBufferAsync"},
+ {6, nullptr, "CtrlOutPostBufferAsync"},
+ {7, nullptr, "GetCtrlInCompletionEvent"},
+ {8, nullptr, "GetCtrlInReportData"},
+ {9, nullptr, "GetCtrlOutCompletionEvent"},
+ {10, nullptr, "GetCtrlOutReportData"},
+ {11, nullptr, "StallCtrl"},
+ {12, nullptr, "AppendConfigurationData"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class USB_DS final : public ServiceFramework<USB_DS> {
+public:
+ explicit USB_DS() : ServiceFramework{"usb:ds"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "BindDevice"},
+ {1, nullptr, "BindClientProcess"},
+ {2, nullptr, "GetDsInterface"},
+ {3, nullptr, "GetStateChangeEvent"},
+ {4, nullptr, "GetState"},
+ {5, nullptr, "ClearDeviceData"},
+ {6, nullptr, "AddUsbStringDescriptor"},
+ {7, nullptr, "DeleteUsbStringDescriptor"},
+ {8, nullptr, "SetUsbDeviceDescriptor"},
+ {9, nullptr, "SetBinaryObjectStore"},
+ {10, nullptr, "Enable"},
+ {11, nullptr, "Disable"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class IClientEpSession final : public ServiceFramework<IClientEpSession> {
+public:
+ explicit IClientEpSession() : ServiceFramework{"IClientEpSession"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown1"},
+ {1, nullptr, "Unknown2"},
+ {2, nullptr, "Unknown3"},
+ {3, nullptr, "Unknown4"},
+ {4, nullptr, "PostBufferAsync"},
+ {5, nullptr, "Unknown5"},
+ {6, nullptr, "Unknown6"},
+ {7, nullptr, "Unknown7"},
+ {8, nullptr, "Unknown8"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class IClientIfSession final : public ServiceFramework<IClientIfSession> {
+public:
+ explicit IClientIfSession() : ServiceFramework{"IClientIfSession"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown1"},
+ {1, nullptr, "Unknown2"},
+ {2, nullptr, "Unknown3"},
+ {3, nullptr, "Unknown4"},
+ {4, nullptr, "Unknown5"},
+ {5, nullptr, "CtrlXferAsync"},
+ {6, nullptr, "Unknown6"},
+ {7, nullptr, "GetCtrlXferReport"},
+ {8, nullptr, "Unknown7"},
+ {9, nullptr, "GetClientEpSession"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class USB_HS final : public ServiceFramework<USB_HS> {
+public:
+ explicit USB_HS() : ServiceFramework{"usb:hs"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "BindClientProcess"},
+ {1, nullptr, "Unknown1"},
+ {2, nullptr, "Unknown2"},
+ {3, nullptr, "Unknown3"},
+ {4, nullptr, "Unknown4"},
+ {5, nullptr, "Unknown5"},
+ {6, nullptr, "GetInterfaceStateChangeEvent"},
+ {7, nullptr, "GetClientIfSession"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class IPdSession final : public ServiceFramework<IPdSession> {
+public:
+ explicit IPdSession() : ServiceFramework{"IPdSession"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "BindNoticeEvent"},
+ {1, nullptr, "Unknown1"},
+ {2, nullptr, "GetStatus"},
+ {3, nullptr, "GetNotice"},
+ {4, nullptr, "Unknown2"},
+ {5, nullptr, "Unknown3"},
+ {6, nullptr, "ReplyPowerRequest"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class USB_PD final : public ServiceFramework<USB_PD> {
+public:
+ explicit USB_PD() : ServiceFramework{"usb:pd"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &USB_PD::GetPdSession, "GetPdSession"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void GetPdSession(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IPdSession>();
+
+ LOG_DEBUG(Service_USB, "called");
+ }
+};
+
+class IPdCradleSession final : public ServiceFramework<IPdCradleSession> {
+public:
+ explicit IPdCradleSession() : ServiceFramework{"IPdCradleSession"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "VdmUserWrite"},
+ {1, nullptr, "VdmUserRead"},
+ {2, nullptr, "Vdm20Init"},
+ {3, nullptr, "GetFwType"},
+ {4, nullptr, "GetFwRevision"},
+ {5, nullptr, "GetManufacturerId"},
+ {6, nullptr, "GetDeviceId"},
+ {7, nullptr, "Unknown1"},
+ {8, nullptr, "Unknown2"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class USB_PD_C final : public ServiceFramework<USB_PD_C> {
+public:
+ explicit USB_PD_C() : ServiceFramework{"usb:pd:c"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &USB_PD_C::GetPdCradleSession, "GetPdCradleSession"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void GetPdCradleSession(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IPdCradleSession>();
+
+ LOG_DEBUG(Service_USB, "called");
+ }
+};
+
+class USB_PM final : public ServiceFramework<USB_PM> {
+public:
+ explicit USB_PM() : ServiceFramework{"usb:pm"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown1"},
+ {1, nullptr, "Unknown2"},
+ {2, nullptr, "Unknown3"},
+ {3, nullptr, "Unknown4"},
+ {4, nullptr, "Unknown5"},
+ {5, nullptr, "Unknown6"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<USB_DS>()->InstallAsService(sm);
+ std::make_shared<USB_HS>()->InstallAsService(sm);
+ std::make_shared<USB_PD>()->InstallAsService(sm);
+ std::make_shared<USB_PD_C>()->InstallAsService(sm);
+ std::make_shared<USB_PM>()->InstallAsService(sm);
+}
+
+} // namespace Service::USB
diff --git a/src/core/hle/service/usb/usb.h b/src/core/hle/service/usb/usb.h
new file mode 100644
index 000000000..970a11fe8
--- /dev/null
+++ b/src/core/hle/service/usb/usb.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::USB {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::USB
diff --git a/src/core/hle/service/wlan/wlan.cpp b/src/core/hle/service/wlan/wlan.cpp
new file mode 100644
index 000000000..2654594c1
--- /dev/null
+++ b/src/core/hle/service/wlan/wlan.cpp
@@ -0,0 +1,172 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+#include "core/hle/service/wlan/wlan.h"
+
+namespace Service::WLAN {
+
+class WLANInfra final : public ServiceFramework<WLANInfra> {
+public:
+ explicit WLANInfra() : ServiceFramework{"wlan:inf"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown1"},
+ {1, nullptr, "Unknown2"},
+ {2, nullptr, "GetMacAddress"},
+ {3, nullptr, "StartScan"},
+ {4, nullptr, "StopScan"},
+ {5, nullptr, "Connect"},
+ {6, nullptr, "CancelConnect"},
+ {7, nullptr, "Disconnect"},
+ {8, nullptr, "Unknown3"},
+ {9, nullptr, "Unknown4"},
+ {10, nullptr, "GetState"},
+ {11, nullptr, "GetScanResult"},
+ {12, nullptr, "GetRssi"},
+ {13, nullptr, "ChangeRxAntenna"},
+ {14, nullptr, "Unknown5"},
+ {15, nullptr, "Unknown6"},
+ {16, nullptr, "RequestWakeUp"},
+ {17, nullptr, "RequestIfUpDown"},
+ {18, nullptr, "Unknown7"},
+ {19, nullptr, "Unknown8"},
+ {20, nullptr, "Unknown9"},
+ {21, nullptr, "Unknown10"},
+ {22, nullptr, "Unknown11"},
+ {23, nullptr, "Unknown12"},
+ {24, nullptr, "Unknown13"},
+ {25, nullptr, "Unknown14"},
+ {26, nullptr, "Unknown15"},
+ {27, nullptr, "Unknown16"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class WLANLocal final : public ServiceFramework<WLANLocal> {
+public:
+ explicit WLANLocal() : ServiceFramework{"wlan:lcl"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown1"},
+ {1, nullptr, "Unknown2"},
+ {2, nullptr, "Unknown3"},
+ {3, nullptr, "Unknown4"},
+ {4, nullptr, "Unknown5"},
+ {5, nullptr, "Unknown6"},
+ {6, nullptr, "GetMacAddress"},
+ {7, nullptr, "CreateBss"},
+ {8, nullptr, "DestroyBss"},
+ {9, nullptr, "StartScan"},
+ {10, nullptr, "StopScan"},
+ {11, nullptr, "Connect"},
+ {12, nullptr, "CancelConnect"},
+ {13, nullptr, "Join"},
+ {14, nullptr, "CancelJoin"},
+ {15, nullptr, "Disconnect"},
+ {16, nullptr, "SetBeaconLostCount"},
+ {17, nullptr, "Unknown7"},
+ {18, nullptr, "Unknown8"},
+ {19, nullptr, "Unknown9"},
+ {20, nullptr, "GetBssIndicationEvent"},
+ {21, nullptr, "GetBssIndicationInfo"},
+ {22, nullptr, "GetState"},
+ {23, nullptr, "GetAllowedChannels"},
+ {24, nullptr, "AddIe"},
+ {25, nullptr, "DeleteIe"},
+ {26, nullptr, "Unknown10"},
+ {27, nullptr, "Unknown11"},
+ {28, nullptr, "CreateRxEntry"},
+ {29, nullptr, "DeleteRxEntry"},
+ {30, nullptr, "Unknown12"},
+ {31, nullptr, "Unknown13"},
+ {32, nullptr, "AddMatchingDataToRxEntry"},
+ {33, nullptr, "RemoveMatchingDataFromRxEntry"},
+ {34, nullptr, "GetScanResult"},
+ {35, nullptr, "Unknown14"},
+ {36, nullptr, "SetActionFrameWithBeacon"},
+ {37, nullptr, "CancelActionFrameWithBeacon"},
+ {38, nullptr, "CreateRxEntryForActionFrame"},
+ {39, nullptr, "DeleteRxEntryForActionFrame"},
+ {40, nullptr, "Unknown15"},
+ {41, nullptr, "Unknown16"},
+ {42, nullptr, "CancelGetActionFrame"},
+ {43, nullptr, "GetRssi"},
+ {44, nullptr, "Unknown17"},
+ {45, nullptr, "Unknown18"},
+ {46, nullptr, "Unknown19"},
+ {47, nullptr, "Unknown20"},
+ {48, nullptr, "Unknown21"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class WLANLocalGetFrame final : public ServiceFramework<WLANLocalGetFrame> {
+public:
+ explicit WLANLocalGetFrame() : ServiceFramework{"wlan:lg"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class WLANSocketGetFrame final : public ServiceFramework<WLANSocketGetFrame> {
+public:
+ explicit WLANSocketGetFrame() : ServiceFramework{"wlan:sg"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class WLANSocketManager final : public ServiceFramework<WLANSocketManager> {
+public:
+ explicit WLANSocketManager() : ServiceFramework{"wlan:soc"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown1"},
+ {1, nullptr, "Unknown2"},
+ {2, nullptr, "Unknown3"},
+ {3, nullptr, "Unknown4"},
+ {4, nullptr, "Unknown5"},
+ {5, nullptr, "Unknown6"},
+ {6, nullptr, "GetMacAddress"},
+ {7, nullptr, "SwitchTsfTimerFunction"},
+ {8, nullptr, "Unknown7"},
+ {9, nullptr, "Unknown8"},
+ {10, nullptr, "Unknown9"},
+ {11, nullptr, "Unknown10"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<WLANInfra>()->InstallAsService(sm);
+ std::make_shared<WLANLocal>()->InstallAsService(sm);
+ std::make_shared<WLANLocalGetFrame>()->InstallAsService(sm);
+ std::make_shared<WLANSocketGetFrame>()->InstallAsService(sm);
+ std::make_shared<WLANSocketManager>()->InstallAsService(sm);
+}
+
+} // namespace Service::WLAN
diff --git a/src/core/hle/service/wlan/wlan.h b/src/core/hle/service/wlan/wlan.h
new file mode 100644
index 000000000..054ea928a
--- /dev/null
+++ b/src/core/hle/service/wlan/wlan.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::WLAN {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::WLAN