summaryrefslogtreecommitdiff
path: root/src/core/hle
diff options
context:
space:
mode:
authorGravatar Emmanuel Gil Peyrot2016-09-18 09:38:01 +0900
committerGravatar Emmanuel Gil Peyrot2016-09-18 09:38:01 +0900
commitdc8479928c5aee4c6ad6fe4f59006fb604cee701 (patch)
tree569a7f13128450bbab973236615587ff00bced5f /src/core/hle
parentTravis: Import Dolphin’s clang-format hook. (diff)
downloadyuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.tar.gz
yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.tar.xz
yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.zip
Sources: Run clang-format on everything.
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/applets/applet.cpp32
-rw-r--r--src/core/hle/applets/applet.h9
-rw-r--r--src/core/hle/applets/erreula.cpp12
-rw-r--r--src/core/hle/applets/erreula.h11
-rw-r--r--src/core/hle/applets/mii_selector.cpp16
-rw-r--r--src/core/hle/applets/mii_selector.h39
-rw-r--r--src/core/hle/applets/swkbd.cpp20
-rw-r--r--src/core/hle/applets/swkbd.h13
-rw-r--r--src/core/hle/config_mem.cpp2
-rw-r--r--src/core/hle/config_mem.h25
-rw-r--r--src/core/hle/function_wrappers.h103
-rw-r--r--src/core/hle/hle.cpp6
-rw-r--r--src/core/hle/hle.h2
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp26
-rw-r--r--src/core/hle/kernel/address_arbiter.h14
-rw-r--r--src/core/hle/kernel/client_port.cpp6
-rw-r--r--src/core/hle/kernel/client_port.h22
-rw-r--r--src/core/hle/kernel/event.cpp10
-rw-r--r--src/core/hle/kernel/event.h19
-rw-r--r--src/core/hle/kernel/kernel.cpp3
-rw-r--r--src/core/hle/kernel/kernel.h66
-rw-r--r--src/core/hle/kernel/memory.cpp22
-rw-r--r--src/core/hle/kernel/memory.h1
-rw-r--r--src/core/hle/kernel/mutex.cpp6
-rw-r--r--src/core/hle/kernel/mutex.h18
-rw-r--r--src/core/hle/kernel/process.cpp65
-rw-r--r--src/core/hle/kernel/process.h50
-rw-r--r--src/core/hle/kernel/resource_limit.cpp114
-rw-r--r--src/core/hle/kernel/resource_limit.h44
-rw-r--r--src/core/hle/kernel/semaphore.cpp8
-rw-r--r--src/core/hle/kernel/semaphore.h20
-rw-r--r--src/core/hle/kernel/server_port.cpp9
-rw-r--r--src/core/hle/kernel/server_port.h20
-rw-r--r--src/core/hle/kernel/session.cpp7
-rw-r--r--src/core/hle/kernel/session.h61
-rw-r--r--src/core/hle/kernel/shared_memory.cpp75
-rw-r--r--src/core/hle/kernel/shared_memory.h59
-rw-r--r--src/core/hle/kernel/thread.cpp114
-rw-r--r--src/core/hle/kernel/thread.h78
-rw-r--r--src/core/hle/kernel/timer.cpp19
-rw-r--r--src/core/hle/kernel/timer.h22
-rw-r--r--src/core/hle/kernel/vm_manager.cpp36
-rw-r--r--src/core/hle/kernel/vm_manager.h21
-rw-r--r--src/core/hle/result.h100
-rw-r--r--src/core/hle/service/ac_u.cpp38
-rw-r--r--src/core/hle/service/am/am.cpp53
-rw-r--r--src/core/hle/service/am/am_app.cpp16
-rw-r--r--src/core/hle/service/am/am_net.cpp110
-rw-r--r--src/core/hle/service/am/am_sys.cpp44
-rw-r--r--src/core/hle/service/am/am_u.cpp70
-rw-r--r--src/core/hle/service/apt/apt.cpp148
-rw-r--r--src/core/hle/service/apt/apt.h95
-rw-r--r--src/core/hle/service/apt/apt_a.cpp57
-rw-r--r--src/core/hle/service/apt/apt_s.cpp171
-rw-r--r--src/core/hle/service/apt/apt_u.cpp177
-rw-r--r--src/core/hle/service/boss/boss.cpp2
-rw-r--r--src/core/hle/service/boss/boss_p.cpp2
-rw-r--r--src/core/hle/service/boss/boss_u.cpp8
-rw-r--r--src/core/hle/service/cam/cam.cpp75
-rw-r--r--src/core/hle/service/cam/cam.h69
-rw-r--r--src/core/hle/service/cam/cam_c.cpp4
-rw-r--r--src/core/hle/service/cam/cam_q.cpp4
-rw-r--r--src/core/hle/service/cam/cam_s.cpp4
-rw-r--r--src/core/hle/service/cam/cam_u.cpp124
-rw-r--r--src/core/hle/service/cecd/cecd.cpp9
-rw-r--r--src/core/hle/service/cecd/cecd.h10
-rw-r--r--src/core/hle/service/cecd/cecd_s.cpp4
-rw-r--r--src/core/hle/service/cecd/cecd_u.cpp6
-rw-r--r--src/core/hle/service/cfg/cfg.cpp191
-rw-r--r--src/core/hle/service/cfg/cfg.h12
-rw-r--r--src/core/hle/service/cfg/cfg_i.cpp84
-rw-r--r--src/core/hle/service/cfg/cfg_s.cpp38
-rw-r--r--src/core/hle/service/cfg/cfg_u.cpp20
-rw-r--r--src/core/hle/service/csnd_snd.cpp34
-rw-r--r--src/core/hle/service/csnd_snd.h2
-rw-r--r--src/core/hle/service/dlp/dlp.cpp2
-rw-r--r--src/core/hle/service/dlp/dlp_clnt.cpp3
-rw-r--r--src/core/hle/service/dlp/dlp_fkcl.cpp3
-rw-r--r--src/core/hle/service/dlp/dlp_srvr.cpp10
-rw-r--r--src/core/hle/service/dsp_dsp.cpp153
-rw-r--r--src/core/hle/service/err_f.cpp129
-rw-r--r--src/core/hle/service/frd/frd.cpp20
-rw-r--r--src/core/hle/service/frd/frd_a.cpp2
-rw-r--r--src/core/hle/service/frd/frd_u.cpp104
-rw-r--r--src/core/hle/service/fs/archive.cpp389
-rw-r--r--src/core/hle/service/fs/archive.h65
-rw-r--r--src/core/hle/service/fs/fs_user.cpp386
-rw-r--r--src/core/hle/service/gsp_gpu.cpp247
-rw-r--r--src/core/hle/service/gsp_gpu.h40
-rw-r--r--src/core/hle/service/gsp_lcd.cpp12
-rw-r--r--src/core/hle/service/hid/hid.cpp47
-rw-r--r--src/core/hle/service/hid/hid.h69
-rw-r--r--src/core/hle/service/hid/hid_spvr.cpp18
-rw-r--r--src/core/hle/service/hid/hid_user.cpp18
-rw-r--r--src/core/hle/service/http_c.cpp100
-rw-r--r--src/core/hle/service/ir/ir.cpp28
-rw-r--r--src/core/hle/service/ir/ir_rst.cpp8
-rw-r--r--src/core/hle/service/ir/ir_u.cpp27
-rw-r--r--src/core/hle/service/ir/ir_user.cpp50
-rw-r--r--src/core/hle/service/ldr_ro/cro_helper.cpp375
-rw-r--r--src/core/hle/service/ldr_ro/cro_helper.h145
-rw-r--r--src/core/hle/service/ldr_ro/ldr_ro.cpp208
-rw-r--r--src/core/hle/service/ldr_ro/memory_synchronizer.cpp5
-rw-r--r--src/core/hle/service/mic_u.cpp32
-rw-r--r--src/core/hle/service/ndm/ndm.cpp20
-rw-r--r--src/core/hle/service/ndm/ndm.h42
-rw-r--r--src/core/hle/service/ndm/ndm_u.cpp44
-rw-r--r--src/core/hle/service/news/news.cpp2
-rw-r--r--src/core/hle/service/news/news_s.cpp26
-rw-r--r--src/core/hle/service/news/news_u.cpp2
-rw-r--r--src/core/hle/service/nim/nim.cpp2
-rw-r--r--src/core/hle/service/nim/nim_aoc.cpp16
-rw-r--r--src/core/hle/service/nim/nim_s.cpp9
-rw-r--r--src/core/hle/service/nim/nim_u.cpp13
-rw-r--r--src/core/hle/service/ns_s.cpp30
-rw-r--r--src/core/hle/service/nwm_uds.cpp82
-rw-r--r--src/core/hle/service/pm_app.cpp24
-rw-r--r--src/core/hle/service/ptm/ptm.cpp31
-rw-r--r--src/core/hle/service/ptm/ptm.h21
-rw-r--r--src/core/hle/service/ptm/ptm_play.cpp8
-rw-r--r--src/core/hle/service/ptm/ptm_play.h6
-rw-r--r--src/core/hle/service/ptm/ptm_sysm.cpp62
-rw-r--r--src/core/hle/service/ptm/ptm_u.cpp28
-rw-r--r--src/core/hle/service/service.cpp23
-rw-r--r--src/core/hle/service/service.h10
-rw-r--r--src/core/hle/service/soc_u.cpp378
-rw-r--r--src/core/hle/service/srv.cpp50
-rw-r--r--src/core/hle/service/ssl_c.cpp44
-rw-r--r--src/core/hle/service/y2r_u.cpp155
-rw-r--r--src/core/hle/shared_page.cpp7
-rw-r--r--src/core/hle/shared_page.h23
-rw-r--r--src/core/hle/svc.cpp512
132 files changed, 4009 insertions, 3462 deletions
diff --git a/src/core/hle/applets/applet.cpp b/src/core/hle/applets/applet.cpp
index ccf35fa07..2b4bd939d 100644
--- a/src/core/hle/applets/applet.cpp
+++ b/src/core/hle/applets/applet.cpp
@@ -23,23 +23,24 @@
23// Specializes std::hash for AppletId, so that we can use it in std::unordered_map. 23// Specializes std::hash for AppletId, so that we can use it in std::unordered_map.
24// Workaround for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970 24// Workaround for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970
25namespace std { 25namespace std {
26 template <> 26template <>
27 struct hash<Service::APT::AppletId> { 27struct hash<Service::APT::AppletId> {
28 typedef Service::APT::AppletId argument_type; 28 typedef Service::APT::AppletId argument_type;
29 typedef std::size_t result_type; 29 typedef std::size_t result_type;
30 30
31 result_type operator()(const argument_type& id_code) const { 31 result_type operator()(const argument_type& id_code) const {
32 typedef std::underlying_type<argument_type>::type Type; 32 typedef std::underlying_type<argument_type>::type Type;
33 return std::hash<Type>()(static_cast<Type>(id_code)); 33 return std::hash<Type>()(static_cast<Type>(id_code));
34 } 34 }
35 }; 35};
36} 36}
37 37
38namespace HLE { 38namespace HLE {
39namespace Applets { 39namespace Applets {
40 40
41static std::unordered_map<Service::APT::AppletId, std::shared_ptr<Applet>> applets; 41static std::unordered_map<Service::APT::AppletId, std::shared_ptr<Applet>> applets;
42static u32 applet_update_event = -1; ///< The CoreTiming event identifier for the Applet update callback. 42static u32 applet_update_event =
43 -1; ///< The CoreTiming event identifier for the Applet update callback.
43/// The interval at which the Applet update callback will be called, 16.6ms 44/// The interval at which the Applet update callback will be called, 16.6ms
44static const u64 applet_update_interval_us = 16666; 45static const u64 applet_update_interval_us = 16666;
45 46
@@ -60,7 +61,8 @@ ResultCode Applet::Create(Service::APT::AppletId id) {
60 default: 61 default:
61 LOG_ERROR(Service_APT, "Could not create applet %u", id); 62 LOG_ERROR(Service_APT, "Could not create applet %u", id);
62 // TODO(Subv): Find the right error code 63 // TODO(Subv): Find the right error code
63 return ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotSupported, ErrorLevel::Permanent); 64 return ResultCode(ErrorDescription::NotFound, ErrorModule::Applet,
65 ErrorSummary::NotSupported, ErrorLevel::Permanent);
64 } 66 }
65 67
66 return RESULT_SUCCESS; 68 return RESULT_SUCCESS;
@@ -84,7 +86,7 @@ static void AppletUpdateEvent(u64 applet_id, int cycles_late) {
84 // If the applet is still running after the last update, reschedule the event 86 // If the applet is still running after the last update, reschedule the event
85 if (applet->IsRunning()) { 87 if (applet->IsRunning()) {
86 CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us) - cycles_late, 88 CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us) - cycles_late,
87 applet_update_event, applet_id); 89 applet_update_event, applet_id);
88 } else { 90 } else {
89 // Otherwise the applet has terminated, in which case we should clean it up 91 // Otherwise the applet has terminated, in which case we should clean it up
90 applets[id] = nullptr; 92 applets[id] = nullptr;
@@ -96,7 +98,8 @@ ResultCode Applet::Start(const Service::APT::AppletStartupParameter& parameter)
96 if (result.IsError()) 98 if (result.IsError())
97 return result; 99 return result;
98 // Schedule the update event 100 // Schedule the update event
99 CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us), applet_update_event, static_cast<u64>(id)); 101 CoreTiming::ScheduleEvent(usToCycles(applet_update_interval_us), applet_update_event,
102 static_cast<u64>(id));
100 return result; 103 return result;
101} 104}
102 105
@@ -116,6 +119,5 @@ void Init() {
116void Shutdown() { 119void Shutdown() {
117 CoreTiming::RemoveEvent(applet_update_event); 120 CoreTiming::RemoveEvent(applet_update_event);
118} 121}
119
120} 122}
121} // namespace 123} // namespace
diff --git a/src/core/hle/applets/applet.h b/src/core/hle/applets/applet.h
index 754c6f7db..350a58594 100644
--- a/src/core/hle/applets/applet.h
+++ b/src/core/hle/applets/applet.h
@@ -14,8 +14,10 @@ namespace Applets {
14 14
15class Applet { 15class Applet {
16public: 16public:
17 virtual ~Applet() { } 17 virtual ~Applet() {
18 Applet(Service::APT::AppletId id) : id(id) { } 18 }
19 Applet(Service::APT::AppletId id) : id(id) {
20 }
19 21
20 /** 22 /**
21 * Creates an instance of the Applet subclass identified by the parameter. 23 * Creates an instance of the Applet subclass identified by the parameter.
@@ -64,7 +66,7 @@ protected:
64 */ 66 */
65 virtual ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) = 0; 67 virtual ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) = 0;
66 68
67 Service::APT::AppletId id; ///< Id of this Applet 69 Service::APT::AppletId id; ///< Id of this Applet
68 std::shared_ptr<std::vector<u8>> heap_memory; ///< Heap memory for this Applet 70 std::shared_ptr<std::vector<u8>> heap_memory; ///< Heap memory for this Applet
69}; 71};
70 72
@@ -76,6 +78,5 @@ void Init();
76 78
77/// Shuts down the HLE applets 79/// Shuts down the HLE applets
78void Shutdown(); 80void Shutdown();
79
80} 81}
81} // namespace 82} // namespace
diff --git a/src/core/hle/applets/erreula.cpp b/src/core/hle/applets/erreula.cpp
index 92a4b2323..144d6a152 100644
--- a/src/core/hle/applets/erreula.cpp
+++ b/src/core/hle/applets/erreula.cpp
@@ -18,7 +18,8 @@ ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& param
18 return ResultCode(-1); 18 return ResultCode(-1);
19 } 19 }
20 20
21 // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory. 21 // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared
22 // memory.
22 // Create the SharedMemory that will hold the framebuffer data 23 // Create the SharedMemory that will hold the framebuffer data
23 Service::APT::CaptureBufferInfo capture_info; 24 Service::APT::CaptureBufferInfo capture_info;
24 ASSERT(sizeof(capture_info) == parameter.buffer.size()); 25 ASSERT(sizeof(capture_info) == parameter.buffer.size());
@@ -30,9 +31,9 @@ ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& param
30 // Allocate a heap block of the required size for this applet. 31 // Allocate a heap block of the required size for this applet.
31 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); 32 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
32 // Create a SharedMemory that directly points to this heap block. 33 // Create a SharedMemory that directly points to this heap block.
33 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(heap_memory, 0, heap_memory->size(), 34 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(
34 MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 35 heap_memory, 0, heap_memory->size(), MemoryPermission::ReadWrite,
35 "ErrEula Memory"); 36 MemoryPermission::ReadWrite, "ErrEula Memory");
36 37
37 // Send the response message with the newly created SharedMemory 38 // Send the response message with the newly created SharedMemory
38 Service::APT::MessageParameter result; 39 Service::APT::MessageParameter result;
@@ -49,7 +50,8 @@ ResultCode ErrEula::ReceiveParameter(const Service::APT::MessageParameter& param
49ResultCode ErrEula::StartImpl(const Service::APT::AppletStartupParameter& parameter) { 50ResultCode ErrEula::StartImpl(const Service::APT::AppletStartupParameter& parameter) {
50 started = true; 51 started = true;
51 52
52 // TODO(Subv): Set the expected fields in the response buffer before resending it to the application. 53 // TODO(Subv): Set the expected fields in the response buffer before resending it to the
54 // application.
53 // TODO(Subv): Reverse the parameter format for the ErrEula applet 55 // TODO(Subv): Reverse the parameter format for the ErrEula applet
54 56
55 // Let the application know that we're closing 57 // Let the application know that we're closing
diff --git a/src/core/hle/applets/erreula.h b/src/core/hle/applets/erreula.h
index 9fe72ae07..dd1d1aee4 100644
--- a/src/core/hle/applets/erreula.h
+++ b/src/core/hle/applets/erreula.h
@@ -12,16 +12,21 @@ namespace Applets {
12 12
13class ErrEula final : public Applet { 13class ErrEula final : public Applet {
14public: 14public:
15 explicit ErrEula(Service::APT::AppletId id): Applet(id) { } 15 explicit ErrEula(Service::APT::AppletId id) : Applet(id) {
16 }
16 17
17 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; 18 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override;
18 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; 19 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override;
19 void Update() override; 20 void Update() override;
20 bool IsRunning() const override { return started; } 21 bool IsRunning() const override {
22 return started;
23 }
21 24
22 /// This SharedMemory will be created when we receive the LibAppJustStarted message. 25 /// This SharedMemory will be created when we receive the LibAppJustStarted message.
23 /// It holds the framebuffer info retrieved by the application with GSPGPU::ImportDisplayCaptureInfo 26 /// It holds the framebuffer info retrieved by the application with
27 /// GSPGPU::ImportDisplayCaptureInfo
24 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; 28 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory;
29
25private: 30private:
26 /// Whether this applet is currently running instead of the host application or not. 31 /// Whether this applet is currently running instead of the host application or not.
27 bool started = false; 32 bool started = false;
diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp
index 77f01d208..19e603eda 100644
--- a/src/core/hle/applets/mii_selector.cpp
+++ b/src/core/hle/applets/mii_selector.cpp
@@ -29,7 +29,8 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p
29 return ResultCode(-1); 29 return ResultCode(-1);
30 } 30 }
31 31
32 // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory. 32 // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared
33 // memory.
33 // Create the SharedMemory that will hold the framebuffer data 34 // Create the SharedMemory that will hold the framebuffer data
34 Service::APT::CaptureBufferInfo capture_info; 35 Service::APT::CaptureBufferInfo capture_info;
35 ASSERT(sizeof(capture_info) == parameter.buffer.size()); 36 ASSERT(sizeof(capture_info) == parameter.buffer.size());
@@ -40,9 +41,9 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p
40 // Allocate a heap block of the required size for this applet. 41 // Allocate a heap block of the required size for this applet.
41 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); 42 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
42 // Create a SharedMemory that directly points to this heap block. 43 // Create a SharedMemory that directly points to this heap block.
43 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(heap_memory, 0, heap_memory->size(), 44 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(
44 MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 45 heap_memory, 0, heap_memory->size(), MemoryPermission::ReadWrite,
45 "MiiSelector Memory"); 46 MemoryPermission::ReadWrite, "MiiSelector Memory");
46 47
47 // Send the response message with the newly created SharedMemory 48 // Send the response message with the newly created SharedMemory
48 Service::APT::MessageParameter result; 49 Service::APT::MessageParameter result;
@@ -59,12 +60,14 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p
59ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& parameter) { 60ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& parameter) {
60 started = true; 61 started = true;
61 62
62 // TODO(Subv): Set the expected fields in the response buffer before resending it to the application. 63 // TODO(Subv): Set the expected fields in the response buffer before resending it to the
64 // application.
63 // TODO(Subv): Reverse the parameter format for the Mii Selector 65 // TODO(Subv): Reverse the parameter format for the Mii Selector
64 66
65 memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); 67 memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
66 68
67 // TODO(Subv): Find more about this structure, result code 0 is enough to let most games continue. 69 // TODO(Subv): Find more about this structure, result code 0 is enough to let most games
70 // continue.
68 MiiResult result; 71 MiiResult result;
69 memset(&result, 0, sizeof(result)); 72 memset(&result, 0, sizeof(result));
70 result.result_code = 0; 73 result.result_code = 0;
@@ -84,6 +87,5 @@ ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& pa
84 87
85void MiiSelector::Update() { 88void MiiSelector::Update() {
86} 89}
87
88} 90}
89} // namespace 91} // namespace
diff --git a/src/core/hle/applets/mii_selector.h b/src/core/hle/applets/mii_selector.h
index 24e8e721d..dba4abc8d 100644
--- a/src/core/hle/applets/mii_selector.h
+++ b/src/core/hle/applets/mii_selector.h
@@ -4,8 +4,8 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h"
8#include "common/common_funcs.h" 7#include "common/common_funcs.h"
8#include "common/common_types.h"
9 9
10#include "core/hle/applets/applet.h" 10#include "core/hle/applets/applet.h"
11#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
@@ -17,28 +17,30 @@ namespace HLE {
17namespace Applets { 17namespace Applets {
18 18
19struct MiiConfig { 19struct MiiConfig {
20 u8 unk_000; 20 u8 unk_000;
21 u8 unk_001; 21 u8 unk_001;
22 u8 unk_002; 22 u8 unk_002;
23 u8 unk_003; 23 u8 unk_003;
24 u8 unk_004; 24 u8 unk_004;
25 INSERT_PADDING_BYTES(3); 25 INSERT_PADDING_BYTES(3);
26 u16 unk_008; 26 u16 unk_008;
27 INSERT_PADDING_BYTES(0x82); 27 INSERT_PADDING_BYTES(0x82);
28 u8 unk_08C; 28 u8 unk_08C;
29 INSERT_PADDING_BYTES(3); 29 INSERT_PADDING_BYTES(3);
30 u16 unk_090; 30 u16 unk_090;
31 INSERT_PADDING_BYTES(2); 31 INSERT_PADDING_BYTES(2);
32 u32 unk_094; 32 u32 unk_094;
33 u16 unk_098; 33 u16 unk_098;
34 u8 unk_09A[0x64]; 34 u8 unk_09A[0x64];
35 u8 unk_0FE; 35 u8 unk_0FE;
36 u8 unk_0FF; 36 u8 unk_0FF;
37 u32 unk_100; 37 u32 unk_100;
38}; 38};
39 39
40static_assert(sizeof(MiiConfig) == 0x104, "MiiConfig structure has incorrect size"); 40static_assert(sizeof(MiiConfig) == 0x104, "MiiConfig structure has incorrect size");
41#define ASSERT_REG_POSITION(field_name, position) static_assert(offsetof(MiiConfig, field_name) == position, "Field "#field_name" has invalid position") 41#define ASSERT_REG_POSITION(field_name, position) \
42 static_assert(offsetof(MiiConfig, field_name) == position, \
43 "Field " #field_name " has invalid position")
42ASSERT_REG_POSITION(unk_008, 0x08); 44ASSERT_REG_POSITION(unk_008, 0x08);
43ASSERT_REG_POSITION(unk_08C, 0x8C); 45ASSERT_REG_POSITION(unk_08C, 0x8C);
44ASSERT_REG_POSITION(unk_090, 0x90); 46ASSERT_REG_POSITION(unk_090, 0x90);
@@ -55,22 +57,28 @@ struct MiiResult {
55 INSERT_PADDING_BYTES(2); 57 INSERT_PADDING_BYTES(2);
56}; 58};
57static_assert(sizeof(MiiResult) == 0x84, "MiiResult structure has incorrect size"); 59static_assert(sizeof(MiiResult) == 0x84, "MiiResult structure has incorrect size");
58#define ASSERT_REG_POSITION(field_name, position) static_assert(offsetof(MiiResult, field_name) == position, "Field "#field_name" has invalid position") 60#define ASSERT_REG_POSITION(field_name, position) \
61 static_assert(offsetof(MiiResult, field_name) == position, \
62 "Field " #field_name " has invalid position")
59ASSERT_REG_POSITION(unk_0C, 0x0C); 63ASSERT_REG_POSITION(unk_0C, 0x0C);
60ASSERT_REG_POSITION(unk_6C, 0x6C); 64ASSERT_REG_POSITION(unk_6C, 0x6C);
61#undef ASSERT_REG_POSITION 65#undef ASSERT_REG_POSITION
62 66
63class MiiSelector final : public Applet { 67class MiiSelector final : public Applet {
64public: 68public:
65 MiiSelector(Service::APT::AppletId id) : Applet(id), started(false) { } 69 MiiSelector(Service::APT::AppletId id) : Applet(id), started(false) {
70 }
66 71
67 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; 72 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override;
68 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; 73 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override;
69 void Update() override; 74 void Update() override;
70 bool IsRunning() const override { return started; } 75 bool IsRunning() const override {
76 return started;
77 }
71 78
72 /// This SharedMemory will be created when we receive the LibAppJustStarted message. 79 /// This SharedMemory will be created when we receive the LibAppJustStarted message.
73 /// It holds the framebuffer info retrieved by the application with GSPGPU::ImportDisplayCaptureInfo 80 /// It holds the framebuffer info retrieved by the application with
81 /// GSPGPU::ImportDisplayCaptureInfo
74 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; 82 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory;
75 83
76 /// Whether this applet is currently running instead of the host application or not. 84 /// Whether this applet is currently running instead of the host application or not.
@@ -78,6 +86,5 @@ public:
78 86
79 MiiConfig config; 87 MiiConfig config;
80}; 88};
81
82} 89}
83} // namespace 90} // namespace
diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp
index d87bf3d57..cf2775968 100644
--- a/src/core/hle/applets/swkbd.cpp
+++ b/src/core/hle/applets/swkbd.cpp
@@ -12,9 +12,9 @@
12#include "core/hle/applets/swkbd.h" 12#include "core/hle/applets/swkbd.h"
13#include "core/hle/kernel/kernel.h" 13#include "core/hle/kernel/kernel.h"
14#include "core/hle/kernel/shared_memory.h" 14#include "core/hle/kernel/shared_memory.h"
15#include "core/hle/service/hid/hid.h"
16#include "core/hle/service/gsp_gpu.h"
17#include "core/hle/result.h" 15#include "core/hle/result.h"
16#include "core/hle/service/gsp_gpu.h"
17#include "core/hle/service/hid/hid.h"
18#include "core/memory.h" 18#include "core/memory.h"
19 19
20#include "video_core/video_core.h" 20#include "video_core/video_core.h"
@@ -32,7 +32,8 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con
32 return ResultCode(-1); 32 return ResultCode(-1);
33 } 33 }
34 34
35 // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory. 35 // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared
36 // memory.
36 // Create the SharedMemory that will hold the framebuffer data 37 // Create the SharedMemory that will hold the framebuffer data
37 Service::APT::CaptureBufferInfo capture_info; 38 Service::APT::CaptureBufferInfo capture_info;
38 ASSERT(sizeof(capture_info) == parameter.buffer.size()); 39 ASSERT(sizeof(capture_info) == parameter.buffer.size());
@@ -43,9 +44,9 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con
43 // Allocate a heap block of the required size for this applet. 44 // Allocate a heap block of the required size for this applet.
44 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size); 45 heap_memory = std::make_shared<std::vector<u8>>(capture_info.size);
45 // Create a SharedMemory that directly points to this heap block. 46 // Create a SharedMemory that directly points to this heap block.
46 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(heap_memory, 0, heap_memory->size(), 47 framebuffer_memory = Kernel::SharedMemory::CreateForApplet(
47 MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 48 heap_memory, 0, heap_memory->size(), MemoryPermission::ReadWrite,
48 "SoftwareKeyboard Memory"); 49 MemoryPermission::ReadWrite, "SoftwareKeyboard Memory");
49 50
50 // Send the response message with the newly created SharedMemory 51 // Send the response message with the newly created SharedMemory
51 Service::APT::MessageParameter result; 52 Service::APT::MessageParameter result;
@@ -60,10 +61,12 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con
60} 61}
61 62
62ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter const& parameter) { 63ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter const& parameter) {
63 ASSERT_MSG(parameter.buffer.size() == sizeof(config), "The size of the parameter (SoftwareKeyboardConfig) is wrong"); 64 ASSERT_MSG(parameter.buffer.size() == sizeof(config),
65 "The size of the parameter (SoftwareKeyboardConfig) is wrong");
64 66
65 memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); 67 memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
66 text_memory = boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object); 68 text_memory =
69 boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object);
67 70
68 // TODO(Subv): Verify if this is the correct behavior 71 // TODO(Subv): Verify if this is the correct behavior
69 memset(text_memory->GetPointer(), 0, text_memory->size); 72 memset(text_memory->GetPointer(), 0, text_memory->size);
@@ -115,6 +118,5 @@ void SoftwareKeyboard::Finalize() {
115 118
116 started = false; 119 started = false;
117} 120}
118
119} 121}
120} // namespace 122} // namespace
diff --git a/src/core/hle/applets/swkbd.h b/src/core/hle/applets/swkbd.h
index cf26a8fb7..f50673912 100644
--- a/src/core/hle/applets/swkbd.h
+++ b/src/core/hle/applets/swkbd.h
@@ -4,8 +4,8 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h"
8#include "common/common_funcs.h" 7#include "common/common_funcs.h"
8#include "common/common_types.h"
9 9
10#include "core/hle/applets/applet.h" 10#include "core/hle/applets/applet.h"
11#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
@@ -53,12 +53,15 @@ static_assert(sizeof(SoftwareKeyboardConfig) == 0x400, "Software Keyboard Config
53 53
54class SoftwareKeyboard final : public Applet { 54class SoftwareKeyboard final : public Applet {
55public: 55public:
56 SoftwareKeyboard(Service::APT::AppletId id) : Applet(id), started(false) { } 56 SoftwareKeyboard(Service::APT::AppletId id) : Applet(id), started(false) {
57 }
57 58
58 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override; 59 ResultCode ReceiveParameter(const Service::APT::MessageParameter& parameter) override;
59 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override; 60 ResultCode StartImpl(const Service::APT::AppletStartupParameter& parameter) override;
60 void Update() override; 61 void Update() override;
61 bool IsRunning() const override { return started; } 62 bool IsRunning() const override {
63 return started;
64 }
62 65
63 /** 66 /**
64 * Draws a keyboard to the current bottom screen framebuffer. 67 * Draws a keyboard to the current bottom screen framebuffer.
@@ -72,7 +75,8 @@ public:
72 void Finalize(); 75 void Finalize();
73 76
74 /// This SharedMemory will be created when we receive the LibAppJustStarted message. 77 /// This SharedMemory will be created when we receive the LibAppJustStarted message.
75 /// It holds the framebuffer info retrieved by the application with GSPGPU::ImportDisplayCaptureInfo 78 /// It holds the framebuffer info retrieved by the application with
79 /// GSPGPU::ImportDisplayCaptureInfo
76 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory; 80 Kernel::SharedPtr<Kernel::SharedMemory> framebuffer_memory;
77 81
78 /// SharedMemory where the output text will be stored 82 /// SharedMemory where the output text will be stored
@@ -84,6 +88,5 @@ public:
84 /// Whether this applet is currently running instead of the host application or not. 88 /// Whether this applet is currently running instead of the host application or not.
85 bool started; 89 bool started;
86}; 90};
87
88} 91}
89} // namespace 92} // namespace
diff --git a/src/core/hle/config_mem.cpp b/src/core/hle/config_mem.cpp
index ccd73cfcb..00efc179e 100644
--- a/src/core/hle/config_mem.cpp
+++ b/src/core/hle/config_mem.cpp
@@ -2,8 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstring>
6#include "core/hle/config_mem.h" 5#include "core/hle/config_mem.h"
6#include <cstring>
7 7
8//////////////////////////////////////////////////////////////////////////////////////////////////// 8////////////////////////////////////////////////////////////////////////////////////////////////////
9 9
diff --git a/src/core/hle/config_mem.h b/src/core/hle/config_mem.h
index 24a1254f2..50664dac6 100644
--- a/src/core/hle/config_mem.h
+++ b/src/core/hle/config_mem.h
@@ -20,16 +20,16 @@
20namespace ConfigMem { 20namespace ConfigMem {
21 21
22struct ConfigMemDef { 22struct ConfigMemDef {
23 u8 kernel_unk; // 0 23 u8 kernel_unk; // 0
24 u8 kernel_version_rev; // 1 24 u8 kernel_version_rev; // 1
25 u8 kernel_version_min; // 2 25 u8 kernel_version_min; // 2
26 u8 kernel_version_maj; // 3 26 u8 kernel_version_maj; // 3
27 u32_le update_flag; // 4 27 u32_le update_flag; // 4
28 u64_le ns_tid; // 8 28 u64_le ns_tid; // 8
29 u32_le sys_core_ver; // 10 29 u32_le sys_core_ver; // 10
30 u8 unit_info; // 14 30 u8 unit_info; // 14
31 u8 boot_firm; // 15 31 u8 boot_firm; // 15
32 u8 prev_firm; // 16 32 u8 prev_firm; // 16
33 INSERT_PADDING_BYTES(0x1); // 17 33 INSERT_PADDING_BYTES(0x1); // 17
34 u32_le ctr_sdk_ver; // 18 34 u32_le ctr_sdk_ver; // 18
35 INSERT_PADDING_BYTES(0x30 - 0x1C); // 1C 35 INSERT_PADDING_BYTES(0x30 - 0x1C); // 1C
@@ -39,15 +39,16 @@ struct ConfigMemDef {
39 u32_le sys_mem_alloc; // 44 39 u32_le sys_mem_alloc; // 44
40 u32_le base_mem_alloc; // 48 40 u32_le base_mem_alloc; // 48
41 INSERT_PADDING_BYTES(0x60 - 0x4C); // 4C 41 INSERT_PADDING_BYTES(0x60 - 0x4C); // 4C
42 u8 firm_unk; // 60 42 u8 firm_unk; // 60
43 u8 firm_version_rev; // 61 43 u8 firm_version_rev; // 61
44 u8 firm_version_min; // 62 44 u8 firm_version_min; // 62
45 u8 firm_version_maj; // 63 45 u8 firm_version_maj; // 63
46 u32_le firm_sys_core_ver; // 64 46 u32_le firm_sys_core_ver; // 64
47 u32_le firm_ctr_sdk_ver; // 68 47 u32_le firm_ctr_sdk_ver; // 68
48 INSERT_PADDING_BYTES(0x1000 - 0x6C); // 6C 48 INSERT_PADDING_BYTES(0x1000 - 0x6C); // 6C
49}; 49};
50static_assert(sizeof(ConfigMemDef) == Memory::CONFIG_MEMORY_SIZE, "Config Memory structure size is wrong"); 50static_assert(sizeof(ConfigMemDef) == Memory::CONFIG_MEMORY_SIZE,
51 "Config Memory structure size is wrong");
51 52
52extern ConfigMemDef config_mem; 53extern ConfigMemDef config_mem;
53 54
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h
index 8839ce482..d5d989c29 100644
--- a/src/core/hle/function_wrappers.h
+++ b/src/core/hle/function_wrappers.h
@@ -7,14 +7,14 @@
7#include "common/common_types.h" 7#include "common/common_types.h"
8 8
9#include "core/arm/arm_interface.h" 9#include "core/arm/arm_interface.h"
10#include "core/memory.h"
11#include "core/hle/hle.h" 10#include "core/hle/hle.h"
12#include "core/hle/result.h" 11#include "core/hle/result.h"
13#include "core/hle/svc.h" 12#include "core/hle/svc.h"
13#include "core/memory.h"
14 14
15namespace HLE { 15namespace HLE {
16 16
17#define PARAM(n) Core::g_app_core->GetReg(n) 17#define PARAM(n) Core::g_app_core->GetReg(n)
18 18
19/// An invalid result code that is meant to be overwritten when a thread resumes from waiting 19/// An invalid result code that is meant to be overwritten when a thread resumes from waiting
20static const ResultCode RESULT_INVALID(0xDEADC0DE); 20static const ResultCode RESULT_INVALID(0xDEADC0DE);
@@ -40,28 +40,33 @@ static inline void FuncReturn64(u64 res) {
40//////////////////////////////////////////////////////////////////////////////////////////////////// 40////////////////////////////////////////////////////////////////////////////////////////////////////
41// Function wrappers that return type ResultCode 41// Function wrappers that return type ResultCode
42 42
43template<ResultCode func(u32, u32, u32, u32)> void Wrap() { 43template <ResultCode func(u32, u32, u32, u32)>
44void Wrap() {
44 FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)).raw); 45 FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)).raw);
45} 46}
46 47
47template<ResultCode func(u32*, u32, u32, u32, u32, u32)> void Wrap(){ 48template <ResultCode func(u32*, u32, u32, u32, u32, u32)>
49void Wrap() {
48 u32 param_1 = 0; 50 u32 param_1 = 0;
49 u32 retval = func(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; 51 u32 retval = func(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw;
50 Core::g_app_core->SetReg(1, param_1); 52 Core::g_app_core->SetReg(1, param_1);
51 FuncReturn(retval); 53 FuncReturn(retval);
52} 54}
53 55
54template<ResultCode func(u32*, s32, u32, u32, u32, s32)> void Wrap() { 56template <ResultCode func(u32*, s32, u32, u32, u32, s32)>
57void Wrap() {
55 u32 param_1 = 0; 58 u32 param_1 = 0;
56 u32 retval = func(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; 59 u32 retval = func(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw;
57 Core::g_app_core->SetReg(1, param_1); 60 Core::g_app_core->SetReg(1, param_1);
58 FuncReturn(retval); 61 FuncReturn(retval);
59} 62}
60 63
61template<ResultCode func(s32*, u32*, s32, bool, s64)> void Wrap() { 64template <ResultCode func(s32*, u32*, s32, bool, s64)>
65void Wrap() {
62 s32 param_1 = 0; 66 s32 param_1 = 0;
63 s32 retval = func(&param_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2), 67 s32 retval = func(&param_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2),
64 (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0))).raw; 68 (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0)))
69 .raw;
65 70
66 if (retval != RESULT_INVALID.raw) { 71 if (retval != RESULT_INVALID.raw) {
67 Core::g_app_core->SetReg(1, (u32)param_1); 72 Core::g_app_core->SetReg(1, (u32)param_1);
@@ -69,18 +74,22 @@ template<ResultCode func(s32*, u32*, s32, bool, s64)> void Wrap() {
69 } 74 }
70} 75}
71 76
72template<ResultCode func(u32, u32, u32, u32, s64)> void Wrap() { 77template <ResultCode func(u32, u32, u32, u32, s64)>
73 FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), (((s64)PARAM(5) << 32) | PARAM(4))).raw); 78void Wrap() {
79 FuncReturn(
80 func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), (((s64)PARAM(5) << 32) | PARAM(4))).raw);
74} 81}
75 82
76template<ResultCode func(u32*)> void Wrap(){ 83template <ResultCode func(u32*)>
84void Wrap() {
77 u32 param_1 = 0; 85 u32 param_1 = 0;
78 u32 retval = func(&param_1).raw; 86 u32 retval = func(&param_1).raw;
79 Core::g_app_core->SetReg(1, param_1); 87 Core::g_app_core->SetReg(1, param_1);
80 FuncReturn(retval); 88 FuncReturn(retval);
81} 89}
82 90
83template<ResultCode func(u32, s64)> void Wrap() { 91template <ResultCode func(u32, s64)>
92void Wrap() {
84 s32 retval = func(PARAM(0), (((s64)PARAM(3) << 32) | PARAM(2))).raw; 93 s32 retval = func(PARAM(0), (((s64)PARAM(3) << 32) | PARAM(2))).raw;
85 94
86 if (retval != RESULT_INVALID.raw) { 95 if (retval != RESULT_INVALID.raw) {
@@ -88,7 +97,8 @@ template<ResultCode func(u32, s64)> void Wrap() {
88 } 97 }
89} 98}
90 99
91template<ResultCode func(MemoryInfo*, PageInfo*, u32)> void Wrap() { 100template <ResultCode func(MemoryInfo*, PageInfo*, u32)>
101void Wrap() {
92 MemoryInfo memory_info = {}; 102 MemoryInfo memory_info = {};
93 PageInfo page_info = {}; 103 PageInfo page_info = {};
94 u32 retval = func(&memory_info, &page_info, PARAM(2)).raw; 104 u32 retval = func(&memory_info, &page_info, PARAM(2)).raw;
@@ -100,7 +110,8 @@ template<ResultCode func(MemoryInfo*, PageInfo*, u32)> void Wrap() {
100 FuncReturn(retval); 110 FuncReturn(retval);
101} 111}
102 112
103template<ResultCode func(MemoryInfo*, PageInfo*, Handle, u32)> void Wrap() { 113template <ResultCode func(MemoryInfo*, PageInfo*, Handle, u32)>
114void Wrap() {
104 MemoryInfo memory_info = {}; 115 MemoryInfo memory_info = {};
105 PageInfo page_info = {}; 116 PageInfo page_info = {};
106 u32 retval = func(&memory_info, &page_info, PARAM(2), PARAM(3)).raw; 117 u32 retval = func(&memory_info, &page_info, PARAM(2), PARAM(3)).raw;
@@ -112,55 +123,65 @@ template<ResultCode func(MemoryInfo*, PageInfo*, Handle, u32)> void Wrap() {
112 FuncReturn(retval); 123 FuncReturn(retval);
113} 124}
114 125
115template<ResultCode func(s32*, u32)> void Wrap(){ 126template <ResultCode func(s32*, u32)>
127void Wrap() {
116 s32 param_1 = 0; 128 s32 param_1 = 0;
117 u32 retval = func(&param_1, PARAM(1)).raw; 129 u32 retval = func(&param_1, PARAM(1)).raw;
118 Core::g_app_core->SetReg(1, param_1); 130 Core::g_app_core->SetReg(1, param_1);
119 FuncReturn(retval); 131 FuncReturn(retval);
120} 132}
121 133
122template<ResultCode func(u32, s32)> void Wrap() { 134template <ResultCode func(u32, s32)>
135void Wrap() {
123 FuncReturn(func(PARAM(0), (s32)PARAM(1)).raw); 136 FuncReturn(func(PARAM(0), (s32)PARAM(1)).raw);
124} 137}
125 138
126template<ResultCode func(u32*, u32)> void Wrap(){ 139template <ResultCode func(u32*, u32)>
140void Wrap() {
127 u32 param_1 = 0; 141 u32 param_1 = 0;
128 u32 retval = func(&param_1, PARAM(1)).raw; 142 u32 retval = func(&param_1, PARAM(1)).raw;
129 Core::g_app_core->SetReg(1, param_1); 143 Core::g_app_core->SetReg(1, param_1);
130 FuncReturn(retval); 144 FuncReturn(retval);
131} 145}
132 146
133template<ResultCode func(u32)> void Wrap() { 147template <ResultCode func(u32)>
148void Wrap() {
134 FuncReturn(func(PARAM(0)).raw); 149 FuncReturn(func(PARAM(0)).raw);
135} 150}
136 151
137template<ResultCode func(s64*, u32, u32*, u32)> void Wrap(){ 152template <ResultCode func(s64*, u32, u32*, u32)>
138 FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), (u32*)Memory::GetPointer(PARAM(2)), 153void Wrap() {
139 (s32)PARAM(3)).raw); 154 FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1),
155 (u32*)Memory::GetPointer(PARAM(2)), (s32)PARAM(3))
156 .raw);
140} 157}
141 158
142template<ResultCode func(u32*, const char*)> void Wrap() { 159template <ResultCode func(u32*, const char*)>
160void Wrap() {
143 u32 param_1 = 0; 161 u32 param_1 = 0;
144 u32 retval = func(&param_1, (char*)Memory::GetPointer(PARAM(1))).raw; 162 u32 retval = func(&param_1, (char*)Memory::GetPointer(PARAM(1))).raw;
145 Core::g_app_core->SetReg(1, param_1); 163 Core::g_app_core->SetReg(1, param_1);
146 FuncReturn(retval); 164 FuncReturn(retval);
147} 165}
148 166
149template<ResultCode func(u32*, s32, s32)> void Wrap() { 167template <ResultCode func(u32*, s32, s32)>
168void Wrap() {
150 u32 param_1 = 0; 169 u32 param_1 = 0;
151 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw; 170 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw;
152 Core::g_app_core->SetReg(1, param_1); 171 Core::g_app_core->SetReg(1, param_1);
153 FuncReturn(retval); 172 FuncReturn(retval);
154} 173}
155 174
156template<ResultCode func(s32*, u32, s32)> void Wrap() { 175template <ResultCode func(s32*, u32, s32)>
176void Wrap() {
157 s32 param_1 = 0; 177 s32 param_1 = 0;
158 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw; 178 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw;
159 Core::g_app_core->SetReg(1, param_1); 179 Core::g_app_core->SetReg(1, param_1);
160 FuncReturn(retval); 180 FuncReturn(retval);
161} 181}
162 182
163template<ResultCode func(s64*, u32, s32)> void Wrap() { 183template <ResultCode func(s64*, u32, s32)>
184void Wrap() {
164 s64 param_1 = 0; 185 s64 param_1 = 0;
165 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw; 186 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw;
166 Core::g_app_core->SetReg(1, (u32)param_1); 187 Core::g_app_core->SetReg(1, (u32)param_1);
@@ -168,7 +189,8 @@ template<ResultCode func(s64*, u32, s32)> void Wrap() {
168 FuncReturn(retval); 189 FuncReturn(retval);
169} 190}
170 191
171template<ResultCode func(u32*, u32, u32, u32, u32)> void Wrap() { 192template <ResultCode func(u32*, u32, u32, u32, u32)>
193void Wrap() {
172 u32 param_1 = 0; 194 u32 param_1 = 0;
173 // The last parameter is passed in R0 instead of R4 195 // The last parameter is passed in R0 instead of R4
174 u32 retval = func(&param_1, PARAM(1), PARAM(2), PARAM(3), PARAM(0)).raw; 196 u32 retval = func(&param_1, PARAM(1), PARAM(2), PARAM(3), PARAM(0)).raw;
@@ -176,13 +198,15 @@ template<ResultCode func(u32*, u32, u32, u32, u32)> void Wrap() {
176 FuncReturn(retval); 198 FuncReturn(retval);
177} 199}
178 200
179template<ResultCode func(u32, s64, s64)> void Wrap() { 201template <ResultCode func(u32, s64, s64)>
202void Wrap() {
180 s64 param1 = ((u64)PARAM(3) << 32) | PARAM(2); 203 s64 param1 = ((u64)PARAM(3) << 32) | PARAM(2);
181 s64 param2 = ((u64)PARAM(4) << 32) | PARAM(1); 204 s64 param2 = ((u64)PARAM(4) << 32) | PARAM(1);
182 FuncReturn(func(PARAM(0), param1, param2).raw); 205 FuncReturn(func(PARAM(0), param1, param2).raw);
183} 206}
184 207
185template<ResultCode func(s64*, Handle, u32)> void Wrap() { 208template <ResultCode func(s64*, Handle, u32)>
209void Wrap() {
186 s64 param_1 = 0; 210 s64 param_1 = 0;
187 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw; 211 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw;
188 Core::g_app_core->SetReg(1, (u32)param_1); 212 Core::g_app_core->SetReg(1, (u32)param_1);
@@ -190,14 +214,18 @@ template<ResultCode func(s64*, Handle, u32)> void Wrap() {
190 FuncReturn(retval); 214 FuncReturn(retval);
191} 215}
192 216
193template<ResultCode func(Handle, u32)> void Wrap() { 217template <ResultCode func(Handle, u32)>
218void Wrap() {
194 FuncReturn(func(PARAM(0), PARAM(1)).raw); 219 FuncReturn(func(PARAM(0), PARAM(1)).raw);
195} 220}
196 221
197template<ResultCode func(Handle*, Handle*, const char*, u32)> void Wrap() { 222template <ResultCode func(Handle*, Handle*, const char*, u32)>
223void Wrap() {
198 Handle param_1 = 0; 224 Handle param_1 = 0;
199 Handle param_2 = 0; 225 Handle param_2 = 0;
200 u32 retval = func(&param_1, &param_2, reinterpret_cast<const char*>(Memory::GetPointer(PARAM(2))), PARAM(3)).raw; 226 u32 retval = func(&param_1, &param_2,
227 reinterpret_cast<const char*>(Memory::GetPointer(PARAM(2))), PARAM(3))
228 .raw;
201 // The first out parameter is moved into R2 and the second is moved into R1. 229 // The first out parameter is moved into R2 and the second is moved into R1.
202 Core::g_app_core->SetReg(1, param_2); 230 Core::g_app_core->SetReg(1, param_2);
203 Core::g_app_core->SetReg(2, param_1); 231 Core::g_app_core->SetReg(2, param_1);
@@ -207,29 +235,34 @@ template<ResultCode func(Handle*, Handle*, const char*, u32)> void Wrap() {
207//////////////////////////////////////////////////////////////////////////////////////////////////// 235////////////////////////////////////////////////////////////////////////////////////////////////////
208// Function wrappers that return type u32 236// Function wrappers that return type u32
209 237
210template<u32 func()> void Wrap() { 238template <u32 func()>
239void Wrap() {
211 FuncReturn(func()); 240 FuncReturn(func());
212} 241}
213 242
214//////////////////////////////////////////////////////////////////////////////////////////////////// 243////////////////////////////////////////////////////////////////////////////////////////////////////
215// Function wrappers that return type s64 244// Function wrappers that return type s64
216 245
217template<s64 func()> void Wrap() { 246template <s64 func()>
247void Wrap() {
218 FuncReturn64(func()); 248 FuncReturn64(func());
219} 249}
220 250
221//////////////////////////////////////////////////////////////////////////////////////////////////// 251////////////////////////////////////////////////////////////////////////////////////////////////////
222/// Function wrappers that return type void 252/// Function wrappers that return type void
223 253
224template<void func(s64)> void Wrap() { 254template <void func(s64)>
255void Wrap() {
225 func(((s64)PARAM(1) << 32) | PARAM(0)); 256 func(((s64)PARAM(1) << 32) | PARAM(0));
226} 257}
227 258
228template<void func(const char*)> void Wrap() { 259template <void func(const char*)>
260void Wrap() {
229 func((char*)Memory::GetPointer(PARAM(0))); 261 func((char*)Memory::GetPointer(PARAM(0)));
230} 262}
231 263
232template<void func(u8)> void Wrap() { 264template <void func(u8)>
265void Wrap() {
233 func((u8)PARAM(0)); 266 func((u8)PARAM(0));
234} 267}
235 268
diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp
index 5c5373517..480a73e80 100644
--- a/src/core/hle/hle.cpp
+++ b/src/core/hle/hle.cpp
@@ -15,13 +15,13 @@
15namespace { 15namespace {
16 16
17bool reschedule; ///< If true, immediately reschedules the CPU to a new thread 17bool reschedule; ///< If true, immediately reschedules the CPU to a new thread
18
19} 18}
20 19
21namespace HLE { 20namespace HLE {
22 21
23void Reschedule(const char *reason) { 22void Reschedule(const char* reason) {
24 DEBUG_ASSERT_MSG(reason != nullptr && strlen(reason) < 256, "Reschedule: Invalid or too long reason."); 23 DEBUG_ASSERT_MSG(reason != nullptr && strlen(reason) < 256,
24 "Reschedule: Invalid or too long reason.");
25 25
26 // TODO(bunnei): It seems that games depend on some CPU execution time elapsing during HLE 26 // TODO(bunnei): It seems that games depend on some CPU execution time elapsing during HLE
27 // routines. This simulates that time by artificially advancing the number of CPU "ticks". 27 // routines. This simulates that time by artificially advancing the number of CPU "ticks".
diff --git a/src/core/hle/hle.h b/src/core/hle/hle.h
index 69ac0ade6..23859e129 100644
--- a/src/core/hle/hle.h
+++ b/src/core/hle/hle.h
@@ -13,7 +13,7 @@ const Handle INVALID_HANDLE = 0;
13 13
14namespace HLE { 14namespace HLE {
15 15
16void Reschedule(const char *reason); 16void Reschedule(const char* reason);
17bool IsReschedulePending(); 17bool IsReschedulePending();
18void DoneRescheduling(); 18void DoneRescheduling();
19 19
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 5c3c47acf..2ff652f13 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -16,8 +16,10 @@
16 16
17namespace Kernel { 17namespace Kernel {
18 18
19AddressArbiter::AddressArbiter() {} 19AddressArbiter::AddressArbiter() {
20AddressArbiter::~AddressArbiter() {} 20}
21AddressArbiter::~AddressArbiter() {
22}
21 23
22SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) { 24SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) {
23 SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter); 25 SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter);
@@ -28,7 +30,7 @@ SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) {
28} 30}
29 31
30ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, 32ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value,
31 u64 nanoseconds) { 33 u64 nanoseconds) {
32 switch (type) { 34 switch (type) {
33 35
34 // Signal thread(s) waiting for arbitrate address... 36 // Signal thread(s) waiting for arbitrate address...
@@ -38,7 +40,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
38 ArbitrateAllThreads(address); 40 ArbitrateAllThreads(address);
39 } else { 41 } else {
40 // Resume first N threads 42 // Resume first N threads
41 for(int i = 0; i < value; i++) 43 for (int i = 0; i < value; i++)
42 ArbitrateHighestPriorityThread(address); 44 ArbitrateHighestPriorityThread(address);
43 } 45 }
44 break; 46 break;
@@ -55,8 +57,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
55 GetCurrentThread()->WakeAfterDelay(nanoseconds); 57 GetCurrentThread()->WakeAfterDelay(nanoseconds);
56 } 58 }
57 break; 59 break;
58 case ArbitrationType::DecrementAndWaitIfLessThan: 60 case ArbitrationType::DecrementAndWaitIfLessThan: {
59 {
60 s32 memory_value = Memory::Read32(address); 61 s32 memory_value = Memory::Read32(address);
61 if (memory_value < value) { 62 if (memory_value < value) {
62 // Only change the memory value if the thread should wait 63 // Only change the memory value if the thread should wait
@@ -65,8 +66,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
65 } 66 }
66 break; 67 break;
67 } 68 }
68 case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: 69 case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: {
69 {
70 s32 memory_value = Memory::Read32(address); 70 s32 memory_value = Memory::Read32(address);
71 if (memory_value < value) { 71 if (memory_value < value) {
72 // Only change the memory value if the thread should wait 72 // Only change the memory value if the thread should wait
@@ -79,17 +79,19 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
79 79
80 default: 80 default:
81 LOG_ERROR(Kernel, "unknown type=%d", type); 81 LOG_ERROR(Kernel, "unknown type=%d", type);
82 return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, ErrorSummary::WrongArgument, ErrorLevel::Usage); 82 return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel,
83 ErrorSummary::WrongArgument, ErrorLevel::Usage);
83 } 84 }
84 85
85 HLE::Reschedule(__func__); 86 HLE::Reschedule(__func__);
86 87
87 // The calls that use a timeout seem to always return a Timeout error even if they did not put the thread to sleep 88 // The calls that use a timeout seem to always return a Timeout error even if they did not put
89 // the thread to sleep
88 if (type == ArbitrationType::WaitIfLessThanWithTimeout || 90 if (type == ArbitrationType::WaitIfLessThanWithTimeout ||
89 type == ArbitrationType::DecrementAndWaitIfLessThanWithTimeout) { 91 type == ArbitrationType::DecrementAndWaitIfLessThanWithTimeout) {
90 92
91 return ResultCode(ErrorDescription::Timeout, ErrorModule::OS, 93 return ResultCode(ErrorDescription::Timeout, ErrorModule::OS, ErrorSummary::StatusChanged,
92 ErrorSummary::StatusChanged, ErrorLevel::Info); 94 ErrorLevel::Info);
93 } 95 }
94 return RESULT_SUCCESS; 96 return RESULT_SUCCESS;
95} 97}
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h
index 8f6a1a8df..1a03993b2 100644
--- a/src/core/hle/kernel/address_arbiter.h
+++ b/src/core/hle/kernel/address_arbiter.h
@@ -36,13 +36,19 @@ public:
36 */ 36 */
37 static SharedPtr<AddressArbiter> Create(std::string name = "Unknown"); 37 static SharedPtr<AddressArbiter> Create(std::string name = "Unknown");
38 38
39 std::string GetTypeName() const override { return "Arbiter"; } 39 std::string GetTypeName() const override {
40 std::string GetName() const override { return name; } 40 return "Arbiter";
41 }
42 std::string GetName() const override {
43 return name;
44 }
41 45
42 static const HandleType HANDLE_TYPE = HandleType::AddressArbiter; 46 static const HandleType HANDLE_TYPE = HandleType::AddressArbiter;
43 HandleType GetHandleType() const override { return HANDLE_TYPE; } 47 HandleType GetHandleType() const override {
48 return HANDLE_TYPE;
49 }
44 50
45 std::string name; ///< Name of address arbiter object (optional) 51 std::string name; ///< Name of address arbiter object (optional)
46 52
47 ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds); 53 ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds);
48 54
diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp
index 444ce8d45..5df769c6a 100644
--- a/src/core/hle/kernel/client_port.cpp
+++ b/src/core/hle/kernel/client_port.cpp
@@ -10,7 +10,9 @@
10 10
11namespace Kernel { 11namespace Kernel {
12 12
13ClientPort::ClientPort() {} 13ClientPort::ClientPort() {
14ClientPort::~ClientPort() {} 14}
15ClientPort::~ClientPort() {
16}
15 17
16} // namespace 18} // namespace
diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h
index 480b6ddae..70e0d56cc 100644
--- a/src/core/hle/kernel/client_port.h
+++ b/src/core/hle/kernel/client_port.h
@@ -17,16 +17,22 @@ class ServerPort;
17class ClientPort : public Object { 17class ClientPort : public Object {
18public: 18public:
19 friend class ServerPort; 19 friend class ServerPort;
20 std::string GetTypeName() const override { return "ClientPort"; } 20 std::string GetTypeName() const override {
21 std::string GetName() const override { return name; } 21 return "ClientPort";
22 }
23 std::string GetName() const override {
24 return name;
25 }
22 26
23 static const HandleType HANDLE_TYPE = HandleType::ClientPort; 27 static const HandleType HANDLE_TYPE = HandleType::ClientPort;
24 HandleType GetHandleType() const override { return HANDLE_TYPE; } 28 HandleType GetHandleType() const override {
25 29 return HANDLE_TYPE;
26 SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port. 30 }
27 u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have 31
28 u32 active_sessions; ///< Number of currently open sessions to this port 32 SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
29 std::string name; ///< Name of client port (optional) 33 u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have
34 u32 active_sessions; ///< Number of currently open sessions to this port
35 std::string name; ///< Name of client port (optional)
30 36
31protected: 37protected:
32 ClientPort(); 38 ClientPort();
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index 2b7c6992a..63375818d 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -2,20 +2,22 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <map>
6#include <algorithm> 5#include <algorithm>
6#include <map>
7#include <vector> 7#include <vector>
8 8
9#include "common/assert.h" 9#include "common/assert.h"
10 10
11#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/event.h" 11#include "core/hle/kernel/event.h"
12#include "core/hle/kernel/kernel.h"
13#include "core/hle/kernel/thread.h" 13#include "core/hle/kernel/thread.h"
14 14
15namespace Kernel { 15namespace Kernel {
16 16
17Event::Event() {} 17Event::Event() {
18Event::~Event() {} 18}
19Event::~Event() {
20}
19 21
20SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) { 22SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) {
21 SharedPtr<Event> evt(new Event); 23 SharedPtr<Event> evt(new Event);
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h
index 73d0da419..e333a46ce 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/event.h
@@ -16,7 +16,6 @@ enum class ResetType {
16 Pulse, 16 Pulse,
17}; 17};
18 18
19
20class Event final : public WaitObject { 19class Event final : public WaitObject {
21public: 20public:
22 /** 21 /**
@@ -26,16 +25,22 @@ public:
26 */ 25 */
27 static SharedPtr<Event> Create(ResetType reset_type, std::string name = "Unknown"); 26 static SharedPtr<Event> Create(ResetType reset_type, std::string name = "Unknown");
28 27
29 std::string GetTypeName() const override { return "Event"; } 28 std::string GetTypeName() const override {
30 std::string GetName() const override { return name; } 29 return "Event";
30 }
31 std::string GetName() const override {
32 return name;
33 }
31 34
32 static const HandleType HANDLE_TYPE = HandleType::Event; 35 static const HandleType HANDLE_TYPE = HandleType::Event;
33 HandleType GetHandleType() const override { return HANDLE_TYPE; } 36 HandleType GetHandleType() const override {
37 return HANDLE_TYPE;
38 }
34 39
35 ResetType reset_type; ///< Current ResetType 40 ResetType reset_type; ///< Current ResetType
36 41
37 bool signaled; ///< Whether the event has already been signaled 42 bool signaled; ///< Whether the event has already been signaled
38 std::string name; ///< Name of event (optional) 43 std::string name; ///< Name of event (optional)
39 44
40 bool ShouldWait() override; 45 bool ShouldWait() override;
41 void Acquire() override; 46 void Acquire() override;
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 7a401a965..1fd7c0326 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -61,7 +61,8 @@ ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
61 61
62 // Overflow count so it fits in the 15 bits dedicated to the generation in the handle. 62 // Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
63 // CTR-OS doesn't use generation 0, so skip straight to 1. 63 // CTR-OS doesn't use generation 0, so skip straight to 1.
64 if (next_generation >= (1 << 15)) next_generation = 1; 64 if (next_generation >= (1 << 15))
65 next_generation = 1;
65 66
66 generations[slot] = generation; 67 generations[slot] = generation;
67 objects[slot] = std::move(obj); 68 objects[slot] = std::move(obj);
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 27ba3f912..cc39652d5 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -23,48 +23,55 @@ class Thread;
23 23
24// TODO: Verify code 24// TODO: Verify code
25const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel, 25const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel,
26 ErrorSummary::OutOfResource, ErrorLevel::Temporary); 26 ErrorSummary::OutOfResource, ErrorLevel::Temporary);
27// TOOD: Verify code 27// TOOD: Verify code
28const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel, 28const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel,
29 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 29 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
30 30
31enum KernelHandle : Handle { 31enum KernelHandle : Handle {
32 CurrentThread = 0xFFFF8000, 32 CurrentThread = 0xFFFF8000,
33 CurrentProcess = 0xFFFF8001, 33 CurrentProcess = 0xFFFF8001,
34}; 34};
35 35
36enum class HandleType : u32 { 36enum class HandleType : u32 {
37 Unknown = 0, 37 Unknown = 0,
38 38
39 Session = 2, 39 Session = 2,
40 Event = 3, 40 Event = 3,
41 Mutex = 4, 41 Mutex = 4,
42 SharedMemory = 5, 42 SharedMemory = 5,
43 Redirection = 6, 43 Redirection = 6,
44 Thread = 7, 44 Thread = 7,
45 Process = 8, 45 Process = 8,
46 AddressArbiter = 9, 46 AddressArbiter = 9,
47 Semaphore = 10, 47 Semaphore = 10,
48 Timer = 11, 48 Timer = 11,
49 ResourceLimit = 12, 49 ResourceLimit = 12,
50 CodeSet = 13, 50 CodeSet = 13,
51 ClientPort = 14, 51 ClientPort = 14,
52 ServerPort = 15, 52 ServerPort = 15,
53}; 53};
54 54
55enum { 55enum {
56 DEFAULT_STACK_SIZE = 0x4000, 56 DEFAULT_STACK_SIZE = 0x4000,
57}; 57};
58 58
59class Object : NonCopyable { 59class Object : NonCopyable {
60public: 60public:
61 virtual ~Object() {} 61 virtual ~Object() {
62 }
62 63
63 /// Returns a unique identifier for the object. For debugging purposes only. 64 /// Returns a unique identifier for the object. For debugging purposes only.
64 unsigned int GetObjectId() const { return object_id; } 65 unsigned int GetObjectId() const {
66 return object_id;
67 }
65 68
66 virtual std::string GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; } 69 virtual std::string GetTypeName() const {
67 virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; } 70 return "[BAD KERNEL OBJECT TYPE]";
71 }
72 virtual std::string GetName() const {
73 return "[UNKNOWN KERNEL OBJECT]";
74 }
68 virtual Kernel::HandleType GetHandleType() const = 0; 75 virtual Kernel::HandleType GetHandleType() const = 0;
69 76
70 /** 77 /**
@@ -122,7 +129,6 @@ using SharedPtr = boost::intrusive_ptr<T>;
122/// Class that represents a Kernel object that a thread can be waiting on 129/// Class that represents a Kernel object that a thread can be waiting on
123class WaitObject : public Object { 130class WaitObject : public Object {
124public: 131public:
125
126 /** 132 /**
127 * Check if the current thread should wait until the object is available 133 * Check if the current thread should wait until the object is available
128 * @return True if the current thread should wait due to this object being unavailable 134 * @return True if the current thread should wait due to this object being unavailable
@@ -247,8 +253,12 @@ private:
247 */ 253 */
248 static const size_t MAX_COUNT = 4096; 254 static const size_t MAX_COUNT = 4096;
249 255
250 static u16 GetSlot(Handle handle) { return handle >> 15; } 256 static u16 GetSlot(Handle handle) {
251 static u16 GetGeneration(Handle handle) { return handle & 0x7FFF; } 257 return handle >> 15;
258 }
259 static u16 GetGeneration(Handle handle) {
260 return handle & 0x7FFF;
261 }
252 262
253 /// Stores the Object referenced by the handle or null if the slot is empty. 263 /// Stores the Object referenced by the handle or null if the slot is empty.
254 std::array<SharedPtr<Object>, MAX_COUNT> objects; 264 std::array<SharedPtr<Object>, MAX_COUNT> objects;
diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp
index 17ae87aef..89a72808a 100644
--- a/src/core/hle/kernel/memory.cpp
+++ b/src/core/hle/kernel/memory.cpp
@@ -31,7 +31,7 @@ static MemoryRegionInfo memory_regions[3];
31static const u32 memory_region_sizes[8][3] = { 31static const u32 memory_region_sizes[8][3] = {
32 // Old 3DS layouts 32 // Old 3DS layouts
33 {0x04000000, 0x02C00000, 0x01400000}, // 0 33 {0x04000000, 0x02C00000, 0x01400000}, // 0
34 { /* This appears to be unused. */ }, // 1 34 {/* This appears to be unused. */}, // 1
35 {0x06000000, 0x00C00000, 0x01400000}, // 2 35 {0x06000000, 0x00C00000, 0x01400000}, // 2
36 {0x05000000, 0x01C00000, 0x01400000}, // 3 36 {0x05000000, 0x01C00000, 0x01400000}, // 3
37 {0x04800000, 0x02400000, 0x01400000}, // 4 37 {0x04800000, 0x02400000, 0x01400000}, // 4
@@ -95,7 +95,6 @@ MemoryRegionInfo* GetMemoryRegion(MemoryRegion region) {
95 UNREACHABLE(); 95 UNREACHABLE();
96 } 96 }
97} 97}
98
99} 98}
100 99
101namespace Memory { 100namespace Memory {
@@ -110,9 +109,8 @@ struct MemoryArea {
110 109
111// We don't declare the IO regions in here since its handled by other means. 110// We don't declare the IO regions in here since its handled by other means.
112static MemoryArea memory_areas[] = { 111static MemoryArea memory_areas[] = {
113 {VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM) 112 {VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM)
114}; 113};
115
116} 114}
117 115
118void Init() { 116void Init() {
@@ -125,15 +123,21 @@ void InitLegacyAddressSpace(Kernel::VMManager& address_space) {
125 123
126 for (MemoryArea& area : memory_areas) { 124 for (MemoryArea& area : memory_areas) {
127 auto block = std::make_shared<std::vector<u8>>(area.size); 125 auto block = std::make_shared<std::vector<u8>>(area.size);
128 address_space.MapMemoryBlock(area.base, std::move(block), 0, area.size, MemoryState::Private).Unwrap(); 126 address_space
127 .MapMemoryBlock(area.base, std::move(block), 0, area.size, MemoryState::Private)
128 .Unwrap();
129 } 129 }
130 130
131 auto cfg_mem_vma = address_space.MapBackingMemory(CONFIG_MEMORY_VADDR, 131 auto cfg_mem_vma = address_space
132 (u8*)&ConfigMem::config_mem, CONFIG_MEMORY_SIZE, MemoryState::Shared).MoveFrom(); 132 .MapBackingMemory(CONFIG_MEMORY_VADDR, (u8*)&ConfigMem::config_mem,
133 CONFIG_MEMORY_SIZE, MemoryState::Shared)
134 .MoveFrom();
133 address_space.Reprotect(cfg_mem_vma, VMAPermission::Read); 135 address_space.Reprotect(cfg_mem_vma, VMAPermission::Read);
134 136
135 auto shared_page_vma = address_space.MapBackingMemory(SHARED_PAGE_VADDR, 137 auto shared_page_vma = address_space
136 (u8*)&SharedPage::shared_page, SHARED_PAGE_SIZE, MemoryState::Shared).MoveFrom(); 138 .MapBackingMemory(SHARED_PAGE_VADDR, (u8*)&SharedPage::shared_page,
139 SHARED_PAGE_SIZE, MemoryState::Shared)
140 .MoveFrom();
137 address_space.Reprotect(shared_page_vma, VMAPermission::Read); 141 address_space.Reprotect(shared_page_vma, VMAPermission::Read);
138 142
139 AudioCore::AddAddressSpace(address_space); 143 AudioCore::AddAddressSpace(address_space);
diff --git a/src/core/hle/kernel/memory.h b/src/core/hle/kernel/memory.h
index 091c1f89f..b941c24b6 100644
--- a/src/core/hle/kernel/memory.h
+++ b/src/core/hle/kernel/memory.h
@@ -25,7 +25,6 @@ struct MemoryRegionInfo {
25void MemoryInit(u32 mem_type); 25void MemoryInit(u32 mem_type);
26void MemoryShutdown(); 26void MemoryShutdown();
27MemoryRegionInfo* GetMemoryRegion(MemoryRegion region); 27MemoryRegionInfo* GetMemoryRegion(MemoryRegion region);
28
29} 28}
30 29
31namespace Memory { 30namespace Memory {
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index edb97d324..f92810804 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -33,8 +33,10 @@ void ReleaseThreadMutexes(Thread* thread) {
33 thread->held_mutexes.clear(); 33 thread->held_mutexes.clear();
34} 34}
35 35
36Mutex::Mutex() {} 36Mutex::Mutex() {
37Mutex::~Mutex() {} 37}
38Mutex::~Mutex() {
39}
38 40
39SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) { 41SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) {
40 SharedPtr<Mutex> mutex(new Mutex); 42 SharedPtr<Mutex> mutex(new Mutex);
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index 1746360e4..cf6a51fdf 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -24,15 +24,21 @@ public:
24 */ 24 */
25 static SharedPtr<Mutex> Create(bool initial_locked, std::string name = "Unknown"); 25 static SharedPtr<Mutex> Create(bool initial_locked, std::string name = "Unknown");
26 26
27 std::string GetTypeName() const override { return "Mutex"; } 27 std::string GetTypeName() const override {
28 std::string GetName() const override { return name; } 28 return "Mutex";
29 }
30 std::string GetName() const override {
31 return name;
32 }
29 33
30 static const HandleType HANDLE_TYPE = HandleType::Mutex; 34 static const HandleType HANDLE_TYPE = HandleType::Mutex;
31 HandleType GetHandleType() const override { return HANDLE_TYPE; } 35 HandleType GetHandleType() const override {
36 return HANDLE_TYPE;
37 }
32 38
33 int lock_count; ///< Number of times the mutex has been acquired 39 int lock_count; ///< Number of times the mutex has been acquired
34 std::string name; ///< Name of mutex (optional) 40 std::string name; ///< Name of mutex (optional)
35 SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex 41 SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex
36 42
37 bool ShouldWait() override; 43 bool ShouldWait() override;
38 void Acquire() override; 44 void Acquire() override;
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 69302cc82..cc37e574c 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -26,8 +26,10 @@ SharedPtr<CodeSet> CodeSet::Create(std::string name, u64 program_id) {
26 return codeset; 26 return codeset;
27} 27}
28 28
29CodeSet::CodeSet() {} 29CodeSet::CodeSet() {
30CodeSet::~CodeSet() {} 30}
31CodeSet::~CodeSet() {
32}
31 33
32u32 Process::next_process_id; 34u32 Process::next_process_id;
33 35
@@ -60,7 +62,8 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
60 62
61 while (bits && index < svc_access_mask.size()) { 63 while (bits && index < svc_access_mask.size()) {
62 svc_access_mask.set(index, bits & 1); 64 svc_access_mask.set(index, bits & 1);
63 ++index; bits >>= 1; 65 ++index;
66 bits >>= 1;
64 } 67 }
65 } else if ((type & 0xFF0) == 0xFE0) { // 0x00FF 68 } else if ((type & 0xFF0) == 0xFE0) { // 0x00FF
66 // Handle table size 69 // Handle table size
@@ -70,11 +73,11 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
70 flags.raw = descriptor & 0xFFFF; 73 flags.raw = descriptor & 0xFFFF;
71 } else if ((type & 0xFFE) == 0xFF8) { // 0x001F 74 } else if ((type & 0xFFE) == 0xFF8) { // 0x001F
72 // Mapped memory range 75 // Mapped memory range
73 if (i+1 >= len || ((kernel_caps[i+1] >> 20) & 0xFFE) != 0xFF8) { 76 if (i + 1 >= len || ((kernel_caps[i + 1] >> 20) & 0xFFE) != 0xFF8) {
74 LOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored."); 77 LOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored.");
75 continue; 78 continue;
76 } 79 }
77 u32 end_desc = kernel_caps[i+1]; 80 u32 end_desc = kernel_caps[i + 1];
78 ++i; // Skip over the second descriptor on the next iteration 81 ++i; // Skip over the second descriptor on the next iteration
79 82
80 AddressMapping mapping; 83 AddressMapping mapping;
@@ -107,23 +110,28 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
107void Process::Run(s32 main_thread_priority, u32 stack_size) { 110void Process::Run(s32 main_thread_priority, u32 stack_size) {
108 memory_region = GetMemoryRegion(flags.memory_region); 111 memory_region = GetMemoryRegion(flags.memory_region);
109 112
110 auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, MemoryState memory_state) { 113 auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions,
111 auto vma = vm_manager.MapMemoryBlock(segment.addr, codeset->memory, 114 MemoryState memory_state) {
112 segment.offset, segment.size, memory_state).Unwrap(); 115 auto vma = vm_manager
116 .MapMemoryBlock(segment.addr, codeset->memory, segment.offset, segment.size,
117 memory_state)
118 .Unwrap();
113 vm_manager.Reprotect(vma, permissions); 119 vm_manager.Reprotect(vma, permissions);
114 misc_memory_used += segment.size; 120 misc_memory_used += segment.size;
115 memory_region->used += segment.size; 121 memory_region->used += segment.size;
116 }; 122 };
117 123
118 // Map CodeSet segments 124 // Map CodeSet segments
119 MapSegment(codeset->code, VMAPermission::ReadExecute, MemoryState::Code); 125 MapSegment(codeset->code, VMAPermission::ReadExecute, MemoryState::Code);
120 MapSegment(codeset->rodata, VMAPermission::Read, MemoryState::Code); 126 MapSegment(codeset->rodata, VMAPermission::Read, MemoryState::Code);
121 MapSegment(codeset->data, VMAPermission::ReadWrite, MemoryState::Private); 127 MapSegment(codeset->data, VMAPermission::ReadWrite, MemoryState::Private);
122 128
123 // Allocate and map stack 129 // Allocate and map stack
124 vm_manager.MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size, 130 vm_manager
125 std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, MemoryState::Locked 131 .MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size,
126 ).Unwrap(); 132 std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size,
133 MemoryState::Locked)
134 .Unwrap();
127 misc_memory_used += stack_size; 135 misc_memory_used += stack_size;
128 memory_region->used += stack_size; 136 memory_region->used += stack_size;
129 137
@@ -143,7 +151,8 @@ VAddr Process::GetLinearHeapLimit() const {
143} 151}
144 152
145ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission perms) { 153ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission perms) {
146 if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || target + size < target) { 154 if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END ||
155 target + size < target) {
147 return ERR_INVALID_ADDRESS; 156 return ERR_INVALID_ADDRESS;
148 } 157 }
149 158
@@ -166,7 +175,8 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per
166 } 175 }
167 ASSERT(heap_end - heap_start == heap_memory->size()); 176 ASSERT(heap_end - heap_start == heap_memory->size());
168 177
169 CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, heap_memory, target - heap_start, size, MemoryState::Private)); 178 CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, heap_memory, target - heap_start,
179 size, MemoryState::Private));
170 vm_manager.Reprotect(vma, perms); 180 vm_manager.Reprotect(vma, perms);
171 181
172 heap_used += size; 182 heap_used += size;
@@ -176,7 +186,8 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per
176} 186}
177 187
178ResultCode Process::HeapFree(VAddr target, u32 size) { 188ResultCode Process::HeapFree(VAddr target, u32 size) {
179 if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || target + size < target) { 189 if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END ||
190 target + size < target) {
180 return ERR_INVALID_ADDRESS; 191 return ERR_INVALID_ADDRESS;
181 } 192 }
182 193
@@ -185,7 +196,8 @@ ResultCode Process::HeapFree(VAddr target, u32 size) {
185 } 196 }
186 197
187 ResultCode result = vm_manager.UnmapRange(target, size); 198 ResultCode result = vm_manager.UnmapRange(target, size);
188 if (result.IsError()) return result; 199 if (result.IsError())
200 return result;
189 201
190 heap_used -= size; 202 heap_used -= size;
191 memory_region->used -= size; 203 memory_region->used -= size;
@@ -203,8 +215,8 @@ ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission p
203 target = heap_end; 215 target = heap_end;
204 } 216 }
205 217
206 if (target < GetLinearHeapBase() || target + size > GetLinearHeapLimit() || 218 if (target < GetLinearHeapBase() || target + size > GetLinearHeapLimit() || target > heap_end ||
207 target > heap_end || target + size < target) { 219 target + size < target) {
208 220
209 return ERR_INVALID_ADDRESS; 221 return ERR_INVALID_ADDRESS;
210 } 222 }
@@ -220,7 +232,8 @@ ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission p
220 // TODO(yuriks): As is, this lets processes map memory allocated by other processes from the 232 // TODO(yuriks): As is, this lets processes map memory allocated by other processes from the
221 // same region. It is unknown if or how the 3DS kernel checks against this. 233 // same region. It is unknown if or how the 3DS kernel checks against this.
222 size_t offset = target - GetLinearHeapBase(); 234 size_t offset = target - GetLinearHeapBase();
223 CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, linheap_memory, offset, size, MemoryState::Continuous)); 235 CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, linheap_memory, offset, size,
236 MemoryState::Continuous));
224 vm_manager.Reprotect(vma, perms); 237 vm_manager.Reprotect(vma, perms);
225 238
226 linear_heap_used += size; 239 linear_heap_used += size;
@@ -248,7 +261,8 @@ ResultCode Process::LinearFree(VAddr target, u32 size) {
248 } 261 }
249 262
250 ResultCode result = vm_manager.UnmapRange(target, size); 263 ResultCode result = vm_manager.UnmapRange(target, size);
251 if (result.IsError()) return result; 264 if (result.IsError())
265 return result;
252 266
253 linear_heap_used -= size; 267 linear_heap_used -= size;
254 memory_region->used -= size; 268 memory_region->used -= size;
@@ -268,9 +282,10 @@ ResultCode Process::LinearFree(VAddr target, u32 size) {
268 return RESULT_SUCCESS; 282 return RESULT_SUCCESS;
269} 283}
270 284
271Kernel::Process::Process() {} 285Kernel::Process::Process() {
272Kernel::Process::~Process() {} 286}
287Kernel::Process::~Process() {
288}
273 289
274SharedPtr<Process> g_current_process; 290SharedPtr<Process> g_current_process;
275
276} 291}
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index d781ef32c..070b2b558 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -36,15 +36,18 @@ enum class MemoryRegion : u16 {
36union ProcessFlags { 36union ProcessFlags {
37 u16 raw; 37 u16 raw;
38 38
39 BitField< 0, 1, u16> allow_debug; ///< Allows other processes to attach to and debug this process. 39 BitField<0, 1, u16>
40 BitField< 1, 1, u16> force_debug; ///< Allows this process to attach to processes even if they don't have allow_debug set. 40 allow_debug; ///< Allows other processes to attach to and debug this process.
41 BitField< 2, 1, u16> allow_nonalphanum; 41 BitField<1, 1, u16> force_debug; ///< Allows this process to attach to processes even if they
42 BitField< 3, 1, u16> shared_page_writable; ///< Shared page is mapped with write permissions. 42 /// don't have allow_debug set.
43 BitField< 4, 1, u16> privileged_priority; ///< Can use priority levels higher than 24. 43 BitField<2, 1, u16> allow_nonalphanum;
44 BitField< 5, 1, u16> allow_main_args; 44 BitField<3, 1, u16> shared_page_writable; ///< Shared page is mapped with write permissions.
45 BitField< 6, 1, u16> shared_device_mem; 45 BitField<4, 1, u16> privileged_priority; ///< Can use priority levels higher than 24.
46 BitField< 7, 1, u16> runnable_on_sleep; 46 BitField<5, 1, u16> allow_main_args;
47 BitField< 8, 4, MemoryRegion> memory_region; ///< Default region for memory allocations for this process 47 BitField<6, 1, u16> shared_device_mem;
48 BitField<7, 1, u16> runnable_on_sleep;
49 BitField<8, 4, MemoryRegion>
50 memory_region; ///< Default region for memory allocations for this process
48 BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000). 51 BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000).
49}; 52};
50 53
@@ -54,11 +57,17 @@ struct MemoryRegionInfo;
54struct CodeSet final : public Object { 57struct CodeSet final : public Object {
55 static SharedPtr<CodeSet> Create(std::string name, u64 program_id); 58 static SharedPtr<CodeSet> Create(std::string name, u64 program_id);
56 59
57 std::string GetTypeName() const override { return "CodeSet"; } 60 std::string GetTypeName() const override {
58 std::string GetName() const override { return name; } 61 return "CodeSet";
62 }
63 std::string GetName() const override {
64 return name;
65 }
59 66
60 static const HandleType HANDLE_TYPE = HandleType::CodeSet; 67 static const HandleType HANDLE_TYPE = HandleType::CodeSet;
61 HandleType GetHandleType() const override { return HANDLE_TYPE; } 68 HandleType GetHandleType() const override {
69 return HANDLE_TYPE;
70 }
62 71
63 /// Name of the process 72 /// Name of the process
64 std::string name; 73 std::string name;
@@ -85,11 +94,17 @@ class Process final : public Object {
85public: 94public:
86 static SharedPtr<Process> Create(SharedPtr<CodeSet> code_set); 95 static SharedPtr<Process> Create(SharedPtr<CodeSet> code_set);
87 96
88 std::string GetTypeName() const override { return "Process"; } 97 std::string GetTypeName() const override {
89 std::string GetName() const override { return codeset->name; } 98 return "Process";
99 }
100 std::string GetName() const override {
101 return codeset->name;
102 }
90 103
91 static const HandleType HANDLE_TYPE = HandleType::Process; 104 static const HandleType HANDLE_TYPE = HandleType::Process;
92 HandleType GetHandleType() const override { return HANDLE_TYPE; } 105 HandleType GetHandleType() const override {
106 return HANDLE_TYPE;
107 }
93 108
94 static u32 next_process_id; 109 static u32 next_process_id;
95 110
@@ -124,7 +139,6 @@ public:
124 */ 139 */
125 void Run(s32 main_thread_priority, u32 stack_size); 140 void Run(s32 main_thread_priority, u32 stack_size);
126 141
127
128 /////////////////////////////////////////////////////////////////////////////////////////////// 142 ///////////////////////////////////////////////////////////////////////////////////////////////
129 // Memory Management 143 // Memory Management
130 144
@@ -144,7 +158,8 @@ public:
144 158
145 /// The Thread Local Storage area is allocated as processes create threads, 159 /// The Thread Local Storage area is allocated as processes create threads,
146 /// each TLS area is 0x200 bytes, so one page (0x1000) is split up in 8 parts, and each part 160 /// each TLS area is 0x200 bytes, so one page (0x1000) is split up in 8 parts, and each part
147 /// holds the TLS for a specific thread. This vector contains which parts are in use for each page as a bitmask. 161 /// holds the TLS for a specific thread. This vector contains which parts are in use for each
162 /// page as a bitmask.
148 /// This vector will grow as more pages are allocated for new threads. 163 /// This vector will grow as more pages are allocated for new threads.
149 std::vector<std::bitset<8>> tls_slots; 164 std::vector<std::bitset<8>> tls_slots;
150 165
@@ -164,5 +179,4 @@ private:
164}; 179};
165 180
166extern SharedPtr<Process> g_current_process; 181extern SharedPtr<Process> g_current_process;
167
168} 182}
diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp
index 67dde08c2..7bd1c1e08 100644
--- a/src/core/hle/kernel/resource_limit.cpp
+++ b/src/core/hle/kernel/resource_limit.cpp
@@ -12,8 +12,10 @@ namespace Kernel {
12 12
13static SharedPtr<ResourceLimit> resource_limits[4]; 13static SharedPtr<ResourceLimit> resource_limits[4];
14 14
15ResourceLimit::ResourceLimit() {} 15ResourceLimit::ResourceLimit() {
16ResourceLimit::~ResourceLimit() {} 16}
17ResourceLimit::~ResourceLimit() {
18}
17 19
18SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) { 20SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) {
19 SharedPtr<ResourceLimit> resource_limit(new ResourceLimit); 21 SharedPtr<ResourceLimit> resource_limit(new ResourceLimit);
@@ -23,70 +25,69 @@ SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) {
23} 25}
24 26
25SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) { 27SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) {
26 switch (category) 28 switch (category) {
27 { 29 case ResourceLimitCategory::APPLICATION:
28 case ResourceLimitCategory::APPLICATION: 30 case ResourceLimitCategory::SYS_APPLET:
29 case ResourceLimitCategory::SYS_APPLET: 31 case ResourceLimitCategory::LIB_APPLET:
30 case ResourceLimitCategory::LIB_APPLET: 32 case ResourceLimitCategory::OTHER:
31 case ResourceLimitCategory::OTHER: 33 return resource_limits[static_cast<u8>(category)];
32 return resource_limits[static_cast<u8>(category)]; 34 default:
33 default: 35 LOG_CRITICAL(Kernel, "Unknown resource limit category");
34 LOG_CRITICAL(Kernel, "Unknown resource limit category"); 36 UNREACHABLE();
35 UNREACHABLE();
36 } 37 }
37} 38}
38 39
39s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const { 40s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const {
40 switch (resource) { 41 switch (resource) {
41 case COMMIT: 42 case COMMIT:
42 return current_commit; 43 return current_commit;
43 case THREAD: 44 case THREAD:
44 return current_threads; 45 return current_threads;
45 case EVENT: 46 case EVENT:
46 return current_events; 47 return current_events;
47 case MUTEX: 48 case MUTEX:
48 return current_mutexes; 49 return current_mutexes;
49 case SEMAPHORE: 50 case SEMAPHORE:
50 return current_semaphores; 51 return current_semaphores;
51 case TIMER: 52 case TIMER:
52 return current_timers; 53 return current_timers;
53 case SHARED_MEMORY: 54 case SHARED_MEMORY:
54 return current_shared_mems; 55 return current_shared_mems;
55 case ADDRESS_ARBITER: 56 case ADDRESS_ARBITER:
56 return current_address_arbiters; 57 return current_address_arbiters;
57 case CPU_TIME: 58 case CPU_TIME:
58 return current_cpu_time; 59 return current_cpu_time;
59 default: 60 default:
60 LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); 61 LOG_ERROR(Kernel, "Unknown resource type=%08X", resource);
61 UNIMPLEMENTED(); 62 UNIMPLEMENTED();
62 return 0; 63 return 0;
63 } 64 }
64} 65}
65 66
66s32 ResourceLimit::GetMaxResourceValue(u32 resource) const { 67s32 ResourceLimit::GetMaxResourceValue(u32 resource) const {
67 switch (resource) { 68 switch (resource) {
68 case COMMIT: 69 case COMMIT:
69 return max_commit; 70 return max_commit;
70 case THREAD: 71 case THREAD:
71 return max_threads; 72 return max_threads;
72 case EVENT: 73 case EVENT:
73 return max_events; 74 return max_events;
74 case MUTEX: 75 case MUTEX:
75 return max_mutexes; 76 return max_mutexes;
76 case SEMAPHORE: 77 case SEMAPHORE:
77 return max_semaphores; 78 return max_semaphores;
78 case TIMER: 79 case TIMER:
79 return max_timers; 80 return max_timers;
80 case SHARED_MEMORY: 81 case SHARED_MEMORY:
81 return max_shared_mems; 82 return max_shared_mems;
82 case ADDRESS_ARBITER: 83 case ADDRESS_ARBITER:
83 return max_address_arbiters; 84 return max_address_arbiters;
84 case CPU_TIME: 85 case CPU_TIME:
85 return max_cpu_time; 86 return max_cpu_time;
86 default: 87 default:
87 LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); 88 LOG_ERROR(Kernel, "Unknown resource type=%08X", resource);
88 UNIMPLEMENTED(); 89 UNIMPLEMENTED();
89 return 0; 90 return 0;
90 } 91 }
91} 92}
92 93
@@ -150,7 +151,6 @@ void ResourceLimitsInit() {
150} 151}
151 152
152void ResourceLimitsShutdown() { 153void ResourceLimitsShutdown() {
153
154} 154}
155 155
156} // namespace 156} // namespace
diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h
index 1b8249c74..c08e744e6 100644
--- a/src/core/hle/kernel/resource_limit.h
+++ b/src/core/hle/kernel/resource_limit.h
@@ -12,22 +12,22 @@ namespace Kernel {
12 12
13enum class ResourceLimitCategory : u8 { 13enum class ResourceLimitCategory : u8 {
14 APPLICATION = 0, 14 APPLICATION = 0,
15 SYS_APPLET = 1, 15 SYS_APPLET = 1,
16 LIB_APPLET = 2, 16 LIB_APPLET = 2,
17 OTHER = 3 17 OTHER = 3
18}; 18};
19 19
20enum ResourceTypes { 20enum ResourceTypes {
21 PRIORITY = 0, 21 PRIORITY = 0,
22 COMMIT = 1, 22 COMMIT = 1,
23 THREAD = 2, 23 THREAD = 2,
24 EVENT = 3, 24 EVENT = 3,
25 MUTEX = 4, 25 MUTEX = 4,
26 SEMAPHORE = 5, 26 SEMAPHORE = 5,
27 TIMER = 6, 27 TIMER = 6,
28 SHARED_MEMORY = 7, 28 SHARED_MEMORY = 7,
29 ADDRESS_ARBITER = 8, 29 ADDRESS_ARBITER = 8,
30 CPU_TIME = 9, 30 CPU_TIME = 9,
31}; 31};
32 32
33class ResourceLimit final : public Object { 33class ResourceLimit final : public Object {
@@ -44,11 +44,17 @@ public:
44 */ 44 */
45 static SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category); 45 static SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category);
46 46
47 std::string GetTypeName() const override { return "ResourceLimit"; } 47 std::string GetTypeName() const override {
48 std::string GetName() const override { return name; } 48 return "ResourceLimit";
49 }
50 std::string GetName() const override {
51 return name;
52 }
49 53
50 static const HandleType HANDLE_TYPE = HandleType::ResourceLimit; 54 static const HandleType HANDLE_TYPE = HandleType::ResourceLimit;
51 HandleType GetHandleType() const override { return HANDLE_TYPE; } 55 HandleType GetHandleType() const override {
56 return HANDLE_TYPE;
57 }
52 58
53 /** 59 /**
54 * Gets the current value for the specified resource. 60 * Gets the current value for the specified resource.
@@ -85,10 +91,12 @@ public:
85 /// Max CPU time that the processes in this category can utilize 91 /// Max CPU time that the processes in this category can utilize
86 s32 max_cpu_time = 0; 92 s32 max_cpu_time = 0;
87 93
88 // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind that 94 // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind
95 // that
89 // APPLICATION resource limits should not be affected by the objects created by service modules. 96 // APPLICATION resource limits should not be affected by the objects created by service modules.
90 // Currently we have no way of distinguishing if a Create was called by the running application, 97 // Currently we have no way of distinguishing if a Create was called by the running application,
91 // or by a service module. Approach this once we have separated the service modules into their own processes 98 // or by a service module. Approach this once we have separated the service modules into their
99 // own processes
92 100
93 /// Current memory that the processes in this category are using 101 /// Current memory that the processes in this category are using
94 s32 current_commit = 0; 102 s32 current_commit = 0;
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index 4b359ed07..71e41079b 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -10,11 +10,13 @@
10 10
11namespace Kernel { 11namespace Kernel {
12 12
13Semaphore::Semaphore() {} 13Semaphore::Semaphore() {
14Semaphore::~Semaphore() {} 14}
15Semaphore::~Semaphore() {
16}
15 17
16ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, 18ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count,
17 std::string name) { 19 std::string name) {
18 20
19 if (initial_count > max_count) 21 if (initial_count > max_count)
20 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, 22 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel,
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
index 390f5e495..ed7d9a85c 100644
--- a/src/core/hle/kernel/semaphore.h
+++ b/src/core/hle/kernel/semaphore.h
@@ -23,17 +23,23 @@ public:
23 * @return The created semaphore 23 * @return The created semaphore
24 */ 24 */
25 static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count, 25 static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count,
26 std::string name = "Unknown"); 26 std::string name = "Unknown");
27 27
28 std::string GetTypeName() const override { return "Semaphore"; } 28 std::string GetTypeName() const override {
29 std::string GetName() const override { return name; } 29 return "Semaphore";
30 }
31 std::string GetName() const override {
32 return name;
33 }
30 34
31 static const HandleType HANDLE_TYPE = HandleType::Semaphore; 35 static const HandleType HANDLE_TYPE = HandleType::Semaphore;
32 HandleType GetHandleType() const override { return HANDLE_TYPE; } 36 HandleType GetHandleType() const override {
37 return HANDLE_TYPE;
38 }
33 39
34 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have 40 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
35 s32 available_count; ///< Number of free slots left in the semaphore 41 s32 available_count; ///< Number of free slots left in the semaphore
36 std::string name; ///< Name of semaphore (optional) 42 std::string name; ///< Name of semaphore (optional)
37 43
38 bool ShouldWait() override; 44 bool ShouldWait() override;
39 void Acquire() override; 45 void Acquire() override;
diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp
index fcc684a20..7c690fa7f 100644
--- a/src/core/hle/kernel/server_port.cpp
+++ b/src/core/hle/kernel/server_port.cpp
@@ -13,8 +13,10 @@
13 13
14namespace Kernel { 14namespace Kernel {
15 15
16ServerPort::ServerPort() {} 16ServerPort::ServerPort() {
17ServerPort::~ServerPort() {} 17}
18ServerPort::~ServerPort() {
19}
18 20
19bool ServerPort::ShouldWait() { 21bool ServerPort::ShouldWait() {
20 // If there are no pending sessions, we wait until a new one is added. 22 // If there are no pending sessions, we wait until a new one is added.
@@ -25,7 +27,8 @@ void ServerPort::Acquire() {
25 ASSERT_MSG(!ShouldWait(), "object unavailable!"); 27 ASSERT_MSG(!ShouldWait(), "object unavailable!");
26} 28}
27 29
28std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair(u32 max_sessions, std::string name) { 30std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>>
31ServerPort::CreatePortPair(u32 max_sessions, std::string name) {
29 SharedPtr<ServerPort> server_port(new ServerPort); 32 SharedPtr<ServerPort> server_port(new ServerPort);
30 SharedPtr<ClientPort> client_port(new ClientPort); 33 SharedPtr<ClientPort> client_port(new ClientPort);
31 34
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h
index e9c972ce6..e43d48674 100644
--- a/src/core/hle/kernel/server_port.h
+++ b/src/core/hle/kernel/server_port.h
@@ -23,17 +23,25 @@ public:
23 * @param name Optional name of the ports 23 * @param name Optional name of the ports
24 * @return The created port tuple 24 * @return The created port tuple
25 */ 25 */
26 static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(u32 max_sessions, std::string name = "UnknownPort"); 26 static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>>
27 CreatePortPair(u32 max_sessions, std::string name = "UnknownPort");
27 28
28 std::string GetTypeName() const override { return "ServerPort"; } 29 std::string GetTypeName() const override {
29 std::string GetName() const override { return name; } 30 return "ServerPort";
31 }
32 std::string GetName() const override {
33 return name;
34 }
30 35
31 static const HandleType HANDLE_TYPE = HandleType::ServerPort; 36 static const HandleType HANDLE_TYPE = HandleType::ServerPort;
32 HandleType GetHandleType() const override { return HANDLE_TYPE; } 37 HandleType GetHandleType() const override {
38 return HANDLE_TYPE;
39 }
33 40
34 std::string name; ///< Name of port (optional) 41 std::string name; ///< Name of port (optional)
35 42
36 std::vector<SharedPtr<WaitObject>> pending_sessions; ///< ServerSessions waiting to be accepted by the port 43 std::vector<SharedPtr<WaitObject>>
44 pending_sessions; ///< ServerSessions waiting to be accepted by the port
37 45
38 bool ShouldWait() override; 46 bool ShouldWait() override;
39 void Acquire() override; 47 void Acquire() override;
diff --git a/src/core/hle/kernel/session.cpp b/src/core/hle/kernel/session.cpp
index 0594967f8..61457845a 100644
--- a/src/core/hle/kernel/session.cpp
+++ b/src/core/hle/kernel/session.cpp
@@ -7,7 +7,8 @@
7 7
8namespace Kernel { 8namespace Kernel {
9 9
10Session::Session() {} 10Session::Session() {
11Session::~Session() {} 11}
12 12Session::~Session() {
13}
13} 14}
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h
index 8ec889967..8e4e010b8 100644
--- a/src/core/hle/kernel/session.h
+++ b/src/core/hle/kernel/session.h
@@ -19,12 +19,13 @@ namespace IPC {
19enum DescriptorType : u32 { 19enum DescriptorType : u32 {
20 // Buffer related desciptors types (mask : 0x0F) 20 // Buffer related desciptors types (mask : 0x0F)
21 StaticBuffer = 0x02, 21 StaticBuffer = 0x02,
22 PXIBuffer = 0x04, 22 PXIBuffer = 0x04,
23 MappedBuffer = 0x08, 23 MappedBuffer = 0x08,
24 // Handle related descriptors types (mask : 0x30, but need to check for buffer related descriptors first ) 24 // Handle related descriptors types (mask : 0x30, but need to check for buffer related
25 CopyHandle = 0x00, 25 // descriptors first )
26 MoveHandle = 0x10, 26 CopyHandle = 0x00,
27 CallingPid = 0x20, 27 MoveHandle = 0x10,
28 CallingPid = 0x20,
28}; 29};
29 30
30/** 31/**
@@ -34,24 +35,28 @@ enum DescriptorType : u32 {
34 * @param translate_params_size Size of the translate parameters in words. Up to 63. 35 * @param translate_params_size Size of the translate parameters in words. Up to 63.
35 * @return The created IPC header. 36 * @return The created IPC header.
36 * 37 *
37 * Normal parameters are sent directly to the process while the translate parameters might go through modifications and checks by the kernel. 38 * Normal parameters are sent directly to the process while the translate parameters might go
39 * through modifications and checks by the kernel.
38 * The translate parameters are described by headers generated with the IPC::*Desc functions. 40 * The translate parameters are described by headers generated with the IPC::*Desc functions.
39 * 41 *
40 * @note While #normal_params is equivalent to the number of normal parameters, #translate_params_size includes the size occupied by the translate parameters headers. 42 * @note While #normal_params is equivalent to the number of normal parameters,
43 * #translate_params_size includes the size occupied by the translate parameters headers.
41 */ 44 */
42constexpr u32 MakeHeader(u16 command_id, unsigned int normal_params, unsigned int translate_params_size) { 45constexpr u32 MakeHeader(u16 command_id, unsigned int normal_params,
43 return (u32(command_id) << 16) | ((u32(normal_params) & 0x3F) << 6) | (u32(translate_params_size) & 0x3F); 46 unsigned int translate_params_size) {
47 return (u32(command_id) << 16) | ((u32(normal_params) & 0x3F) << 6) |
48 (u32(translate_params_size) & 0x3F);
44} 49}
45 50
46union Header { 51union Header {
47 u32 raw; 52 u32 raw;
48 BitField< 0, 6, u32> translate_params_size; 53 BitField<0, 6, u32> translate_params_size;
49 BitField< 6, 6, u32> normal_params; 54 BitField<6, 6, u32> normal_params;
50 BitField<16, 16, u32> command_id; 55 BitField<16, 16, u32> command_id;
51}; 56};
52 57
53inline Header ParseHeader(u32 header) { 58inline Header ParseHeader(u32 header) {
54 return{ header }; 59 return {header};
55} 60}
56 61
57constexpr u32 MoveHandleDesc(u32 num_handles = 1) { 62constexpr u32 MoveHandleDesc(u32 num_handles = 1) {
@@ -80,27 +85,29 @@ constexpr u32 StaticBufferDesc(u32 size, u8 buffer_id) {
80 85
81union StaticBufferDescInfo { 86union StaticBufferDescInfo {
82 u32 raw; 87 u32 raw;
83 BitField< 10, 4, u32> buffer_id; 88 BitField<10, 4, u32> buffer_id;
84 BitField< 14, 18, u32> size; 89 BitField<14, 18, u32> size;
85}; 90};
86 91
87inline StaticBufferDescInfo ParseStaticBufferDesc(const u32 desc) { 92inline StaticBufferDescInfo ParseStaticBufferDesc(const u32 desc) {
88 return{ desc }; 93 return {desc};
89} 94}
90 95
91/** 96/**
92 * @brief Creates a header describing a buffer to be sent over PXI. 97 * @brief Creates a header describing a buffer to be sent over PXI.
93 * @param size Size of the buffer. Max 0x00FFFFFF. 98 * @param size Size of the buffer. Max 0x00FFFFFF.
94 * @param buffer_id The Id of the buffer. Max 0xF. 99 * @param buffer_id The Id of the buffer. Max 0xF.
95 * @param is_read_only true if the buffer is read-only. If false, the buffer is considered to have read-write access. 100 * @param is_read_only true if the buffer is read-only. If false, the buffer is considered to have
101 * read-write access.
96 * @return The created PXI buffer header. 102 * @return The created PXI buffer header.
97 * 103 *
98 * The next value is a phys-address of a table located in the BASE memregion. 104 * The next value is a phys-address of a table located in the BASE memregion.
99 */ 105 */
100inline u32 PXIBufferDesc(u32 size, unsigned buffer_id, bool is_read_only) { 106inline u32 PXIBufferDesc(u32 size, unsigned buffer_id, bool is_read_only) {
101 u32 type = PXIBuffer; 107 u32 type = PXIBuffer;
102 if (is_read_only) type |= 0x2; 108 if (is_read_only)
103 return type | (size << 8) | ((buffer_id & 0xF) << 4); 109 type |= 0x2;
110 return type | (size << 8) | ((buffer_id & 0xF) << 4);
104} 111}
105 112
106enum MappedBufferPermissions { 113enum MappedBufferPermissions {
@@ -115,12 +122,12 @@ constexpr u32 MappedBufferDesc(u32 size, MappedBufferPermissions perms) {
115 122
116union MappedBufferDescInfo { 123union MappedBufferDescInfo {
117 u32 raw; 124 u32 raw;
118 BitField< 4, 28, u32> size; 125 BitField<4, 28, u32> size;
119 BitField< 1, 2, MappedBufferPermissions> perms; 126 BitField<1, 2, MappedBufferPermissions> perms;
120}; 127};
121 128
122inline MappedBufferDescInfo ParseMappedBufferDesc(const u32 desc) { 129inline MappedBufferDescInfo ParseMappedBufferDesc(const u32 desc) {
123 return{ desc }; 130 return {desc};
124} 131}
125 132
126inline DescriptorType GetDescriptorType(u32 descriptor) { 133inline DescriptorType GetDescriptorType(u32 descriptor) {
@@ -153,7 +160,8 @@ static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of
153 * @return Pointer to command buffer 160 * @return Pointer to command buffer
154 */ 161 */
155inline u32* GetCommandBuffer(const int offset = 0) { 162inline u32* GetCommandBuffer(const int offset = 0) {
156 return (u32*)Memory::GetPointer(GetCurrentThread()->GetTLSAddress() + kCommandHeaderOffset + offset); 163 return (u32*)Memory::GetPointer(GetCurrentThread()->GetTLSAddress() + kCommandHeaderOffset +
164 offset);
157} 165}
158 166
159/** 167/**
@@ -183,10 +191,14 @@ public:
183 Session(); 191 Session();
184 ~Session() override; 192 ~Session() override;
185 193
186 std::string GetTypeName() const override { return "Session"; } 194 std::string GetTypeName() const override {
195 return "Session";
196 }
187 197
188 static const HandleType HANDLE_TYPE = HandleType::Session; 198 static const HandleType HANDLE_TYPE = HandleType::Session;
189 HandleType GetHandleType() const override { return HANDLE_TYPE; } 199 HandleType GetHandleType() const override {
200 return HANDLE_TYPE;
201 }
190 202
191 /** 203 /**
192 * Handles a synchronous call to this session using HLE emulation. Emulated <-> emulated calls 204 * Handles a synchronous call to this session using HLE emulation. Emulated <-> emulated calls
@@ -205,5 +217,4 @@ public:
205 ASSERT_MSG(!ShouldWait(), "object unavailable!"); 217 ASSERT_MSG(!ShouldWait(), "object unavailable!");
206 } 218 }
207}; 219};
208
209} 220}
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 6a22c8986..74f40930c 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -6,17 +6,21 @@
6 6
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8 8
9#include "core/memory.h"
10#include "core/hle/kernel/memory.h" 9#include "core/hle/kernel/memory.h"
11#include "core/hle/kernel/shared_memory.h" 10#include "core/hle/kernel/shared_memory.h"
11#include "core/memory.h"
12 12
13namespace Kernel { 13namespace Kernel {
14 14
15SharedMemory::SharedMemory() {} 15SharedMemory::SharedMemory() {
16SharedMemory::~SharedMemory() {} 16}
17SharedMemory::~SharedMemory() {
18}
17 19
18SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u32 size, MemoryPermission permissions, 20SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u32 size,
19 MemoryPermission other_permissions, VAddr address, MemoryRegion region, std::string name) { 21 MemoryPermission permissions,
22 MemoryPermission other_permissions, VAddr address,
23 MemoryRegion region, std::string name) {
20 SharedPtr<SharedMemory> shared_memory(new SharedMemory); 24 SharedPtr<SharedMemory> shared_memory(new SharedMemory);
21 25
22 shared_memory->owner_process = owner_process; 26 shared_memory->owner_process = owner_process;
@@ -31,7 +35,8 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
31 MemoryRegionInfo* memory_region = GetMemoryRegion(region); 35 MemoryRegionInfo* memory_region = GetMemoryRegion(region);
32 auto& linheap_memory = memory_region->linear_heap_memory; 36 auto& linheap_memory = memory_region->linear_heap_memory;
33 37
34 ASSERT_MSG(linheap_memory->size() + size <= memory_region->size, "Not enough space in region to allocate shared memory!"); 38 ASSERT_MSG(linheap_memory->size() + size <= memory_region->size,
39 "Not enough space in region to allocate shared memory!");
35 40
36 shared_memory->backing_block = linheap_memory; 41 shared_memory->backing_block = linheap_memory;
37 shared_memory->backing_block_offset = linheap_memory->size(); 42 shared_memory->backing_block_offset = linheap_memory->size();
@@ -39,7 +44,8 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
39 linheap_memory->insert(linheap_memory->end(), size, 0); 44 linheap_memory->insert(linheap_memory->end(), size, 0);
40 memory_region->used += size; 45 memory_region->used += size;
41 46
42 shared_memory->linear_heap_phys_address = Memory::FCRAM_PADDR + memory_region->base + shared_memory->backing_block_offset; 47 shared_memory->linear_heap_phys_address =
48 Memory::FCRAM_PADDR + memory_region->base + shared_memory->backing_block_offset;
43 49
44 // Increase the amount of used linear heap memory for the owner process. 50 // Increase the amount of used linear heap memory for the owner process.
45 if (shared_memory->owner_process != nullptr) { 51 if (shared_memory->owner_process != nullptr) {
@@ -51,18 +57,20 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
51 Kernel::g_current_process->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get()); 57 Kernel::g_current_process->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get());
52 } 58 }
53 } else { 59 } else {
54 // TODO(Subv): What happens if an application tries to create multiple memory blocks pointing to the same address? 60 // TODO(Subv): What happens if an application tries to create multiple memory blocks
61 // pointing to the same address?
55 auto& vm_manager = shared_memory->owner_process->vm_manager; 62 auto& vm_manager = shared_memory->owner_process->vm_manager;
56 // The memory is already available and mapped in the owner process. 63 // The memory is already available and mapped in the owner process.
57 auto vma = vm_manager.FindVMA(address)->second; 64 auto vma = vm_manager.FindVMA(address)->second;
58 // Copy it over to our own storage 65 // Copy it over to our own storage
59 shared_memory->backing_block = std::make_shared<std::vector<u8>>(vma.backing_block->data() + vma.offset, 66 shared_memory->backing_block = std::make_shared<std::vector<u8>>(
60 vma.backing_block->data() + vma.offset + size); 67 vma.backing_block->data() + vma.offset, vma.backing_block->data() + vma.offset + size);
61 shared_memory->backing_block_offset = 0; 68 shared_memory->backing_block_offset = 0;
62 // Unmap the existing pages 69 // Unmap the existing pages
63 vm_manager.UnmapRange(address, size); 70 vm_manager.UnmapRange(address, size);
64 // Map our own block into the address space 71 // Map our own block into the address space
65 vm_manager.MapMemoryBlock(address, shared_memory->backing_block, 0, size, MemoryState::Shared); 72 vm_manager.MapMemoryBlock(address, shared_memory->backing_block, 0, size,
73 MemoryState::Shared);
66 // Reprotect the block with the new permissions 74 // Reprotect the block with the new permissions
67 vm_manager.ReprotectRange(address, size, ConvertPermissions(permissions)); 75 vm_manager.ReprotectRange(address, size, ConvertPermissions(permissions));
68 } 76 }
@@ -71,8 +79,11 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
71 return shared_memory; 79 return shared_memory;
72} 80}
73 81
74SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, u32 offset, u32 size, 82SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block,
75 MemoryPermission permissions, MemoryPermission other_permissions, std::string name) { 83 u32 offset, u32 size,
84 MemoryPermission permissions,
85 MemoryPermission other_permissions,
86 std::string name) {
76 SharedPtr<SharedMemory> shared_memory(new SharedMemory); 87 SharedPtr<SharedMemory> shared_memory(new SharedMemory);
77 88
78 shared_memory->owner_process = nullptr; 89 shared_memory->owner_process = nullptr;
@@ -88,27 +99,31 @@ SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vecto
88} 99}
89 100
90ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermission permissions, 101ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermission permissions,
91 MemoryPermission other_permissions) { 102 MemoryPermission other_permissions) {
92 103
93 MemoryPermission own_other_permissions = target_process == owner_process ? this->permissions : this->other_permissions; 104 MemoryPermission own_other_permissions =
105 target_process == owner_process ? this->permissions : this->other_permissions;
94 106
95 // Automatically allocated memory blocks can only be mapped with other_permissions = DontCare 107 // Automatically allocated memory blocks can only be mapped with other_permissions = DontCare
96 if (base_address == 0 && other_permissions != MemoryPermission::DontCare) { 108 if (base_address == 0 && other_permissions != MemoryPermission::DontCare) {
97 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 109 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
110 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
98 } 111 }
99 112
100 // Error out if the requested permissions don't match what the creator process allows. 113 // Error out if the requested permissions don't match what the creator process allows.
101 if (static_cast<u32>(permissions) & ~static_cast<u32>(own_other_permissions)) { 114 if (static_cast<u32>(permissions) & ~static_cast<u32>(own_other_permissions)) {
102 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", 115 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match",
103 GetObjectId(), address, name.c_str()); 116 GetObjectId(), address, name.c_str());
104 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 117 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
118 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
105 } 119 }
106 120
107 // Heap-backed memory blocks can not be mapped with other_permissions = DontCare 121 // Heap-backed memory blocks can not be mapped with other_permissions = DontCare
108 if (base_address != 0 && other_permissions == MemoryPermission::DontCare) { 122 if (base_address != 0 && other_permissions == MemoryPermission::DontCare) {
109 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", 123 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match",
110 GetObjectId(), address, name.c_str()); 124 GetObjectId(), address, name.c_str());
111 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 125 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
126 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
112 } 127 }
113 128
114 // Error out if the provided permissions are not compatible with what the creator process needs. 129 // Error out if the provided permissions are not compatible with what the creator process needs.
@@ -116,12 +131,14 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
116 static_cast<u32>(this->permissions) & ~static_cast<u32>(other_permissions)) { 131 static_cast<u32>(this->permissions) & ~static_cast<u32>(other_permissions)) {
117 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", 132 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match",
118 GetObjectId(), address, name.c_str()); 133 GetObjectId(), address, name.c_str());
119 return ResultCode(ErrorDescription::WrongPermission, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 134 return ResultCode(ErrorDescription::WrongPermission, ErrorModule::OS,
135 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
120 } 136 }
121 137
122 // TODO(Subv): Check for the Shared Device Mem flag in the creator process. 138 // TODO(Subv): Check for the Shared Device Mem flag in the creator process.
123 /*if (was_created_with_shared_device_mem && address != 0) { 139 /*if (was_created_with_shared_device_mem && address != 0) {
124 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 140 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
141 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
125 }*/ 142 }*/
126 143
127 // TODO(Subv): The same process that created a SharedMemory object 144 // TODO(Subv): The same process that created a SharedMemory object
@@ -144,23 +161,29 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
144 } 161 }
145 162
146 // Map the memory block into the target process 163 // Map the memory block into the target process
147 auto result = target_process->vm_manager.MapMemoryBlock(target_address, backing_block, backing_block_offset, size, MemoryState::Shared); 164 auto result = target_process->vm_manager.MapMemoryBlock(
165 target_address, backing_block, backing_block_offset, size, MemoryState::Shared);
148 if (result.Failed()) { 166 if (result.Failed()) {
149 LOG_ERROR(Kernel, "cannot map id=%u, target_address=0x%08X name=%s, error mapping to virtual memory", 167 LOG_ERROR(
150 GetObjectId(), target_address, name.c_str()); 168 Kernel,
169 "cannot map id=%u, target_address=0x%08X name=%s, error mapping to virtual memory",
170 GetObjectId(), target_address, name.c_str());
151 return result.Code(); 171 return result.Code();
152 } 172 }
153 173
154 return target_process->vm_manager.ReprotectRange(target_address, size, ConvertPermissions(permissions)); 174 return target_process->vm_manager.ReprotectRange(target_address, size,
175 ConvertPermissions(permissions));
155} 176}
156 177
157ResultCode SharedMemory::Unmap(Process* target_process, VAddr address) { 178ResultCode SharedMemory::Unmap(Process* target_process, VAddr address) {
158 // TODO(Subv): Verify what happens if the application tries to unmap an address that is not mapped to a SharedMemory. 179 // TODO(Subv): Verify what happens if the application tries to unmap an address that is not
180 // mapped to a SharedMemory.
159 return target_process->vm_manager.UnmapRange(address, size); 181 return target_process->vm_manager.UnmapRange(address, size);
160} 182}
161 183
162VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) { 184VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) {
163 u32 masked_permissions = static_cast<u32>(permission) & static_cast<u32>(MemoryPermission::ReadWriteExecute); 185 u32 masked_permissions =
186 static_cast<u32>(permission) & static_cast<u32>(MemoryPermission::ReadWriteExecute);
164 return static_cast<VMAPermission>(masked_permissions); 187 return static_cast<VMAPermission>(masked_permissions);
165}; 188};
166 189
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index 0c404a9f8..afb142380 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -16,15 +16,15 @@ namespace Kernel {
16 16
17/// Permissions for mapped shared memory blocks 17/// Permissions for mapped shared memory blocks
18enum class MemoryPermission : u32 { 18enum class MemoryPermission : u32 {
19 None = 0, 19 None = 0,
20 Read = (1u << 0), 20 Read = (1u << 0),
21 Write = (1u << 1), 21 Write = (1u << 1),
22 ReadWrite = (Read | Write), 22 ReadWrite = (Read | Write),
23 Execute = (1u << 2), 23 Execute = (1u << 2),
24 ReadExecute = (Read | Execute), 24 ReadExecute = (Read | Execute),
25 WriteExecute = (Write | Execute), 25 WriteExecute = (Write | Execute),
26 ReadWriteExecute = (Read | Write | Execute), 26 ReadWriteExecute = (Read | Write | Execute),
27 DontCare = (1u << 28) 27 DontCare = (1u << 28)
28}; 28};
29 29
30class SharedMemory final : public Object { 30class SharedMemory final : public Object {
@@ -34,13 +34,18 @@ public:
34 * @param owner_process Process that created this shared memory object. 34 * @param owner_process Process that created this shared memory object.
35 * @param size Size of the memory block. Must be page-aligned. 35 * @param size Size of the memory block. Must be page-aligned.
36 * @param permissions Permission restrictions applied to the process which created the block. 36 * @param permissions Permission restrictions applied to the process which created the block.
37 * @param other_permissions Permission restrictions applied to other processes mapping the block. 37 * @param other_permissions Permission restrictions applied to other processes mapping the
38 * block.
38 * @param address The address from which to map the Shared Memory. 39 * @param address The address from which to map the Shared Memory.
39 * @param region If the address is 0, the shared memory will be allocated in this region of the linear heap. 40 * @param region If the address is 0, the shared memory will be allocated in this region of the
41 * linear heap.
40 * @param name Optional object name, used for debugging purposes. 42 * @param name Optional object name, used for debugging purposes.
41 */ 43 */
42 static SharedPtr<SharedMemory> Create(SharedPtr<Process> owner_process, u32 size, MemoryPermission permissions, 44 static SharedPtr<SharedMemory> Create(SharedPtr<Process> owner_process, u32 size,
43 MemoryPermission other_permissions, VAddr address = 0, MemoryRegion region = MemoryRegion::BASE, std::string name = "Unknown"); 45 MemoryPermission permissions,
46 MemoryPermission other_permissions, VAddr address = 0,
47 MemoryRegion region = MemoryRegion::BASE,
48 std::string name = "Unknown");
44 49
45 /** 50 /**
46 * Creates a shared memory object from a block of memory managed by an HLE applet. 51 * Creates a shared memory object from a block of memory managed by an HLE applet.
@@ -48,17 +53,27 @@ public:
48 * @param offset The offset into the heap block that the SharedMemory will map. 53 * @param offset The offset into the heap block that the SharedMemory will map.
49 * @param size Size of the memory block. Must be page-aligned. 54 * @param size Size of the memory block. Must be page-aligned.
50 * @param permissions Permission restrictions applied to the process which created the block. 55 * @param permissions Permission restrictions applied to the process which created the block.
51 * @param other_permissions Permission restrictions applied to other processes mapping the block. 56 * @param other_permissions Permission restrictions applied to other processes mapping the
57 * block.
52 * @param name Optional object name, used for debugging purposes. 58 * @param name Optional object name, used for debugging purposes.
53 */ 59 */
54 static SharedPtr<SharedMemory> CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, u32 offset, u32 size, 60 static SharedPtr<SharedMemory> CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block,
55 MemoryPermission permissions, MemoryPermission other_permissions, std::string name = "Unknown Applet"); 61 u32 offset, u32 size,
56 62 MemoryPermission permissions,
57 std::string GetTypeName() const override { return "SharedMemory"; } 63 MemoryPermission other_permissions,
58 std::string GetName() const override { return name; } 64 std::string name = "Unknown Applet");
65
66 std::string GetTypeName() const override {
67 return "SharedMemory";
68 }
69 std::string GetName() const override {
70 return name;
71 }
59 72
60 static const HandleType HANDLE_TYPE = HandleType::SharedMemory; 73 static const HandleType HANDLE_TYPE = HandleType::SharedMemory;
61 HandleType GetHandleType() const override { return HANDLE_TYPE; } 74 HandleType GetHandleType() const override {
75 return HANDLE_TYPE;
76 }
62 77
63 /** 78 /**
64 * Converts the specified MemoryPermission into the equivalent VMAPermission. 79 * Converts the specified MemoryPermission into the equivalent VMAPermission.
@@ -73,7 +88,8 @@ public:
73 * @param permissions Memory block map permissions (specified by SVC field) 88 * @param permissions Memory block map permissions (specified by SVC field)
74 * @param other_permissions Memory block map other permissions (specified by SVC field) 89 * @param other_permissions Memory block map other permissions (specified by SVC field)
75 */ 90 */
76 ResultCode Map(Process* target_process, VAddr address, MemoryPermission permissions, MemoryPermission other_permissions); 91 ResultCode Map(Process* target_process, VAddr address, MemoryPermission permissions,
92 MemoryPermission other_permissions);
77 93
78 /** 94 /**
79 * Unmaps a shared memory block from the specified address in system memory 95 * Unmaps a shared memory block from the specified address in system memory
@@ -94,7 +110,8 @@ public:
94 SharedPtr<Process> owner_process; 110 SharedPtr<Process> owner_process;
95 /// Address of shared memory block in the owner process if specified. 111 /// Address of shared memory block in the owner process if specified.
96 VAddr base_address; 112 VAddr base_address;
97 /// Physical address of the shared memory block in the linear heap if no address was specified during creation. 113 /// Physical address of the shared memory block in the linear heap if no address was specified
114 /// during creation.
98 PAddr linear_heap_phys_address; 115 PAddr linear_heap_phys_address;
99 /// Backing memory for this shared memory block. 116 /// Backing memory for this shared memory block.
100 std::shared_ptr<std::vector<u8>> backing_block; 117 std::shared_ptr<std::vector<u8>> backing_block;
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index f1e5cf3cb..59272715f 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -18,10 +18,10 @@
18#include "core/core_timing.h" 18#include "core/core_timing.h"
19#include "core/hle/hle.h" 19#include "core/hle/hle.h"
20#include "core/hle/kernel/kernel.h" 20#include "core/hle/kernel/kernel.h"
21#include "core/hle/kernel/process.h"
22#include "core/hle/kernel/thread.h"
23#include "core/hle/kernel/memory.h" 21#include "core/hle/kernel/memory.h"
24#include "core/hle/kernel/mutex.h" 22#include "core/hle/kernel/mutex.h"
23#include "core/hle/kernel/process.h"
24#include "core/hle/kernel/thread.h"
25#include "core/hle/result.h" 25#include "core/hle/result.h"
26#include "core/memory.h" 26#include "core/memory.h"
27 27
@@ -46,7 +46,7 @@ static Kernel::HandleTable wakeup_callback_handle_table;
46static std::vector<SharedPtr<Thread>> thread_list; 46static std::vector<SharedPtr<Thread>> thread_list;
47 47
48// Lists only ready thread ids. 48// Lists only ready thread ids.
49static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST+1> ready_queue; 49static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST + 1> ready_queue;
50 50
51static Thread* current_thread; 51static Thread* current_thread;
52 52
@@ -61,8 +61,10 @@ inline static u32 const NewThreadId() {
61 return next_thread_id++; 61 return next_thread_id++;
62} 62}
63 63
64Thread::Thread() {} 64Thread::Thread() {
65Thread::~Thread() {} 65}
66Thread::~Thread() {
67}
66 68
67Thread* GetCurrentThread() { 69Thread* GetCurrentThread() {
68 return current_thread; 70 return current_thread;
@@ -103,7 +105,7 @@ void Thread::Stop() {
103 105
104 // Clean up thread from ready queue 106 // Clean up thread from ready queue
105 // This is only needed when the thread is termintated forcefully (SVC TerminateProcess) 107 // This is only needed when the thread is termintated forcefully (SVC TerminateProcess)
106 if (status == THREADSTATUS_READY){ 108 if (status == THREADSTATUS_READY) {
107 ready_queue.remove(current_priority, this); 109 ready_queue.remove(current_priority, this);
108 } 110 }
109 111
@@ -119,7 +121,8 @@ void Thread::Stop() {
119 121
120 // Mark the TLS slot in the thread's page as free. 122 // Mark the TLS slot in the thread's page as free.
121 u32 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE; 123 u32 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE;
122 u32 tls_slot = ((tls_address - Memory::TLS_AREA_VADDR) % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE; 124 u32 tls_slot =
125 ((tls_address - Memory::TLS_AREA_VADDR) % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE;
123 Kernel::g_current_process->tls_slots[tls_page].reset(tls_slot); 126 Kernel::g_current_process->tls_slots[tls_page].reset(tls_slot);
124 127
125 HLE::Reschedule(__func__); 128 HLE::Reschedule(__func__);
@@ -137,7 +140,7 @@ Thread* ArbitrateHighestPriorityThread(u32 address) {
137 if (thread == nullptr) 140 if (thread == nullptr)
138 continue; 141 continue;
139 142
140 if(thread->current_priority <= priority) { 143 if (thread->current_priority <= priority) {
141 highest_priority_thread = thread.get(); 144 highest_priority_thread = thread.get();
142 priority = thread->current_priority; 145 priority = thread->current_priority;
143 } 146 }
@@ -170,7 +173,7 @@ static void PriorityBoostStarvedThreads() {
170 // on hardware. However, this is almost certainly not perfect, and the real CTR OS scheduler 173 // on hardware. However, this is almost certainly not perfect, and the real CTR OS scheduler
171 // should probably be reversed to verify this. 174 // should probably be reversed to verify this.
172 175
173 const u64 boost_timeout = 2000000; // Boost threads that have been ready for > this long 176 const u64 boost_timeout = 2000000; // Boost threads that have been ready for > this long
174 177
175 u64 delta = current_ticks - thread->last_running_ticks; 178 u64 delta = current_ticks - thread->last_running_ticks;
176 179
@@ -193,10 +196,12 @@ static std::tuple<u32*, u32*> GetWaitSynchTimeoutParameterRegister(Thread* threa
193 196
194 if ((thumb_mode && thumb_inst == 0xDF24) || (!thumb_mode && inst == 0x0F000024)) { 197 if ((thumb_mode && thumb_inst == 0xDF24) || (!thumb_mode && inst == 0x0F000024)) {
195 // svc #0x24 (WaitSynchronization1) 198 // svc #0x24 (WaitSynchronization1)
196 return std::make_tuple(&thread->context.cpu_registers[2], &thread->context.cpu_registers[3]); 199 return std::make_tuple(&thread->context.cpu_registers[2],
200 &thread->context.cpu_registers[3]);
197 } else if ((thumb_mode && thumb_inst == 0xDF25) || (!thumb_mode && inst == 0x0F000025)) { 201 } else if ((thumb_mode && thumb_inst == 0xDF25) || (!thumb_mode && inst == 0x0F000025)) {
198 // svc #0x25 (WaitSynchronizationN) 202 // svc #0x25 (WaitSynchronizationN)
199 return std::make_tuple(&thread->context.cpu_registers[0], &thread->context.cpu_registers[4]); 203 return std::make_tuple(&thread->context.cpu_registers[0],
204 &thread->context.cpu_registers[4]);
200 } 205 }
201 206
202 UNREACHABLE(); 207 UNREACHABLE();
@@ -245,7 +250,8 @@ static void SwitchContext(Thread* new_thread) {
245 250
246 // Load context of new thread 251 // Load context of new thread
247 if (new_thread) { 252 if (new_thread) {
248 DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY, "Thread must be ready to become running."); 253 DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY,
254 "Thread must be ready to become running.");
249 255
250 // Cancel any outstanding wakeup events for this thread 256 // Cancel any outstanding wakeup events for this thread
251 CoreTiming::UnscheduleEvent(ThreadWakeupEventType, new_thread->callback_handle); 257 CoreTiming::UnscheduleEvent(ThreadWakeupEventType, new_thread->callback_handle);
@@ -263,7 +269,7 @@ static void SwitchContext(Thread* new_thread) {
263 new_thread->context.pc -= thumb_mode ? 2 : 4; 269 new_thread->context.pc -= thumb_mode ? 2 : 4;
264 270
265 // Get the register for timeout parameter 271 // Get the register for timeout parameter
266 u32* timeout_low, *timeout_high; 272 u32 *timeout_low, *timeout_high;
267 std::tie(timeout_low, timeout_high) = GetWaitSynchTimeoutParameterRegister(new_thread); 273 std::tie(timeout_low, timeout_high) = GetWaitSynchTimeoutParameterRegister(new_thread);
268 274
269 // Update the timeout parameter 275 // Update the timeout parameter
@@ -307,7 +313,7 @@ static Thread* PopNextReadyThread() {
307 // Otherwise just keep going with the current thread 313 // Otherwise just keep going with the current thread
308 next = thread; 314 next = thread;
309 } 315 }
310 } else { 316 } else {
311 next = ready_queue.pop_first(); 317 next = ready_queue.pop_first();
312 } 318 }
313 319
@@ -321,7 +327,8 @@ void WaitCurrentThread_Sleep() {
321 HLE::Reschedule(__func__); 327 HLE::Reschedule(__func__);
322} 328}
323 329
324void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, bool wait_set_output, bool wait_all) { 330void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects,
331 bool wait_set_output, bool wait_all) {
325 Thread* thread = GetCurrentThread(); 332 Thread* thread = GetCurrentThread();
326 thread->wait_set_output = wait_set_output; 333 thread->wait_set_output = wait_set_output;
327 thread->wait_all = wait_all; 334 thread->wait_all = wait_all;
@@ -352,7 +359,8 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
352 359
353 if (thread->status == THREADSTATUS_WAIT_SYNCH || thread->status == THREADSTATUS_WAIT_ARB) { 360 if (thread->status == THREADSTATUS_WAIT_SYNCH || thread->status == THREADSTATUS_WAIT_ARB) {
354 thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS, 361 thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS,
355 ErrorSummary::StatusChanged, ErrorLevel::Info)); 362 ErrorSummary::StatusChanged,
363 ErrorLevel::Info));
356 364
357 if (thread->wait_set_output) 365 if (thread->wait_set_output)
358 thread->SetWaitSynchronizationOutput(-1); 366 thread->SetWaitSynchronizationOutput(-1);
@@ -372,25 +380,25 @@ void Thread::WakeAfterDelay(s64 nanoseconds) {
372 380
373void Thread::ResumeFromWait() { 381void Thread::ResumeFromWait() {
374 switch (status) { 382 switch (status) {
375 case THREADSTATUS_WAIT_SYNCH: 383 case THREADSTATUS_WAIT_SYNCH:
376 case THREADSTATUS_WAIT_ARB: 384 case THREADSTATUS_WAIT_ARB:
377 case THREADSTATUS_WAIT_SLEEP: 385 case THREADSTATUS_WAIT_SLEEP:
378 break; 386 break;
379 387
380 case THREADSTATUS_READY: 388 case THREADSTATUS_READY:
381 // If the thread is waiting on multiple wait objects, it might be awoken more than once 389 // If the thread is waiting on multiple wait objects, it might be awoken more than once
382 // before actually resuming. We can ignore subsequent wakeups if the thread status has 390 // before actually resuming. We can ignore subsequent wakeups if the thread status has
383 // already been set to THREADSTATUS_READY. 391 // already been set to THREADSTATUS_READY.
384 return; 392 return;
385 393
386 case THREADSTATUS_RUNNING: 394 case THREADSTATUS_RUNNING:
387 DEBUG_ASSERT_MSG(false, "Thread with object id %u has already resumed.", GetObjectId()); 395 DEBUG_ASSERT_MSG(false, "Thread with object id %u has already resumed.", GetObjectId());
388 return; 396 return;
389 case THREADSTATUS_DEAD: 397 case THREADSTATUS_DEAD:
390 // This should never happen, as threads must complete before being stopped. 398 // This should never happen, as threads must complete before being stopped.
391 DEBUG_ASSERT_MSG(false, "Thread with object id %u cannot be resumed because it's DEAD.", 399 DEBUG_ASSERT_MSG(false, "Thread with object id %u cannot be resumed because it's DEAD.",
392 GetObjectId()); 400 GetObjectId());
393 return; 401 return;
394 } 402 }
395 403
396 ready_queue.push_back(current_priority, this); 404 ready_queue.push_back(current_priority, this);
@@ -405,7 +413,8 @@ static void DebugThreadQueue() {
405 if (!thread) { 413 if (!thread) {
406 LOG_DEBUG(Kernel, "Current: NO CURRENT THREAD"); 414 LOG_DEBUG(Kernel, "Current: NO CURRENT THREAD");
407 } else { 415 } else {
408 LOG_DEBUG(Kernel, "0x%02X %u (current)", thread->current_priority, GetCurrentThread()->GetObjectId()); 416 LOG_DEBUG(Kernel, "0x%02X %u (current)", thread->current_priority,
417 GetCurrentThread()->GetObjectId());
409 } 418 }
410 419
411 for (auto& t : thread_list) { 420 for (auto& t : thread_list) {
@@ -448,7 +457,8 @@ std::tuple<u32, u32, bool> GetFreeThreadLocalSlot(std::vector<std::bitset<8>>& t
448 * @param entry_point Address of entry point for execution 457 * @param entry_point Address of entry point for execution
449 * @param arg User argument for thread 458 * @param arg User argument for thread
450 */ 459 */
451static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) { 460static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point,
461 u32 arg) {
452 memset(&context, 0, sizeof(Core::ThreadContext)); 462 memset(&context, 0, sizeof(Core::ThreadContext));
453 463
454 context.cpu_registers[0] = arg; 464 context.cpu_registers[0] = arg;
@@ -458,11 +468,11 @@ static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32
458} 468}
459 469
460ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority, 470ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority,
461 u32 arg, s32 processor_id, VAddr stack_top) { 471 u32 arg, s32 processor_id, VAddr stack_top) {
462 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { 472 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) {
463 s32 new_priority = MathUtil::Clamp<s32>(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); 473 s32 new_priority = MathUtil::Clamp<s32>(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST);
464 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", 474 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", name.c_str(),
465 name.c_str(), priority, new_priority); 475 priority, new_priority);
466 // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm 476 // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm
467 // validity of this 477 // validity of this
468 priority = new_priority; 478 priority = new_priority;
@@ -472,7 +482,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
472 LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point); 482 LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point);
473 // TODO: Verify error 483 // TODO: Verify error
474 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, 484 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
475 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 485 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
476 } 486 }
477 487
478 SharedPtr<Thread> thread(new Thread); 488 SharedPtr<Thread> thread(new Thread);
@@ -511,8 +521,10 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
511 auto& linheap_memory = memory_region->linear_heap_memory; 521 auto& linheap_memory = memory_region->linear_heap_memory;
512 522
513 if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) { 523 if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) {
514 LOG_ERROR(Kernel_SVC, "Not enough space in region to allocate a new TLS page for thread"); 524 LOG_ERROR(Kernel_SVC,
515 return ResultCode(ErrorDescription::OutOfMemory, ErrorModule::Kernel, ErrorSummary::OutOfResource, ErrorLevel::Permanent); 525 "Not enough space in region to allocate a new TLS page for thread");
526 return ResultCode(ErrorDescription::OutOfMemory, ErrorModule::Kernel,
527 ErrorSummary::OutOfResource, ErrorLevel::Permanent);
516 } 528 }
517 529
518 u32 offset = linheap_memory->size(); 530 u32 offset = linheap_memory->size();
@@ -537,7 +549,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
537 549
538 // Mark the slot as used 550 // Mark the slot as used
539 tls_slots[available_page].set(available_slot); 551 tls_slots[available_page].set(available_slot);
540 thread->tls_address = Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE + available_slot * Memory::TLS_ENTRY_SIZE; 552 thread->tls_address = Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE +
553 available_slot * Memory::TLS_ENTRY_SIZE;
541 554
542 // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used 555 // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used
543 // to initialize the context 556 // to initialize the context
@@ -551,10 +564,12 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
551 return MakeResult<SharedPtr<Thread>>(std::move(thread)); 564 return MakeResult<SharedPtr<Thread>>(std::move(thread));
552} 565}
553 566
554// TODO(peachum): Remove this. Range checking should be done, and an appropriate error should be returned. 567// TODO(peachum): Remove this. Range checking should be done, and an appropriate error should be
568// returned.
555static void ClampPriority(const Thread* thread, s32* priority) { 569static void ClampPriority(const Thread* thread, s32* priority) {
556 if (*priority < THREADPRIO_HIGHEST || *priority > THREADPRIO_LOWEST) { 570 if (*priority < THREADPRIO_HIGHEST || *priority > THREADPRIO_LOWEST) {
557 DEBUG_ASSERT_MSG(false, "Application passed an out of range priority. An error should be returned."); 571 DEBUG_ASSERT_MSG(
572 false, "Application passed an out of range priority. An error should be returned.");
558 573
559 s32 new_priority = MathUtil::Clamp<s32>(*priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); 574 s32 new_priority = MathUtil::Clamp<s32>(*priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST);
560 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", 575 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d",
@@ -586,12 +601,13 @@ SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) {
586 DEBUG_ASSERT(!GetCurrentThread()); 601 DEBUG_ASSERT(!GetCurrentThread());
587 602
588 // Initialize new "main" thread 603 // Initialize new "main" thread
589 auto thread_res = Thread::Create("main", entry_point, priority, 0, 604 auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0,
590 THREADPROCESSORID_0, Memory::HEAP_VADDR_END); 605 Memory::HEAP_VADDR_END);
591 606
592 SharedPtr<Thread> thread = thread_res.MoveFrom(); 607 SharedPtr<Thread> thread = thread_res.MoveFrom();
593 608
594 thread->context.fpscr = FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO | FPSCR_IXC; // 0x03C00010 609 thread->context.fpscr =
610 FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO | FPSCR_IXC; // 0x03C00010
595 611
596 // Run new "main" thread 612 // Run new "main" thread
597 SwitchContext(thread.get()); 613 SwitchContext(thread.get());
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index deab5d5a6..2ed5cf74e 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -17,29 +17,29 @@
17#include "core/hle/kernel/kernel.h" 17#include "core/hle/kernel/kernel.h"
18#include "core/hle/result.h" 18#include "core/hle/result.h"
19 19
20enum ThreadPriority : s32{ 20enum ThreadPriority : s32 {
21 THREADPRIO_HIGHEST = 0, ///< Highest thread priority 21 THREADPRIO_HIGHEST = 0, ///< Highest thread priority
22 THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps 22 THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps
23 THREADPRIO_DEFAULT = 48, ///< Default thread priority for userland apps 23 THREADPRIO_DEFAULT = 48, ///< Default thread priority for userland apps
24 THREADPRIO_LOWEST = 63, ///< Lowest thread priority 24 THREADPRIO_LOWEST = 63, ///< Lowest thread priority
25}; 25};
26 26
27enum ThreadProcessorId : s32 { 27enum ThreadProcessorId : s32 {
28 THREADPROCESSORID_DEFAULT = -2, ///< Run thread on default core specified by exheader 28 THREADPROCESSORID_DEFAULT = -2, ///< Run thread on default core specified by exheader
29 THREADPROCESSORID_ALL = -1, ///< Run thread on either core 29 THREADPROCESSORID_ALL = -1, ///< Run thread on either core
30 THREADPROCESSORID_0 = 0, ///< Run thread on core 0 (AppCore) 30 THREADPROCESSORID_0 = 0, ///< Run thread on core 0 (AppCore)
31 THREADPROCESSORID_1 = 1, ///< Run thread on core 1 (SysCore) 31 THREADPROCESSORID_1 = 1, ///< Run thread on core 1 (SysCore)
32 THREADPROCESSORID_MAX = 2, ///< Processor ID must be less than this 32 THREADPROCESSORID_MAX = 2, ///< Processor ID must be less than this
33}; 33};
34 34
35enum ThreadStatus { 35enum ThreadStatus {
36 THREADSTATUS_RUNNING, ///< Currently running 36 THREADSTATUS_RUNNING, ///< Currently running
37 THREADSTATUS_READY, ///< Ready to run 37 THREADSTATUS_READY, ///< Ready to run
38 THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter 38 THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter
39 THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC 39 THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC
40 THREADSTATUS_WAIT_SYNCH, ///< Waiting due to a WaitSynchronization SVC 40 THREADSTATUS_WAIT_SYNCH, ///< Waiting due to a WaitSynchronization SVC
41 THREADSTATUS_DORMANT, ///< Created but not yet made ready 41 THREADSTATUS_DORMANT, ///< Created but not yet made ready
42 THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated 42 THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated
43}; 43};
44 44
45namespace Kernel { 45namespace Kernel {
@@ -60,13 +60,19 @@ public:
60 * @return A shared pointer to the newly created thread 60 * @return A shared pointer to the newly created thread
61 */ 61 */
62 static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority, 62 static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority,
63 u32 arg, s32 processor_id, VAddr stack_top); 63 u32 arg, s32 processor_id, VAddr stack_top);
64 64
65 std::string GetName() const override { return name; } 65 std::string GetName() const override {
66 std::string GetTypeName() const override { return "Thread"; } 66 return name;
67 }
68 std::string GetTypeName() const override {
69 return "Thread";
70 }
67 71
68 static const HandleType HANDLE_TYPE = HandleType::Thread; 72 static const HandleType HANDLE_TYPE = HandleType::Thread;
69 HandleType GetHandleType() const override { return HANDLE_TYPE; } 73 HandleType GetHandleType() const override {
74 return HANDLE_TYPE;
75 }
70 76
71 bool ShouldWait() override; 77 bool ShouldWait() override;
72 void Acquire() override; 78 void Acquire() override;
@@ -75,7 +81,9 @@ public:
75 * Gets the thread's current priority 81 * Gets the thread's current priority
76 * @return The current thread's priority 82 * @return The current thread's priority
77 */ 83 */
78 s32 GetPriority() const { return current_priority; } 84 s32 GetPriority() const {
85 return current_priority;
86 }
79 87
80 /** 88 /**
81 * Sets the thread's current priority 89 * Sets the thread's current priority
@@ -93,7 +101,9 @@ public:
93 * Gets the thread's thread ID 101 * Gets the thread's thread ID
94 * @return The thread's ID 102 * @return The thread's ID
95 */ 103 */
96 u32 GetThreadId() const { return thread_id; } 104 u32 GetThreadId() const {
105 return thread_id;
106 }
97 107
98 /** 108 /**
99 * Resumes a thread from waiting 109 * Resumes a thread from waiting
@@ -127,7 +137,9 @@ public:
127 * Returns the Thread Local Storage address of the current thread 137 * Returns the Thread Local Storage address of the current thread
128 * @returns VAddr of the thread's TLS 138 * @returns VAddr of the thread's TLS
129 */ 139 */
130 VAddr GetTLSAddress() const { return tls_address; } 140 VAddr GetTLSAddress() const {
141 return tls_address;
142 }
131 143
132 Core::ThreadContext context; 144 Core::ThreadContext context;
133 145
@@ -137,8 +149,8 @@ public:
137 u32 entry_point; 149 u32 entry_point;
138 u32 stack_top; 150 u32 stack_top;
139 151
140 s32 nominal_priority; ///< Nominal thread priority, as set by the emulated application 152 s32 nominal_priority; ///< Nominal thread priority, as set by the emulated application
141 s32 current_priority; ///< Current thread priority, can be temporarily changed 153 s32 current_priority; ///< Current thread priority, can be temporarily changed
142 154
143 u64 last_running_ticks; ///< CPU tick when thread was last running 155 u64 last_running_ticks; ///< CPU tick when thread was last running
144 156
@@ -151,11 +163,11 @@ public:
151 /// Mutexes currently held by this thread, which will be released when it exits. 163 /// Mutexes currently held by this thread, which will be released when it exits.
152 boost::container::flat_set<SharedPtr<Mutex>> held_mutexes; 164 boost::container::flat_set<SharedPtr<Mutex>> held_mutexes;
153 165
154 SharedPtr<Process> owner_process; ///< Process that owns this thread 166 SharedPtr<Process> owner_process; ///< Process that owns this thread
155 std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on 167 std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on
156 VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address 168 VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address
157 bool wait_all; ///< True if the thread is waiting on all objects before resuming 169 bool wait_all; ///< True if the thread is waiting on all objects before resuming
158 bool wait_set_output; ///< True if the output parameter should be set on thread wakeup 170 bool wait_set_output; ///< True if the output parameter should be set on thread wakeup
159 171
160 std::string name; 172 std::string name;
161 173
@@ -205,10 +217,12 @@ void WaitCurrentThread_Sleep();
205/** 217/**
206 * Waits the current thread from a WaitSynchronization call 218 * Waits the current thread from a WaitSynchronization call
207 * @param wait_objects Kernel objects that we are waiting on 219 * @param wait_objects Kernel objects that we are waiting on
208 * @param wait_set_output If true, set the output parameter on thread wakeup (for WaitSynchronizationN only) 220 * @param wait_set_output If true, set the output parameter on thread wakeup (for
221 * WaitSynchronizationN only)
209 * @param wait_all If true, wait on all objects before resuming (for WaitSynchronizationN only) 222 * @param wait_all If true, wait on all objects before resuming (for WaitSynchronizationN only)
210 */ 223 */
211void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, bool wait_set_output, bool wait_all); 224void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects,
225 bool wait_set_output, bool wait_all);
212 226
213/** 227/**
214 * Waits the current thread from an ArbitrateAddress call 228 * Waits the current thread from an ArbitrateAddress call
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index b8daaeede..255cb1aca 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -9,8 +9,8 @@
9 9
10#include "core/core_timing.h" 10#include "core/core_timing.h"
11#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/timer.h"
13#include "core/hle/kernel/thread.h" 12#include "core/hle/kernel/thread.h"
13#include "core/hle/kernel/timer.h"
14 14
15namespace Kernel { 15namespace Kernel {
16 16
@@ -20,8 +20,10 @@ static int timer_callback_event_type;
20// us to simply use a pool index or similar. 20// us to simply use a pool index or similar.
21static Kernel::HandleTable timer_callback_handle_table; 21static Kernel::HandleTable timer_callback_handle_table;
22 22
23Timer::Timer() {} 23Timer::Timer() {
24Timer::~Timer() {} 24}
25Timer::~Timer() {
26}
25 27
26SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) { 28SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) {
27 SharedPtr<Timer> timer(new Timer); 29 SharedPtr<Timer> timer(new Timer);
@@ -41,7 +43,7 @@ bool Timer::ShouldWait() {
41} 43}
42 44
43void Timer::Acquire() { 45void Timer::Acquire() {
44 ASSERT_MSG( !ShouldWait(), "object unavailable!"); 46 ASSERT_MSG(!ShouldWait(), "object unavailable!");
45 47
46 if (reset_type == ResetType::OneShot) 48 if (reset_type == ResetType::OneShot)
47 signaled = false; 49 signaled = false;
@@ -55,8 +57,8 @@ void Timer::Set(s64 initial, s64 interval) {
55 interval_delay = interval; 57 interval_delay = interval;
56 58
57 u64 initial_microseconds = initial / 1000; 59 u64 initial_microseconds = initial / 1000;
58 CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), 60 CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type,
59 timer_callback_event_type, callback_handle); 61 callback_handle);
60 62
61 HLE::Reschedule(__func__); 63 HLE::Reschedule(__func__);
62} 64}
@@ -73,7 +75,8 @@ void Timer::Clear() {
73 75
74/// The timer callback event, called when a timer is fired 76/// The timer callback event, called when a timer is fired
75static void TimerCallback(u64 timer_handle, int cycles_late) { 77static void TimerCallback(u64 timer_handle, int cycles_late) {
76 SharedPtr<Timer> timer = timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle)); 78 SharedPtr<Timer> timer =
79 timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle));
77 80
78 if (timer == nullptr) { 81 if (timer == nullptr) {
79 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08" PRIx64, timer_handle); 82 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08" PRIx64, timer_handle);
@@ -91,7 +94,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
91 // Reschedule the timer with the interval delay 94 // Reschedule the timer with the interval delay
92 u64 interval_microseconds = timer->interval_delay / 1000; 95 u64 interval_microseconds = timer->interval_delay / 1000;
93 CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late, 96 CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late,
94 timer_callback_event_type, timer_handle); 97 timer_callback_event_type, timer_handle);
95 } 98 }
96} 99}
97 100
diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h
index b1db60e8f..97cd0d63c 100644
--- a/src/core/hle/kernel/timer.h
+++ b/src/core/hle/kernel/timer.h
@@ -21,19 +21,25 @@ public:
21 */ 21 */
22 static SharedPtr<Timer> Create(ResetType reset_type, std::string name = "Unknown"); 22 static SharedPtr<Timer> Create(ResetType reset_type, std::string name = "Unknown");
23 23
24 std::string GetTypeName() const override { return "Timer"; } 24 std::string GetTypeName() const override {
25 std::string GetName() const override { return name; } 25 return "Timer";
26 }
27 std::string GetName() const override {
28 return name;
29 }
26 30
27 static const HandleType HANDLE_TYPE = HandleType::Timer; 31 static const HandleType HANDLE_TYPE = HandleType::Timer;
28 HandleType GetHandleType() const override { return HANDLE_TYPE; } 32 HandleType GetHandleType() const override {
33 return HANDLE_TYPE;
34 }
29 35
30 ResetType reset_type; ///< The ResetType of this timer 36 ResetType reset_type; ///< The ResetType of this timer
31 37
32 bool signaled; ///< Whether the timer has been signaled or not 38 bool signaled; ///< Whether the timer has been signaled or not
33 std::string name; ///< Name of timer (optional) 39 std::string name; ///< Name of timer (optional)
34 40
35 u64 initial_delay; ///< The delay until the timer fires for the first time 41 u64 initial_delay; ///< The delay until the timer fires for the first time
36 u64 interval_delay; ///< The delay until the timer fires after the first time 42 u64 interval_delay; ///< The delay until the timer fires after the first time
37 43
38 bool ShouldWait() override; 44 bool ShouldWait() override;
39 void Acquire() override; 45 void Acquire() override;
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index 066146cff..4ad86cf48 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -15,8 +15,8 @@ namespace Kernel {
15 15
16static const char* GetMemoryStateName(MemoryState state) { 16static const char* GetMemoryStateName(MemoryState state) {
17 static const char* names[] = { 17 static const char* names[] = {
18 "Free", "Reserved", "IO", "Static", "Code", "Private", "Shared", "Continuous", "Aliased", 18 "Free", "Reserved", "IO", "Static", "Code", "Private",
19 "Alias", "AliasCode", "Locked", 19 "Shared", "Continuous", "Aliased", "Alias", "AliasCode", "Locked",
20 }; 20 };
21 21
22 return names[(int)state]; 22 return names[(int)state];
@@ -24,13 +24,12 @@ static const char* GetMemoryStateName(MemoryState state) {
24 24
25bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { 25bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const {
26 ASSERT(base + size == next.base); 26 ASSERT(base + size == next.base);
27 if (permissions != next.permissions || 27 if (permissions != next.permissions || meminfo_state != next.meminfo_state ||
28 meminfo_state != next.meminfo_state || 28 type != next.type) {
29 type != next.type) {
30 return false; 29 return false;
31 } 30 }
32 if (type == VMAType::AllocatedMemoryBlock && 31 if (type == VMAType::AllocatedMemoryBlock &&
33 (backing_block != next.backing_block || offset + size != next.offset)) { 32 (backing_block != next.backing_block || offset + size != next.offset)) {
34 return false; 33 return false;
35 } 34 }
36 if (type == VMAType::BackingMemory && backing_memory + size != next.backing_memory) { 35 if (type == VMAType::BackingMemory && backing_memory + size != next.backing_memory) {
@@ -70,7 +69,9 @@ VMManager::VMAHandle VMManager::FindVMA(VAddr target) const {
70} 69}
71 70
72ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, 71ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target,
73 std::shared_ptr<std::vector<u8>> block, size_t offset, u32 size, MemoryState state) { 72 std::shared_ptr<std::vector<u8>> block,
73 size_t offset, u32 size,
74 MemoryState state) {
74 ASSERT(block != nullptr); 75 ASSERT(block != nullptr);
75 ASSERT(offset + size <= block->size()); 76 ASSERT(offset + size <= block->size());
76 77
@@ -89,7 +90,8 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target,
89 return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); 90 return MakeResult<VMAHandle>(MergeAdjacent(vma_handle));
90} 91}
91 92
92ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8 * memory, u32 size, MemoryState state) { 93ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* memory, u32 size,
94 MemoryState state) {
93 ASSERT(memory != nullptr); 95 ASSERT(memory != nullptr);
94 96
95 // This is the appropriately sized VMA that will turn into our allocation. 97 // This is the appropriately sized VMA that will turn into our allocation.
@@ -106,7 +108,9 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8 * m
106 return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); 108 return MakeResult<VMAHandle>(MergeAdjacent(vma_handle));
107} 109}
108 110
109ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state, Memory::MMIORegionPointer mmio_handler) { 111ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size,
112 MemoryState state,
113 Memory::MMIORegionPointer mmio_handler) {
110 // This is the appropriately sized VMA that will turn into our allocation. 114 // This is the appropriately sized VMA that will turn into our allocation.
111 CASCADE_RESULT(VMAIter vma_handle, CarveVMA(target, size)); 115 CASCADE_RESULT(VMAIter vma_handle, CarveVMA(target, size));
112 VirtualMemoryArea& final_vma = vma_handle->second; 116 VirtualMemoryArea& final_vma = vma_handle->second;
@@ -191,15 +195,16 @@ void VMManager::RefreshMemoryBlockMappings(const std::vector<u8>* block) {
191void VMManager::LogLayout(Log::Level log_level) const { 195void VMManager::LogLayout(Log::Level log_level) const {
192 for (const auto& p : vma_map) { 196 for (const auto& p : vma_map) {
193 const VirtualMemoryArea& vma = p.second; 197 const VirtualMemoryArea& vma = p.second;
194 LOG_GENERIC(Log::Class::Kernel, log_level, "%08X - %08X size: %8X %c%c%c %s", 198 LOG_GENERIC(Log::Class::Kernel, log_level, "%08X - %08X size: %8X %c%c%c %s", vma.base,
195 vma.base, vma.base + vma.size, vma.size, 199 vma.base + vma.size, vma.size,
196 (u8)vma.permissions & (u8)VMAPermission::Read ? 'R' : '-', 200 (u8)vma.permissions & (u8)VMAPermission::Read ? 'R' : '-',
197 (u8)vma.permissions & (u8)VMAPermission::Write ? 'W' : '-', 201 (u8)vma.permissions & (u8)VMAPermission::Write ? 'W' : '-',
198 (u8)vma.permissions & (u8)VMAPermission::Execute ? 'X' : '-', GetMemoryStateName(vma.meminfo_state)); 202 (u8)vma.permissions & (u8)VMAPermission::Execute ? 'X' : '-',
203 GetMemoryStateName(vma.meminfo_state));
199 } 204 }
200} 205}
201 206
202VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle & iter) { 207VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle& iter) {
203 // This uses a neat C++ trick to convert a const_iterator to a regular iterator, given 208 // This uses a neat C++ trick to convert a const_iterator to a regular iterator, given
204 // non-const access to its container. 209 // non-const access to its container.
205 return vma_map.erase(iter, iter); // Erases an empty range of elements 210 return vma_map.erase(iter, iter); // Erases an empty range of elements
@@ -337,5 +342,4 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
337 break; 342 break;
338 } 343 }
339} 344}
340
341} 345}
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index 91d40655b..fbcd9870f 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -15,13 +15,13 @@
15 15
16namespace Kernel { 16namespace Kernel {
17 17
18const ResultCode ERR_INVALID_ADDRESS{ // 0xE0E01BF5 18const ResultCode ERR_INVALID_ADDRESS{// 0xE0E01BF5
19 ErrorDescription::InvalidAddress, ErrorModule::OS, 19 ErrorDescription::InvalidAddress, ErrorModule::OS,
20 ErrorSummary::InvalidArgument, ErrorLevel::Usage}; 20 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
21 21
22const ResultCode ERR_INVALID_ADDRESS_STATE{ // 0xE0A01BF5 22const ResultCode ERR_INVALID_ADDRESS_STATE{// 0xE0A01BF5
23 ErrorDescription::InvalidAddress, ErrorModule::OS, 23 ErrorDescription::InvalidAddress, ErrorModule::OS,
24 ErrorSummary::InvalidState, ErrorLevel::Usage}; 24 ErrorSummary::InvalidState, ErrorLevel::Usage};
25 25
26enum class VMAType : u8 { 26enum class VMAType : u8 {
27 /// VMA represents an unmapped region of the address space. 27 /// VMA represents an unmapped region of the address space.
@@ -115,7 +115,8 @@ class VMManager final {
115 // TODO(yuriks): Make page tables switchable to support multiple VMManagers 115 // TODO(yuriks): Make page tables switchable to support multiple VMManagers
116public: 116public:
117 /** 117 /**
118 * The maximum amount of address space managed by the kernel. Addresses above this are never used. 118 * The maximum amount of address space managed by the kernel. Addresses above this are never
119 * used.
119 * @note This is the limit used by the New 3DS kernel. Old 3DS used 0x20000000. 120 * @note This is the limit used by the New 3DS kernel. Old 3DS used 0x20000000.
120 */ 121 */
121 static const u32 MAX_ADDRESS = 0x40000000; 122 static const u32 MAX_ADDRESS = 0x40000000;
@@ -151,7 +152,7 @@ public:
151 * @param state MemoryState tag to attach to the VMA. 152 * @param state MemoryState tag to attach to the VMA.
152 */ 153 */
153 ResultVal<VMAHandle> MapMemoryBlock(VAddr target, std::shared_ptr<std::vector<u8>> block, 154 ResultVal<VMAHandle> MapMemoryBlock(VAddr target, std::shared_ptr<std::vector<u8>> block,
154 size_t offset, u32 size, MemoryState state); 155 size_t offset, u32 size, MemoryState state);
155 156
156 /** 157 /**
157 * Maps an unmanaged host memory pointer at a given address. 158 * Maps an unmanaged host memory pointer at a given address.
@@ -172,7 +173,8 @@ public:
172 * @param state MemoryState tag to attach to the VMA. 173 * @param state MemoryState tag to attach to the VMA.
173 * @param mmio_handler The handler that will implement read and write for this MMIO region. 174 * @param mmio_handler The handler that will implement read and write for this MMIO region.
174 */ 175 */
175 ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state, Memory::MMIORegionPointer mmio_handler); 176 ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state,
177 Memory::MMIORegionPointer mmio_handler);
176 178
177 /// Unmaps a range of addresses, splitting VMAs as necessary. 179 /// Unmaps a range of addresses, splitting VMAs as necessary.
178 ResultCode UnmapRange(VAddr target, u32 size); 180 ResultCode UnmapRange(VAddr target, u32 size);
@@ -228,5 +230,4 @@ private:
228 /// Updates the pages corresponding to this VMA so they match the VMA's attributes. 230 /// Updates the pages corresponding to this VMA so they match the VMA's attributes.
229 void UpdatePageTableForVMA(const VirtualMemoryArea& vma); 231 void UpdatePageTableForVMA(const VirtualMemoryArea& vma);
230}; 232};
231
232} 233}
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index 268a8dad2..6e3dd9cd2 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -26,7 +26,8 @@ enum class ErrorDescription : u32 {
26 FS_InvalidOpenFlags = 230, 26 FS_InvalidOpenFlags = 230,
27 FS_NotAFile = 250, 27 FS_NotAFile = 250,
28 FS_NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive 28 FS_NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive
29 OutofRangeOrMisalignedAddress = 513, // TODO(purpasmart): Check if this name fits its actual usage 29 OutofRangeOrMisalignedAddress =
30 513, // TODO(purpasmart): Check if this name fits its actual usage
30 GPU_FirstInitialization = 519, 31 GPU_FirstInitialization = 519,
31 FS_InvalidPath = 702, 32 FS_InvalidPath = 702,
32 InvalidSection = 1000, 33 InvalidSection = 1000,
@@ -168,15 +169,15 @@ enum class ErrorSummary : u32 {
168 Success = 0, 169 Success = 0,
169 NothingHappened = 1, 170 NothingHappened = 1,
170 WouldBlock = 2, 171 WouldBlock = 2,
171 OutOfResource = 3, ///< There are no more kernel resources (memory, table slots) to 172 OutOfResource = 3, ///< There are no more kernel resources (memory, table slots) to
172 ///< execute the operation. 173 ///< execute the operation.
173 NotFound = 4, ///< A file or resource was not found. 174 NotFound = 4, ///< A file or resource was not found.
174 InvalidState = 5, 175 InvalidState = 5,
175 NotSupported = 6, ///< The operation is not supported or not implemented. 176 NotSupported = 6, ///< The operation is not supported or not implemented.
176 InvalidArgument = 7, ///< Returned when a passed argument is invalid in the current runtime 177 InvalidArgument = 7, ///< Returned when a passed argument is invalid in the current runtime
177 ///< context. (Invalid handle, out-of-bounds pointer or size, etc.) 178 ///< context. (Invalid handle, out-of-bounds pointer or size, etc.)
178 WrongArgument = 8, ///< Returned when a passed argument is in an incorrect format for use 179 WrongArgument = 8, ///< Returned when a passed argument is in an incorrect format for use
179 ///< with the function. (E.g. Invalid enum value) 180 ///< with the function. (E.g. Invalid enum value)
180 Canceled = 9, 181 Canceled = 9,
181 StatusChanged = 10, 182 StatusChanged = 10,
182 Internal = 11, 183 Internal = 11,
@@ -208,19 +209,25 @@ union ResultCode {
208 BitField<21, 6, ErrorSummary> summary; 209 BitField<21, 6, ErrorSummary> summary;
209 BitField<27, 5, ErrorLevel> level; 210 BitField<27, 5, ErrorLevel> level;
210 211
211 // The last bit of `level` is checked by apps and the kernel to determine if a result code is an error 212 // The last bit of `level` is checked by apps and the kernel to determine if a result code is an
213 // error
212 BitField<31, 1, u32> is_error; 214 BitField<31, 1, u32> is_error;
213 215
214 explicit ResultCode(u32 raw) : raw(raw) {} 216 explicit ResultCode(u32 raw) : raw(raw) {
215 ResultCode(ErrorDescription description_, ErrorModule module_, 217 }
216 ErrorSummary summary_, ErrorLevel level_) : raw(0) { 218 ResultCode(ErrorDescription description_, ErrorModule module_, ErrorSummary summary_,
219 ErrorLevel level_)
220 : raw(0) {
217 description.Assign(description_); 221 description.Assign(description_);
218 module.Assign(module_); 222 module.Assign(module_);
219 summary.Assign(summary_); 223 summary.Assign(summary_);
220 level.Assign(level_); 224 level.Assign(level_);
221 } 225 }
222 226
223 ResultCode& operator=(const ResultCode& o) { raw = o.raw; return *this; } 227 ResultCode& operator=(const ResultCode& o) {
228 raw = o.raw;
229 return *this;
230 }
224 231
225 bool IsSuccess() const { 232 bool IsSuccess() const {
226 return is_error == 0; 233 return is_error == 0;
@@ -246,8 +253,8 @@ const ResultCode RESULT_SUCCESS(0);
246 253
247/// Might be returned instead of a dummy success for unimplemented APIs. 254/// Might be returned instead of a dummy success for unimplemented APIs.
248inline ResultCode UnimplementedFunction(ErrorModule module) { 255inline ResultCode UnimplementedFunction(ErrorModule module) {
249 return ResultCode(ErrorDescription::NotImplemented, module, 256 return ResultCode(ErrorDescription::NotImplemented, module, ErrorSummary::NotSupported,
250 ErrorSummary::NotSupported, ErrorLevel::Permanent); 257 ErrorLevel::Permanent);
251} 258}
252 259
253/** 260/**
@@ -285,10 +292,9 @@ inline ResultCode UnimplementedFunction(ErrorModule module) {
285template <typename T> 292template <typename T>
286class ResultVal { 293class ResultVal {
287public: 294public:
288 /// Constructs an empty `ResultVal` with the given error code. The code must not be a success code. 295 /// Constructs an empty `ResultVal` with the given error code. The code must not be a success
289 ResultVal(ResultCode error_code = ResultCode(-1)) 296 /// code.
290 : result_code(error_code) 297 ResultVal(ResultCode error_code = ResultCode(-1)) : result_code(error_code) {
291 {
292 ASSERT(error_code.IsError()); 298 ASSERT(error_code.IsError());
293 } 299 }
294 300
@@ -303,17 +309,13 @@ public:
303 return result; 309 return result;
304 } 310 }
305 311
306 ResultVal(const ResultVal& o) 312 ResultVal(const ResultVal& o) : result_code(o.result_code) {
307 : result_code(o.result_code)
308 {
309 if (!o.empty()) { 313 if (!o.empty()) {
310 new (&object) T(o.object); 314 new (&object) T(o.object);
311 } 315 }
312 } 316 }
313 317
314 ResultVal(ResultVal&& o) 318 ResultVal(ResultVal&& o) : result_code(o.result_code) {
315 : result_code(o.result_code)
316 {
317 if (!o.empty()) { 319 if (!o.empty()) {
318 new (&object) T(std::move(o.object)); 320 new (&object) T(std::move(o.object));
319 } 321 }
@@ -357,19 +359,35 @@ public:
357 } 359 }
358 360
359 /// Returns true if the `ResultVal` contains an error code and no value. 361 /// Returns true if the `ResultVal` contains an error code and no value.
360 bool empty() const { return result_code.IsError(); } 362 bool empty() const {
363 return result_code.IsError();
364 }
361 365
362 /// Returns true if the `ResultVal` contains a return value. 366 /// Returns true if the `ResultVal` contains a return value.
363 bool Succeeded() const { return result_code.IsSuccess(); } 367 bool Succeeded() const {
368 return result_code.IsSuccess();
369 }
364 /// Returns true if the `ResultVal` contains an error code and no value. 370 /// Returns true if the `ResultVal` contains an error code and no value.
365 bool Failed() const { return empty(); } 371 bool Failed() const {
372 return empty();
373 }
366 374
367 ResultCode Code() const { return result_code; } 375 ResultCode Code() const {
376 return result_code;
377 }
368 378
369 const T& operator* () const { return object; } 379 const T& operator*() const {
370 T& operator* () { return object; } 380 return object;
371 const T* operator->() const { return &object; } 381 }
372 T* operator->() { return &object; } 382 T& operator*() {
383 return object;
384 }
385 const T* operator->() const {
386 return &object;
387 }
388 T* operator->() {
389 return &object;
390 }
373 391
374 /// Returns the value contained in this `ResultVal`, or the supplied default if it is missing. 392 /// Returns the value contained in this `ResultVal`, or the supplied default if it is missing.
375 template <typename U> 393 template <typename U>
@@ -390,7 +408,9 @@ public:
390private: 408private:
391 // A union is used to allocate the storage for the value, while allowing us to construct and 409 // A union is used to allocate the storage for the value, while allowing us to construct and
392 // destruct it at will. 410 // destruct it at will.
393 union { T object; }; 411 union {
412 T object;
413 };
394 ResultCode result_code; 414 ResultCode result_code;
395}; 415};
396 416
@@ -409,8 +429,8 @@ ResultVal<T> MakeResult(Args&&... args) {
409 * variable declaration. If it fails the return code is returned from the current function. Thus it 429 * variable declaration. If it fails the return code is returned from the current function. Thus it
410 * can be used to cascade errors out, achieving something akin to exception handling. 430 * can be used to cascade errors out, achieving something akin to exception handling.
411 */ 431 */
412#define CASCADE_RESULT(target, source) \ 432#define CASCADE_RESULT(target, source) \
413 auto CONCAT2(check_result_L, __LINE__) = source; \ 433 auto CONCAT2(check_result_L, __LINE__) = source; \
414 if (CONCAT2(check_result_L, __LINE__).Failed()) \ 434 if (CONCAT2(check_result_L, __LINE__).Failed()) \
415 return CONCAT2(check_result_L, __LINE__).Code(); \ 435 return CONCAT2(check_result_L, __LINE__).Code(); \
416 target = std::move(*CONCAT2(check_result_L, __LINE__)) 436 target = std::move(*CONCAT2(check_result_L, __LINE__))
diff --git a/src/core/hle/service/ac_u.cpp b/src/core/hle/service/ac_u.cpp
index 5241dd3e7..887b57529 100644
--- a/src/core/hle/service/ac_u.cpp
+++ b/src/core/hle/service/ac_u.cpp
@@ -47,7 +47,7 @@ static void GetWifiStatus(Service::Interface* self) {
47 // it returns a valid result without implementing full functionality. 47 // it returns a valid result without implementing full functionality.
48 48
49 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 49 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
50 cmd_buff[2] = 0; // Connection type set to none 50 cmd_buff[2] = 0; // Connection type set to none
51 51
52 LOG_WARNING(Service_AC, "(STUBBED) called"); 52 LOG_WARNING(Service_AC, "(STUBBED) called");
53} 53}
@@ -62,29 +62,29 @@ static void IsConnected(Service::Interface* self) {
62 u32* cmd_buff = Kernel::GetCommandBuffer(); 62 u32* cmd_buff = Kernel::GetCommandBuffer();
63 63
64 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 64 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
65 cmd_buff[2] = false; // Not connected to ac:u service 65 cmd_buff[2] = false; // Not connected to ac:u service
66 66
67 LOG_WARNING(Service_AC, "(STUBBED) called"); 67 LOG_WARNING(Service_AC, "(STUBBED) called");
68} 68}
69 69
70const Interface::FunctionInfo FunctionTable[] = { 70const Interface::FunctionInfo FunctionTable[] = {
71 {0x00010000, nullptr, "CreateDefaultConfig"}, 71 {0x00010000, nullptr, "CreateDefaultConfig"},
72 {0x00040006, nullptr, "ConnectAsync"}, 72 {0x00040006, nullptr, "ConnectAsync"},
73 {0x00050002, nullptr, "GetConnectResult"}, 73 {0x00050002, nullptr, "GetConnectResult"},
74 {0x00080004, CloseAsync, "CloseAsync"}, 74 {0x00080004, CloseAsync, "CloseAsync"},
75 {0x00090002, nullptr, "GetCloseResult"}, 75 {0x00090002, nullptr, "GetCloseResult"},
76 {0x000A0000, nullptr, "GetLastErrorCode"}, 76 {0x000A0000, nullptr, "GetLastErrorCode"},
77 {0x000D0000, GetWifiStatus, "GetWifiStatus"}, 77 {0x000D0000, GetWifiStatus, "GetWifiStatus"},
78 {0x000E0042, nullptr, "GetCurrentAPInfo"}, 78 {0x000E0042, nullptr, "GetCurrentAPInfo"},
79 {0x00100042, nullptr, "GetCurrentNZoneInfo"}, 79 {0x00100042, nullptr, "GetCurrentNZoneInfo"},
80 {0x00110042, nullptr, "GetNZoneApNumService"}, 80 {0x00110042, nullptr, "GetNZoneApNumService"},
81 {0x00240042, nullptr, "AddDenyApType"}, 81 {0x00240042, nullptr, "AddDenyApType"},
82 {0x00270002, nullptr, "GetInfraPriority"}, 82 {0x00270002, nullptr, "GetInfraPriority"},
83 {0x002D0082, nullptr, "SetRequestEulaVersion"}, 83 {0x002D0082, nullptr, "SetRequestEulaVersion"},
84 {0x00300004, nullptr, "RegisterDisconnectEvent"}, 84 {0x00300004, nullptr, "RegisterDisconnectEvent"},
85 {0x003C0042, nullptr, "GetAPSSIDList"}, 85 {0x003C0042, nullptr, "GetAPSSIDList"},
86 {0x003E0042, IsConnected, "IsConnected"}, 86 {0x003E0042, IsConnected, "IsConnected"},
87 {0x00400042, nullptr, "SetClientVersion"}, 87 {0x00400042, nullptr, "SetClientVersion"},
88}; 88};
89 89
90//////////////////////////////////////////////////////////////////////////////////////////////////// 90////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 3f71e7f2b..b653523a4 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -6,19 +6,19 @@
6 6
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8 8
9#include "core/hle/service/service.h"
10#include "core/hle/service/am/am.h" 9#include "core/hle/service/am/am.h"
11#include "core/hle/service/am/am_app.h" 10#include "core/hle/service/am/am_app.h"
12#include "core/hle/service/am/am_net.h" 11#include "core/hle/service/am/am_net.h"
13#include "core/hle/service/am/am_sys.h" 12#include "core/hle/service/am/am_sys.h"
14#include "core/hle/service/am/am_u.h" 13#include "core/hle/service/am/am_u.h"
14#include "core/hle/service/service.h"
15 15
16namespace Service { 16namespace Service {
17namespace AM { 17namespace AM {
18 18
19static std::array<u32, 3> am_content_count = { 0, 0, 0 }; 19static std::array<u32, 3> am_content_count = {0, 0, 0};
20static std::array<u32, 3> am_titles_count = { 0, 0, 0 }; 20static std::array<u32, 3> am_titles_count = {0, 0, 0};
21static std::array<u32, 3> am_titles_list_count = { 0, 0, 0 }; 21static std::array<u32, 3> am_titles_list_count = {0, 0, 0};
22static u32 am_ticket_count = 0; 22static u32 am_ticket_count = 0;
23static u32 am_ticket_list_count = 0; 23static u32 am_ticket_list_count = 0;
24 24
@@ -29,7 +29,8 @@ void GetTitleCount(Service::Interface* self) {
29 29
30 cmd_buff[1] = RESULT_SUCCESS.raw; 30 cmd_buff[1] = RESULT_SUCCESS.raw;
31 cmd_buff[2] = am_titles_count[media_type]; 31 cmd_buff[2] = am_titles_count[media_type];
32 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_count=0x%08x", media_type, am_titles_count[media_type]); 32 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_count=0x%08x", media_type,
33 am_titles_count[media_type]);
33} 34}
34 35
35void FindContentInfos(Service::Interface* self) { 36void FindContentInfos(Service::Interface* self) {
@@ -43,8 +44,10 @@ void FindContentInfos(Service::Interface* self) {
43 am_content_count[media_type] = cmd_buff[4]; 44 am_content_count[media_type] = cmd_buff[4];
44 45
45 cmd_buff[1] = RESULT_SUCCESS.raw; 46 cmd_buff[1] = RESULT_SUCCESS.raw;
46 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_id=0x%016llx, content_cound=%u, content_ids_pointer=0x%08x, content_info_pointer=0x%08x", 47 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_id=0x%016llx, content_cound=%u, "
47 media_type, title_id, am_content_count[media_type], content_ids_pointer, content_info_pointer); 48 "content_ids_pointer=0x%08x, content_info_pointer=0x%08x",
49 media_type, title_id, am_content_count[media_type], content_ids_pointer,
50 content_info_pointer);
48} 51}
49 52
50void ListContentInfos(Service::Interface* self) { 53void ListContentInfos(Service::Interface* self) {
@@ -59,8 +62,10 @@ void ListContentInfos(Service::Interface* self) {
59 62
60 cmd_buff[1] = RESULT_SUCCESS.raw; 63 cmd_buff[1] = RESULT_SUCCESS.raw;
61 cmd_buff[2] = am_content_count[media_type]; 64 cmd_buff[2] = am_content_count[media_type];
62 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, content_count=%u, title_id=0x%016" PRIx64 ", start_index=0x%08x, content_info_pointer=0x%08X", 65 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, content_count=%u, title_id=0x%016" PRIx64
63 media_type, am_content_count[media_type], title_id, start_index, content_info_pointer); 66 ", start_index=0x%08x, content_info_pointer=0x%08X",
67 media_type, am_content_count[media_type], title_id, start_index,
68 content_info_pointer);
64} 69}
65 70
66void DeleteContents(Service::Interface* self) { 71void DeleteContents(Service::Interface* self) {
@@ -73,8 +78,9 @@ void DeleteContents(Service::Interface* self) {
73 am_content_count[media_type] = cmd_buff[4]; 78 am_content_count[media_type] = cmd_buff[4];
74 79
75 cmd_buff[1] = RESULT_SUCCESS.raw; 80 cmd_buff[1] = RESULT_SUCCESS.raw;
76 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_id=0x%016" PRIx64 ", content_count=%u, content_ids_pointer=0x%08x", 81 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_id=0x%016" PRIx64
77 media_type, title_id, am_content_count[media_type], content_ids_pointer); 82 ", content_count=%u, content_ids_pointer=0x%08x",
83 media_type, title_id, am_content_count[media_type], content_ids_pointer);
78} 84}
79 85
80void GetTitleList(Service::Interface* self) { 86void GetTitleList(Service::Interface* self) {
@@ -87,8 +93,10 @@ void GetTitleList(Service::Interface* self) {
87 93
88 cmd_buff[1] = RESULT_SUCCESS.raw; 94 cmd_buff[1] = RESULT_SUCCESS.raw;
89 cmd_buff[2] = am_titles_list_count[media_type]; 95 cmd_buff[2] = am_titles_list_count[media_type];
90 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, titles_list_count=0x%08X, title_ids_output_pointer=0x%08X", 96 LOG_WARNING(
91 media_type, am_titles_list_count[media_type], title_ids_output_pointer); 97 Service_AM,
98 "(STUBBED) media_type=%u, titles_list_count=0x%08X, title_ids_output_pointer=0x%08X",
99 media_type, am_titles_list_count[media_type], title_ids_output_pointer);
92} 100}
93 101
94void GetTitleInfo(Service::Interface* self) { 102void GetTitleInfo(Service::Interface* self) {
@@ -101,7 +109,8 @@ void GetTitleInfo(Service::Interface* self) {
101 am_titles_count[media_type] = cmd_buff[2]; 109 am_titles_count[media_type] = cmd_buff[2];
102 110
103 cmd_buff[1] = RESULT_SUCCESS.raw; 111 cmd_buff[1] = RESULT_SUCCESS.raw;
104 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, total_titles=0x%08X, title_id_list_pointer=0x%08X, title_list_pointer=0x%08X", 112 LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, total_titles=0x%08X, "
113 "title_id_list_pointer=0x%08X, title_list_pointer=0x%08X",
105 media_type, am_titles_count[media_type], title_id_list_pointer, title_list_pointer); 114 media_type, am_titles_count[media_type], title_id_list_pointer, title_list_pointer);
106} 115}
107 116
@@ -122,8 +131,9 @@ void ListDataTitleTicketInfos(Service::Interface* self) {
122 131
123 cmd_buff[1] = RESULT_SUCCESS.raw; 132 cmd_buff[1] = RESULT_SUCCESS.raw;
124 cmd_buff[2] = am_ticket_count; 133 cmd_buff[2] = am_ticket_count;
125 LOG_WARNING(Service_AM, "(STUBBED) ticket_count=0x%08X, title_id=0x%016" PRIx64 ", start_index=0x%08X, ticket_info_pointer=0x%08X", 134 LOG_WARNING(Service_AM, "(STUBBED) ticket_count=0x%08X, title_id=0x%016" PRIx64
126 am_ticket_count, title_id, start_index, ticket_info_pointer); 135 ", start_index=0x%08X, ticket_info_pointer=0x%08X",
136 am_ticket_count, title_id, start_index, ticket_info_pointer);
127} 137}
128 138
129void GetNumContentInfos(Service::Interface* self) { 139void GetNumContentInfos(Service::Interface* self) {
@@ -140,7 +150,7 @@ void DeleteTicket(Service::Interface* self) {
140 u64 title_id = (static_cast<u64>(cmd_buff[2]) << 32) | cmd_buff[1]; 150 u64 title_id = (static_cast<u64>(cmd_buff[2]) << 32) | cmd_buff[1];
141 151
142 cmd_buff[1] = RESULT_SUCCESS.raw; 152 cmd_buff[1] = RESULT_SUCCESS.raw;
143 LOG_WARNING(Service_AM, "(STUBBED) called title_id=0x%016" PRIx64 "",title_id); 153 LOG_WARNING(Service_AM, "(STUBBED) called title_id=0x%016" PRIx64 "", title_id);
144} 154}
145 155
146void GetTicketCount(Service::Interface* self) { 156void GetTicketCount(Service::Interface* self) {
@@ -148,7 +158,7 @@ void GetTicketCount(Service::Interface* self) {
148 158
149 cmd_buff[1] = RESULT_SUCCESS.raw; 159 cmd_buff[1] = RESULT_SUCCESS.raw;
150 cmd_buff[2] = am_ticket_count; 160 cmd_buff[2] = am_ticket_count;
151 LOG_WARNING(Service_AM, "(STUBBED) called ticket_count=0x%08x",am_ticket_count); 161 LOG_WARNING(Service_AM, "(STUBBED) called ticket_count=0x%08x", am_ticket_count);
152} 162}
153 163
154void GetTicketList(Service::Interface* self) { 164void GetTicketList(Service::Interface* self) {
@@ -161,8 +171,10 @@ void GetTicketList(Service::Interface* self) {
161 171
162 cmd_buff[1] = RESULT_SUCCESS.raw; 172 cmd_buff[1] = RESULT_SUCCESS.raw;
163 cmd_buff[2] = am_ticket_list_count; 173 cmd_buff[2] = am_ticket_list_count;
164 LOG_WARNING(Service_AM, "(STUBBED) ticket_list_count=0x%08x, num_of_skip=0x%08x, ticket_list_pointer=0x%08x", 174 LOG_WARNING(
165 am_ticket_list_count, num_of_skip, ticket_list_pointer); 175 Service_AM,
176 "(STUBBED) ticket_list_count=0x%08x, num_of_skip=0x%08x, ticket_list_pointer=0x%08x",
177 am_ticket_list_count, num_of_skip, ticket_list_pointer);
166} 178}
167 179
168void Init() { 180void Init() {
@@ -175,7 +187,6 @@ void Init() {
175} 187}
176 188
177void Shutdown() { 189void Shutdown() {
178
179} 190}
180 191
181} // namespace AM 192} // namespace AM
diff --git a/src/core/hle/service/am/am_app.cpp b/src/core/hle/service/am/am_app.cpp
index d27b3defd..bfc1ca6bd 100644
--- a/src/core/hle/service/am/am_app.cpp
+++ b/src/core/hle/service/am/am_app.cpp
@@ -9,14 +9,14 @@ namespace Service {
9namespace AM { 9namespace AM {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x100100C0, GetNumContentInfos, "GetNumContentInfos"}, 12 {0x100100C0, GetNumContentInfos, "GetNumContentInfos"},
13 {0x10020104, FindContentInfos, "FindContentInfos"}, 13 {0x10020104, FindContentInfos, "FindContentInfos"},
14 {0x10030142, ListContentInfos, "ListContentInfos"}, 14 {0x10030142, ListContentInfos, "ListContentInfos"},
15 {0x10040102, DeleteContents, "DeleteContents"}, 15 {0x10040102, DeleteContents, "DeleteContents"},
16 {0x10050084, GetDataTitleInfos, "GetDataTitleInfos"}, 16 {0x10050084, GetDataTitleInfos, "GetDataTitleInfos"},
17 {0x10070102, ListDataTitleTicketInfos, "ListDataTitleTicketInfos"}, 17 {0x10070102, ListDataTitleTicketInfos, "ListDataTitleTicketInfos"},
18 {0x100900C0, nullptr, "IsDataTitleInUse"}, 18 {0x100900C0, nullptr, "IsDataTitleInUse"},
19 {0x100A0000, nullptr, "IsExternalTitleDatabaseInitialized"}, 19 {0x100A0000, nullptr, "IsExternalTitleDatabaseInitialized"},
20}; 20};
21 21
22AM_APP_Interface::AM_APP_Interface() { 22AM_APP_Interface::AM_APP_Interface() {
diff --git a/src/core/hle/service/am/am_net.cpp b/src/core/hle/service/am/am_net.cpp
index e75755245..3a597a34c 100644
--- a/src/core/hle/service/am/am_net.cpp
+++ b/src/core/hle/service/am/am_net.cpp
@@ -9,61 +9,61 @@ namespace Service {
9namespace AM { 9namespace AM {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010040, GetTitleCount, "GetTitleCount"}, 12 {0x00010040, GetTitleCount, "GetTitleCount"},
13 {0x00020082, GetTitleList, "GetTitleList"}, 13 {0x00020082, GetTitleList, "GetTitleList"},
14 {0x00030084, GetTitleInfo, "GetTitleInfo"}, 14 {0x00030084, GetTitleInfo, "GetTitleInfo"},
15 {0x000400C0, nullptr, "DeleteApplicationTitle"}, 15 {0x000400C0, nullptr, "DeleteApplicationTitle"},
16 {0x000500C0, nullptr, "GetTitleProductCode"}, 16 {0x000500C0, nullptr, "GetTitleProductCode"},
17 {0x000600C0, nullptr, "GetTitleExtDataId"}, 17 {0x000600C0, nullptr, "GetTitleExtDataId"},
18 {0x00070080, DeleteTicket, "DeleteTicket"}, 18 {0x00070080, DeleteTicket, "DeleteTicket"},
19 {0x00080000, GetTicketCount, "GetTicketCount"}, 19 {0x00080000, GetTicketCount, "GetTicketCount"},
20 {0x00090082, GetTicketList, "GetTicketList"}, 20 {0x00090082, GetTicketList, "GetTicketList"},
21 {0x000A0000, nullptr, "GetDeviceID"}, 21 {0x000A0000, nullptr, "GetDeviceID"},
22 {0x000D0084, nullptr, "GetPendingTitleInfo"}, 22 {0x000D0084, nullptr, "GetPendingTitleInfo"},
23 {0x000E00C0, nullptr, "DeletePendingTitle"}, 23 {0x000E00C0, nullptr, "DeletePendingTitle"},
24 {0x00140040, nullptr, "FinalizePendingTitles"}, 24 {0x00140040, nullptr, "FinalizePendingTitles"},
25 {0x00150040, nullptr, "DeleteAllPendingTitles"}, 25 {0x00150040, nullptr, "DeleteAllPendingTitles"},
26 {0x00180080, nullptr, "InitializeTitleDatabase"}, 26 {0x00180080, nullptr, "InitializeTitleDatabase"},
27 {0x00190040, nullptr, "ReloadDBS"}, 27 {0x00190040, nullptr, "ReloadDBS"},
28 {0x001A00C0, nullptr, "GetDSiWareExportSize"}, 28 {0x001A00C0, nullptr, "GetDSiWareExportSize"},
29 {0x001B0144, nullptr, "ExportDSiWare"}, 29 {0x001B0144, nullptr, "ExportDSiWare"},
30 {0x001C0084, nullptr, "ImportDSiWare"}, 30 {0x001C0084, nullptr, "ImportDSiWare"},
31 {0x00230080, nullptr, "TitleIDListGetTotal2"}, 31 {0x00230080, nullptr, "TitleIDListGetTotal2"},
32 {0x002400C2, nullptr, "GetTitleIDList2"}, 32 {0x002400C2, nullptr, "GetTitleIDList2"},
33 {0x04010080, nullptr, "InstallFIRM"}, 33 {0x04010080, nullptr, "InstallFIRM"},
34 {0x04020040, nullptr, "StartInstallCIADB0"}, 34 {0x04020040, nullptr, "StartInstallCIADB0"},
35 {0x04030000, nullptr, "StartInstallCIADB1"}, 35 {0x04030000, nullptr, "StartInstallCIADB1"},
36 {0x04040002, nullptr, "AbortCIAInstall"}, 36 {0x04040002, nullptr, "AbortCIAInstall"},
37 {0x04050002, nullptr, "CloseCIAFinalizeInstall"}, 37 {0x04050002, nullptr, "CloseCIAFinalizeInstall"},
38 {0x04060002, nullptr, "CloseCIA"}, 38 {0x04060002, nullptr, "CloseCIA"},
39 {0x040700C2, nullptr, "FinalizeTitlesInstall"}, 39 {0x040700C2, nullptr, "FinalizeTitlesInstall"},
40 {0x04080042, nullptr, "GetCiaFileInfo"}, 40 {0x04080042, nullptr, "GetCiaFileInfo"},
41 {0x040E00C2, nullptr, "InstallTitlesFinish"}, 41 {0x040E00C2, nullptr, "InstallTitlesFinish"},
42 {0x040F0000, nullptr, "InstallNATIVEFIRM"}, 42 {0x040F0000, nullptr, "InstallNATIVEFIRM"},
43 {0x041000C0, nullptr, "DeleteTitle"}, 43 {0x041000C0, nullptr, "DeleteTitle"},
44 {0x04120000, nullptr, "Initialize"}, 44 {0x04120000, nullptr, "Initialize"},
45 {0x041700C0, nullptr, "MigrateAGBtoSAV"}, 45 {0x041700C0, nullptr, "MigrateAGBtoSAV"},
46 {0x08010000, nullptr, "OpenTicket"}, 46 {0x08010000, nullptr, "OpenTicket"},
47 {0x08020002, nullptr, "TicketAbortInstall"}, 47 {0x08020002, nullptr, "TicketAbortInstall"},
48 {0x08030002, nullptr, "TicketFinalizeInstall"}, 48 {0x08030002, nullptr, "TicketFinalizeInstall"},
49 {0x08040100, nullptr, "InstallTitleBegin"}, 49 {0x08040100, nullptr, "InstallTitleBegin"},
50 {0x08050000, nullptr, "InstallTitleAbort"}, 50 {0x08050000, nullptr, "InstallTitleAbort"},
51 {0x080600C0, nullptr, "InstallTitleResume"}, 51 {0x080600C0, nullptr, "InstallTitleResume"},
52 {0x08070000, nullptr, "InstallTitleAbortTMD"}, 52 {0x08070000, nullptr, "InstallTitleAbortTMD"},
53 {0x08080000, nullptr, "InstallTitleFinish"}, 53 {0x08080000, nullptr, "InstallTitleFinish"},
54 {0x080A0000, nullptr, "OpenTMD"}, 54 {0x080A0000, nullptr, "OpenTMD"},
55 {0x080B0002, nullptr, "TMDAbortInstall"}, 55 {0x080B0002, nullptr, "TMDAbortInstall"},
56 {0x080C0042, nullptr, "TMDFinalizeInstall"}, 56 {0x080C0042, nullptr, "TMDFinalizeInstall"},
57 {0x080E0040, nullptr, "OpenContentCreate"}, 57 {0x080E0040, nullptr, "OpenContentCreate"},
58 {0x080F0002, nullptr, "ContentAbortInstall"}, 58 {0x080F0002, nullptr, "ContentAbortInstall"},
59 {0x08100040, nullptr, "OpenContentResume"}, 59 {0x08100040, nullptr, "OpenContentResume"},
60 {0x08120002, nullptr, "ContentFinalizeInstall"}, 60 {0x08120002, nullptr, "ContentFinalizeInstall"},
61 {0x08130000, nullptr, "GetTotalContents"}, 61 {0x08130000, nullptr, "GetTotalContents"},
62 {0x08140042, nullptr, "GetContentIndexes"}, 62 {0x08140042, nullptr, "GetContentIndexes"},
63 {0x08150044, nullptr, "GetContentsInfo"}, 63 {0x08150044, nullptr, "GetContentsInfo"},
64 {0x08180042, nullptr, "GetCTCert"}, 64 {0x08180042, nullptr, "GetCTCert"},
65 {0x08190108, nullptr, "SetCertificates"}, 65 {0x08190108, nullptr, "SetCertificates"},
66 {0x081B00C2, nullptr, "InstallTitlesFinish"}, 66 {0x081B00C2, nullptr, "InstallTitlesFinish"},
67}; 67};
68 68
69AM_NET_Interface::AM_NET_Interface() { 69AM_NET_Interface::AM_NET_Interface() {
diff --git a/src/core/hle/service/am/am_sys.cpp b/src/core/hle/service/am/am_sys.cpp
index 8bad5e1c9..8bb58cab7 100644
--- a/src/core/hle/service/am/am_sys.cpp
+++ b/src/core/hle/service/am/am_sys.cpp
@@ -8,29 +8,27 @@
8namespace Service { 8namespace Service {
9namespace AM { 9namespace AM {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {{0x00010040, GetTitleCount, "GetTitleCount"},
12 {0x00010040, GetTitleCount, "GetTitleCount"}, 12 {0x00020082, GetTitleList, "GetTitleList"},
13 {0x00020082, GetTitleList, "GetTitleList"}, 13 {0x00030084, GetTitleInfo, "GetTitleInfo"},
14 {0x00030084, GetTitleInfo, "GetTitleInfo"}, 14 {0x000400C0, nullptr, "DeleteApplicationTitle"},
15 {0x000400C0, nullptr, "DeleteApplicationTitle"}, 15 {0x000500C0, nullptr, "GetTitleProductCode"},
16 {0x000500C0, nullptr, "GetTitleProductCode"}, 16 {0x000600C0, nullptr, "GetTitleExtDataId"},
17 {0x000600C0, nullptr, "GetTitleExtDataId"}, 17 {0x00070080, DeleteTicket, "DeleteTicket"},
18 {0x00070080, DeleteTicket, "DeleteTicket"}, 18 {0x00080000, GetTicketCount, "GetTicketCount"},
19 {0x00080000, GetTicketCount, "GetTicketCount"}, 19 {0x00090082, GetTicketList, "GetTicketList"},
20 {0x00090082, GetTicketList, "GetTicketList"}, 20 {0x000A0000, nullptr, "GetDeviceID"},
21 {0x000A0000, nullptr, "GetDeviceID"}, 21 {0x000D0084, nullptr, "GetPendingTitleInfo"},
22 {0x000D0084, nullptr, "GetPendingTitleInfo"}, 22 {0x000E00C0, nullptr, "DeletePendingTitle"},
23 {0x000E00C0, nullptr, "DeletePendingTitle"}, 23 {0x00140040, nullptr, "FinalizePendingTitles"},
24 {0x00140040, nullptr, "FinalizePendingTitles"}, 24 {0x00150040, nullptr, "DeleteAllPendingTitles"},
25 {0x00150040, nullptr, "DeleteAllPendingTitles"}, 25 {0x00180080, nullptr, "InitializeTitleDatabase"},
26 {0x00180080, nullptr, "InitializeTitleDatabase"}, 26 {0x00190040, nullptr, "ReloadDBS"},
27 {0x00190040, nullptr, "ReloadDBS"}, 27 {0x001A00C0, nullptr, "GetDSiWareExportSize"},
28 {0x001A00C0, nullptr, "GetDSiWareExportSize"}, 28 {0x001B0144, nullptr, "ExportDSiWare"},
29 {0x001B0144, nullptr, "ExportDSiWare"}, 29 {0x001C0084, nullptr, "ImportDSiWare"},
30 {0x001C0084, nullptr, "ImportDSiWare"}, 30 {0x00230080, nullptr, "GetPendingTitleCount"},
31 {0x00230080, nullptr, "GetPendingTitleCount"}, 31 {0x002400C2, nullptr, "GetPendingTitleList"}};
32 {0x002400C2, nullptr, "GetPendingTitleList"}
33};
34 32
35AM_SYS_Interface::AM_SYS_Interface() { 33AM_SYS_Interface::AM_SYS_Interface() {
36 Register(FunctionTable); 34 Register(FunctionTable);
diff --git a/src/core/hle/service/am/am_u.cpp b/src/core/hle/service/am/am_u.cpp
index d583dd9e6..32d47741f 100644
--- a/src/core/hle/service/am/am_u.cpp
+++ b/src/core/hle/service/am/am_u.cpp
@@ -8,42 +8,40 @@
8namespace Service { 8namespace Service {
9namespace AM { 9namespace AM {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {{0x00010040, GetTitleCount, "GetTitleCount"},
12 {0x00010040, GetTitleCount, "GetTitleCount"}, 12 {0x00020082, GetTitleList, "GetTitleList"},
13 {0x00020082, GetTitleList, "GetTitleList"}, 13 {0x00030084, GetTitleInfo, "GetTitleInfo"},
14 {0x00030084, GetTitleInfo, "GetTitleInfo"}, 14 {0x000400C0, nullptr, "DeleteApplicationTitle"},
15 {0x000400C0, nullptr, "DeleteApplicationTitle"}, 15 {0x000500C0, nullptr, "GetTitleProductCode"},
16 {0x000500C0, nullptr, "GetTitleProductCode"}, 16 {0x000600C0, nullptr, "GetTitleExtDataId"},
17 {0x000600C0, nullptr, "GetTitleExtDataId"}, 17 {0x00070080, DeleteTicket, "DeleteTicket"},
18 {0x00070080, DeleteTicket, "DeleteTicket"}, 18 {0x00080000, GetTicketCount, "GetTicketCount"},
19 {0x00080000, GetTicketCount, "GetTicketCount"}, 19 {0x00090082, GetTicketList, "GetTicketList"},
20 {0x00090082, GetTicketList, "GetTicketList"}, 20 {0x000A0000, nullptr, "GetDeviceID"},
21 {0x000A0000, nullptr, "GetDeviceID"}, 21 {0x000D0084, nullptr, "GetPendingTitleInfo"},
22 {0x000D0084, nullptr, "GetPendingTitleInfo"}, 22 {0x000E00C0, nullptr, "DeletePendingTitle"},
23 {0x000E00C0, nullptr, "DeletePendingTitle"}, 23 {0x00140040, nullptr, "FinalizePendingTitles"},
24 {0x00140040, nullptr, "FinalizePendingTitles"}, 24 {0x00150040, nullptr, "DeleteAllPendingTitles"},
25 {0x00150040, nullptr, "DeleteAllPendingTitles"}, 25 {0x00180080, nullptr, "InitializeTitleDatabase"},
26 {0x00180080, nullptr, "InitializeTitleDatabase"}, 26 {0x00190040, nullptr, "ReloadDBS"},
27 {0x00190040, nullptr, "ReloadDBS"}, 27 {0x001A00C0, nullptr, "GetDSiWareExportSize"},
28 {0x001A00C0, nullptr, "GetDSiWareExportSize"}, 28 {0x001B0144, nullptr, "ExportDSiWare"},
29 {0x001B0144, nullptr, "ExportDSiWare"}, 29 {0x001C0084, nullptr, "ImportDSiWare"},
30 {0x001C0084, nullptr, "ImportDSiWare"}, 30 {0x00230080, nullptr, "TitleIDListGetTotal2"},
31 {0x00230080, nullptr, "TitleIDListGetTotal2"}, 31 {0x002400C2, nullptr, "GetTitleIDList2"},
32 {0x002400C2, nullptr, "GetTitleIDList2"}, 32 {0x04010080, nullptr, "InstallFIRM"},
33 {0x04010080, nullptr, "InstallFIRM"}, 33 {0x04020040, nullptr, "StartInstallCIADB0"},
34 {0x04020040, nullptr, "StartInstallCIADB0"}, 34 {0x04030000, nullptr, "StartInstallCIADB1"},
35 {0x04030000, nullptr, "StartInstallCIADB1"}, 35 {0x04040002, nullptr, "AbortCIAInstall"},
36 {0x04040002, nullptr, "AbortCIAInstall"}, 36 {0x04050002, nullptr, "CloseCIAFinalizeInstall"},
37 {0x04050002, nullptr, "CloseCIAFinalizeInstall"}, 37 {0x04060002, nullptr, "CloseCIA"},
38 {0x04060002, nullptr, "CloseCIA"}, 38 {0x040700C2, nullptr, "FinalizeTitlesInstall"},
39 {0x040700C2, nullptr, "FinalizeTitlesInstall"}, 39 {0x04080042, nullptr, "GetCiaFileInfo"},
40 {0x04080042, nullptr, "GetCiaFileInfo"}, 40 {0x040E00C2, nullptr, "InstallTitlesFinish"},
41 {0x040E00C2, nullptr, "InstallTitlesFinish"}, 41 {0x040F0000, nullptr, "InstallNATIVEFIRM"},
42 {0x040F0000, nullptr, "InstallNATIVEFIRM"}, 42 {0x041000C0, nullptr, "DeleteTitle"},
43 {0x041000C0, nullptr, "DeleteTitle"}, 43 {0x04120000, nullptr, "Initialize"},
44 {0x04120000, nullptr, "Initialize"}, 44 {0x041700C0, nullptr, "MigrateAGBtoSAV"}};
45 {0x041700C0, nullptr, "MigrateAGBtoSAV"}
46};
47 45
48AM_U_Interface::AM_U_Interface() { 46AM_U_Interface::AM_U_Interface() {
49 Register(FunctionTable); 47 Register(FunctionTable);
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index 4d2956638..c798e8752 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -7,7 +7,6 @@
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8 8
9#include "core/hle/applets/applet.h" 9#include "core/hle/applets/applet.h"
10#include "core/hle/service/service.h"
11#include "core/hle/service/apt/apt.h" 10#include "core/hle/service/apt/apt.h"
12#include "core/hle/service/apt/apt_a.h" 11#include "core/hle/service/apt/apt_a.h"
13#include "core/hle/service/apt/apt_s.h" 12#include "core/hle/service/apt/apt_s.h"
@@ -15,6 +14,7 @@
15#include "core/hle/service/apt/bcfnt/bcfnt.h" 14#include "core/hle/service/apt/bcfnt/bcfnt.h"
16#include "core/hle/service/fs/archive.h" 15#include "core/hle/service/fs/archive.h"
17#include "core/hle/service/ptm/ptm.h" 16#include "core/hle/service/ptm/ptm.h"
17#include "core/hle/service/service.h"
18 18
19#include "core/hle/kernel/event.h" 19#include "core/hle/kernel/event.h"
20#include "core/hle/kernel/mutex.h" 20#include "core/hle/kernel/mutex.h"
@@ -30,7 +30,7 @@ static bool shared_font_relocated = false;
30 30
31static Kernel::SharedPtr<Kernel::Mutex> lock; 31static Kernel::SharedPtr<Kernel::Mutex> lock;
32static Kernel::SharedPtr<Kernel::Event> notification_event; ///< APT notification event 32static Kernel::SharedPtr<Kernel::Event> notification_event; ///< APT notification event
33static Kernel::SharedPtr<Kernel::Event> parameter_event; ///< APT parameter event 33static Kernel::SharedPtr<Kernel::Event> parameter_event; ///< APT parameter event
34 34
35static u32 cpu_percent; ///< CPU time available to the running application 35static u32 cpu_percent; ///< CPU time available to the running application
36 36
@@ -51,7 +51,7 @@ void SendParameter(const MessageParameter& parameter) {
51void Initialize(Service::Interface* self) { 51void Initialize(Service::Interface* self) {
52 u32* cmd_buff = Kernel::GetCommandBuffer(); 52 u32* cmd_buff = Kernel::GetCommandBuffer();
53 u32 app_id = cmd_buff[1]; 53 u32 app_id = cmd_buff[1];
54 u32 flags = cmd_buff[2]; 54 u32 flags = cmd_buff[2];
55 55
56 cmd_buff[2] = IPC::CopyHandleDesc(2); 56 cmd_buff[2] = IPC::CopyHandleDesc(2);
57 cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom(); 57 cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom();
@@ -75,20 +75,24 @@ void GetSharedFont(Service::Interface* self) {
75 if (!shared_font_mem) { 75 if (!shared_font_mem) {
76 LOG_ERROR(Service_APT, "shared font file missing - go dump it from your 3ds"); 76 LOG_ERROR(Service_APT, "shared font file missing - go dump it from your 3ds");
77 cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2); 77 cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2);
78 cmd_buff[1] = -1; // TODO: Find the right error code 78 cmd_buff[1] = -1; // TODO: Find the right error code
79 return; 79 return;
80 } 80 }
81 81
82 // The shared font has to be relocated to the new address before being passed to the application. 82 // The shared font has to be relocated to the new address before being passed to the
83 VAddr target_address = Memory::PhysicalToVirtualAddress(shared_font_mem->linear_heap_phys_address); 83 // application.
84 VAddr target_address =
85 Memory::PhysicalToVirtualAddress(shared_font_mem->linear_heap_phys_address);
84 if (!shared_font_relocated) { 86 if (!shared_font_relocated) {
85 BCFNT::RelocateSharedFont(shared_font_mem, target_address); 87 BCFNT::RelocateSharedFont(shared_font_mem, target_address);
86 shared_font_relocated = true; 88 shared_font_relocated = true;
87 } 89 }
88 cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2); 90 cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2);
89 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 91 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
90 // Since the SharedMemory interface doesn't provide the address at which the memory was allocated, 92 // Since the SharedMemory interface doesn't provide the address at which the memory was
91 // the real APT service calculates this address by scanning the entire address space (using svcQueryMemory) 93 // allocated,
94 // the real APT service calculates this address by scanning the entire address space (using
95 // svcQueryMemory)
92 // and searches for an allocation of the same size as the Shared Font. 96 // and searches for an allocation of the same size as the Shared Font.
93 cmd_buff[2] = target_address; 97 cmd_buff[2] = target_address;
94 cmd_buff[3] = IPC::CopyHandleDesc(); 98 cmd_buff[3] = IPC::CopyHandleDesc();
@@ -112,18 +116,19 @@ void GetLockHandle(Service::Interface* self) {
112 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 116 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
113 117
114 cmd_buff[2] = applet_attributes; // Applet Attributes, this value is passed to Enable. 118 cmd_buff[2] = applet_attributes; // Applet Attributes, this value is passed to Enable.
115 cmd_buff[3] = 0; // Least significant bit = power button state 119 cmd_buff[3] = 0; // Least significant bit = power button state
116 cmd_buff[4] = IPC::CopyHandleDesc(); 120 cmd_buff[4] = IPC::CopyHandleDesc();
117 cmd_buff[5] = Kernel::g_handle_table.Create(lock).MoveFrom(); 121 cmd_buff[5] = Kernel::g_handle_table.Create(lock).MoveFrom();
118 122
119 LOG_WARNING(Service_APT, "(STUBBED) called handle=0x%08X applet_attributes=0x%08X", cmd_buff[5], applet_attributes); 123 LOG_WARNING(Service_APT, "(STUBBED) called handle=0x%08X applet_attributes=0x%08X", cmd_buff[5],
124 applet_attributes);
120} 125}
121 126
122void Enable(Service::Interface* self) { 127void Enable(Service::Interface* self) {
123 u32* cmd_buff = Kernel::GetCommandBuffer(); 128 u32* cmd_buff = Kernel::GetCommandBuffer();
124 u32 attributes = cmd_buff[1]; 129 u32 attributes = cmd_buff[1];
125 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 130 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
126 parameter_event->Signal(); // Let the application know that it has been started 131 parameter_event->Signal(); // Let the application know that it has been started
127 LOG_WARNING(Service_APT, "(STUBBED) called attributes=0x%08X", attributes); 132 LOG_WARNING(Service_APT, "(STUBBED) called attributes=0x%08X", attributes);
128} 133}
129 134
@@ -133,7 +138,7 @@ void GetAppletManInfo(Service::Interface* self) {
133 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 138 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
134 cmd_buff[2] = 0; 139 cmd_buff[2] = 0;
135 cmd_buff[3] = 0; 140 cmd_buff[3] = 0;
136 cmd_buff[4] = static_cast<u32>(AppletId::HomeMenu); // Home menu AppID 141 cmd_buff[4] = static_cast<u32>(AppletId::HomeMenu); // Home menu AppID
137 cmd_buff[5] = static_cast<u32>(AppletId::Application); // TODO(purpasmart96): Do this correctly 142 cmd_buff[5] = static_cast<u32>(AppletId::Application); // TODO(purpasmart96): Do this correctly
138 143
139 LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk); 144 LOG_WARNING(Service_APT, "(STUBBED) called unk=0x%08X", unk);
@@ -159,23 +164,24 @@ void IsRegistered(Service::Interface* self) {
159void InquireNotification(Service::Interface* self) { 164void InquireNotification(Service::Interface* self) {
160 u32* cmd_buff = Kernel::GetCommandBuffer(); 165 u32* cmd_buff = Kernel::GetCommandBuffer();
161 u32 app_id = cmd_buff[1]; 166 u32 app_id = cmd_buff[1];
162 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 167 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
163 cmd_buff[2] = static_cast<u32>(SignalType::None); // Signal type 168 cmd_buff[2] = static_cast<u32>(SignalType::None); // Signal type
164 LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id); 169 LOG_WARNING(Service_APT, "(STUBBED) called app_id=0x%08X", app_id);
165} 170}
166 171
167void SendParameter(Service::Interface* self) { 172void SendParameter(Service::Interface* self) {
168 u32* cmd_buff = Kernel::GetCommandBuffer(); 173 u32* cmd_buff = Kernel::GetCommandBuffer();
169 u32 src_app_id = cmd_buff[1]; 174 u32 src_app_id = cmd_buff[1];
170 u32 dst_app_id = cmd_buff[2]; 175 u32 dst_app_id = cmd_buff[2];
171 u32 signal_type = cmd_buff[3]; 176 u32 signal_type = cmd_buff[3];
172 u32 buffer_size = cmd_buff[4]; 177 u32 buffer_size = cmd_buff[4];
173 u32 value = cmd_buff[5]; 178 u32 value = cmd_buff[5];
174 u32 handle = cmd_buff[6]; 179 u32 handle = cmd_buff[6];
175 u32 size = cmd_buff[7]; 180 u32 size = cmd_buff[7];
176 u32 buffer = cmd_buff[8]; 181 u32 buffer = cmd_buff[8];
177 182
178 std::shared_ptr<HLE::Applets::Applet> dest_applet = HLE::Applets::Applet::Get(static_cast<AppletId>(dst_app_id)); 183 std::shared_ptr<HLE::Applets::Applet> dest_applet =
184 HLE::Applets::Applet::Get(static_cast<AppletId>(dst_app_id));
179 185
180 if (dest_applet == nullptr) { 186 if (dest_applet == nullptr) {
181 LOG_ERROR(Service_APT, "Unknown applet id=0x%08X", dst_app_id); 187 LOG_ERROR(Service_APT, "Unknown applet id=0x%08X", dst_app_id);
@@ -193,9 +199,11 @@ void SendParameter(Service::Interface* self) {
193 199
194 cmd_buff[1] = dest_applet->ReceiveParameter(param).raw; 200 cmd_buff[1] = dest_applet->ReceiveParameter(param).raw;
195 201
196 LOG_WARNING(Service_APT, "(STUBBED) called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X," 202 LOG_WARNING(
197 "buffer_size=0x%08X, value=0x%08X, handle=0x%08X, size=0x%08X, in_param_buffer_ptr=0x%08X", 203 Service_APT,
198 src_app_id, dst_app_id, signal_type, buffer_size, value, handle, size, buffer); 204 "(STUBBED) called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X,"
205 "buffer_size=0x%08X, value=0x%08X, handle=0x%08X, size=0x%08X, in_param_buffer_ptr=0x%08X",
206 src_app_id, dst_app_id, signal_type, buffer_size, value, handle, size, buffer);
199} 207}
200 208
201void ReceiveParameter(Service::Interface* self) { 209void ReceiveParameter(Service::Interface* self) {
@@ -206,7 +214,7 @@ void ReceiveParameter(Service::Interface* self) {
206 214
207 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 215 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
208 cmd_buff[2] = next_parameter.sender_id; 216 cmd_buff[2] = next_parameter.sender_id;
209 cmd_buff[3] = next_parameter.signal; // Signal type 217 cmd_buff[3] = next_parameter.signal; // Signal type
210 cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size 218 cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size
211 cmd_buff[5] = 0x10; 219 cmd_buff[5] = 0x10;
212 cmd_buff[6] = 0; 220 cmd_buff[6] = 0;
@@ -228,7 +236,7 @@ void GlanceParameter(Service::Interface* self) {
228 236
229 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 237 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
230 cmd_buff[2] = next_parameter.sender_id; 238 cmd_buff[2] = next_parameter.sender_id;
231 cmd_buff[3] = next_parameter.signal; // Signal type 239 cmd_buff[3] = next_parameter.signal; // Signal type
232 cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size 240 cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size
233 cmd_buff[5] = 0x10; 241 cmd_buff[5] = 0x10;
234 cmd_buff[6] = 0; 242 cmd_buff[6] = 0;
@@ -237,32 +245,34 @@ void GlanceParameter(Service::Interface* self) {
237 cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2; 245 cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2;
238 cmd_buff[8] = buffer; 246 cmd_buff[8] = buffer;
239 247
240 Memory::WriteBlock(buffer, next_parameter.buffer.data(), std::min(static_cast<size_t>(buffer_size), next_parameter.buffer.size())); 248 Memory::WriteBlock(buffer, next_parameter.buffer.data(),
249 std::min(static_cast<size_t>(buffer_size), next_parameter.buffer.size()));
241 250
242 LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); 251 LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size);
243} 252}
244 253
245void CancelParameter(Service::Interface* self) { 254void CancelParameter(Service::Interface* self) {
246 u32* cmd_buff = Kernel::GetCommandBuffer(); 255 u32* cmd_buff = Kernel::GetCommandBuffer();
247 u32 flag1 = cmd_buff[1]; 256 u32 flag1 = cmd_buff[1];
248 u32 unk = cmd_buff[2]; 257 u32 unk = cmd_buff[2];
249 u32 flag2 = cmd_buff[3]; 258 u32 flag2 = cmd_buff[3];
250 u32 app_id = cmd_buff[4]; 259 u32 app_id = cmd_buff[4];
251 260
252 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 261 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
253 cmd_buff[2] = 1; // Set to Success 262 cmd_buff[2] = 1; // Set to Success
254 263
255 LOG_WARNING(Service_APT, "(STUBBED) called flag1=0x%08X, unk=0x%08X, flag2=0x%08X, app_id=0x%08X", 264 LOG_WARNING(Service_APT,
256 flag1, unk, flag2, app_id); 265 "(STUBBED) called flag1=0x%08X, unk=0x%08X, flag2=0x%08X, app_id=0x%08X", flag1,
266 unk, flag2, app_id);
257} 267}
258 268
259void PrepareToStartApplication(Service::Interface* self) { 269void PrepareToStartApplication(Service::Interface* self) {
260 u32* cmd_buff = Kernel::GetCommandBuffer(); 270 u32* cmd_buff = Kernel::GetCommandBuffer();
261 u32 title_info1 = cmd_buff[1]; 271 u32 title_info1 = cmd_buff[1];
262 u32 title_info2 = cmd_buff[2]; 272 u32 title_info2 = cmd_buff[2];
263 u32 title_info3 = cmd_buff[3]; 273 u32 title_info3 = cmd_buff[3];
264 u32 title_info4 = cmd_buff[4]; 274 u32 title_info4 = cmd_buff[4];
265 u32 flags = cmd_buff[5]; 275 u32 flags = cmd_buff[5];
266 276
267 if (flags & 0x00000100) { 277 if (flags & 0x00000100) {
268 unknown_ns_state_field = 1; 278 unknown_ns_state_field = 1;
@@ -270,25 +280,28 @@ void PrepareToStartApplication(Service::Interface* self) {
270 280
271 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 281 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
272 282
273 LOG_WARNING(Service_APT, "(STUBBED) called title_info1=0x%08X, title_info2=0x%08X, title_info3=0x%08X," 283 LOG_WARNING(Service_APT,
274 "title_info4=0x%08X, flags=0x%08X", title_info1, title_info2, title_info3, title_info4, flags); 284 "(STUBBED) called title_info1=0x%08X, title_info2=0x%08X, title_info3=0x%08X,"
285 "title_info4=0x%08X, flags=0x%08X",
286 title_info1, title_info2, title_info3, title_info4, flags);
275} 287}
276 288
277void StartApplication(Service::Interface* self) { 289void StartApplication(Service::Interface* self) {
278 u32* cmd_buff = Kernel::GetCommandBuffer(); 290 u32* cmd_buff = Kernel::GetCommandBuffer();
279 u32 buffer1_size = cmd_buff[1]; 291 u32 buffer1_size = cmd_buff[1];
280 u32 buffer2_size = cmd_buff[2]; 292 u32 buffer2_size = cmd_buff[2];
281 u32 flag = cmd_buff[3]; 293 u32 flag = cmd_buff[3];
282 u32 size1 = cmd_buff[4]; 294 u32 size1 = cmd_buff[4];
283 u32 buffer1_ptr = cmd_buff[5]; 295 u32 buffer1_ptr = cmd_buff[5];
284 u32 size2 = cmd_buff[6]; 296 u32 size2 = cmd_buff[6];
285 u32 buffer2_ptr = cmd_buff[7]; 297 u32 buffer2_ptr = cmd_buff[7];
286 298
287 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 299 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
288 300
289 LOG_WARNING(Service_APT, "(STUBBED) called buffer1_size=0x%08X, buffer2_size=0x%08X, flag=0x%08X," 301 LOG_WARNING(Service_APT,
290 "size1=0x%08X, buffer1_ptr=0x%08X, size2=0x%08X, buffer2_ptr=0x%08X", 302 "(STUBBED) called buffer1_size=0x%08X, buffer2_size=0x%08X, flag=0x%08X,"
291 buffer1_size, buffer2_size, flag, size1, buffer1_ptr, size2, buffer2_ptr); 303 "size1=0x%08X, buffer1_ptr=0x%08X, size2=0x%08X, buffer2_ptr=0x%08X",
304 buffer1_size, buffer2_size, flag, size1, buffer1_ptr, size2, buffer2_ptr);
292} 305}
293 306
294void AppletUtility(Service::Interface* self) { 307void AppletUtility(Service::Interface* self) {
@@ -303,14 +316,15 @@ void AppletUtility(Service::Interface* self) {
303 316
304 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 317 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
305 318
306 LOG_WARNING(Service_APT, "(STUBBED) called command=0x%08X, buffer1_size=0x%08X, buffer2_size=0x%08X, " 319 LOG_WARNING(Service_APT,
307 "buffer1_addr=0x%08X, buffer2_addr=0x%08X", command, buffer1_size, buffer2_size, 320 "(STUBBED) called command=0x%08X, buffer1_size=0x%08X, buffer2_size=0x%08X, "
308 buffer1_addr, buffer2_addr); 321 "buffer1_addr=0x%08X, buffer2_addr=0x%08X",
322 command, buffer1_size, buffer2_size, buffer1_addr, buffer2_addr);
309} 323}
310 324
311void SetAppCpuTimeLimit(Service::Interface* self) { 325void SetAppCpuTimeLimit(Service::Interface* self) {
312 u32* cmd_buff = Kernel::GetCommandBuffer(); 326 u32* cmd_buff = Kernel::GetCommandBuffer();
313 u32 value = cmd_buff[1]; 327 u32 value = cmd_buff[1];
314 cpu_percent = cmd_buff[2]; 328 cpu_percent = cmd_buff[2];
315 329
316 if (value != 1) { 330 if (value != 1) {
@@ -393,7 +407,8 @@ void SetScreenCapPostPermission(Service::Interface* self) {
393 407
394 cmd_buff[0] = IPC::MakeHeader(0x55, 1, 0); 408 cmd_buff[0] = IPC::MakeHeader(0x55, 1, 0);
395 cmd_buff[1] = RESULT_SUCCESS.raw; 409 cmd_buff[1] = RESULT_SUCCESS.raw;
396 LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u", screen_capture_post_permission); 410 LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u",
411 screen_capture_post_permission);
397} 412}
398 413
399void GetScreenCapPostPermission(Service::Interface* self) { 414void GetScreenCapPostPermission(Service::Interface* self) {
@@ -402,7 +417,8 @@ void GetScreenCapPostPermission(Service::Interface* self) {
402 cmd_buff[0] = IPC::MakeHeader(0x56, 2, 0); 417 cmd_buff[0] = IPC::MakeHeader(0x56, 2, 0);
403 cmd_buff[1] = RESULT_SUCCESS.raw; 418 cmd_buff[1] = RESULT_SUCCESS.raw;
404 cmd_buff[2] = static_cast<u32>(screen_capture_post_permission); 419 cmd_buff[2] = static_cast<u32>(screen_capture_post_permission);
405 LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u", screen_capture_post_permission); 420 LOG_WARNING(Service_APT, "(STUBBED) screen_capture_post_permission=%u",
421 screen_capture_post_permission);
406} 422}
407 423
408void GetAppletInfo(Service::Interface* self) { 424void GetAppletInfo(Service::Interface* self) {
@@ -418,7 +434,8 @@ void GetAppletInfo(Service::Interface* self) {
418 cmd_buff[7] = 0; // Applet Attributes 434 cmd_buff[7] = 0; // Applet Attributes
419 } else { 435 } else {
420 cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, 436 cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Applet,
421 ErrorSummary::NotFound, ErrorLevel::Status).raw; 437 ErrorSummary::NotFound, ErrorLevel::Status)
438 .raw;
422 } 439 }
423 LOG_WARNING(Service_APT, "(stubbed) called appid=%u", app_id); 440 LOG_WARNING(Service_APT, "(stubbed) called appid=%u", app_id);
424} 441}
@@ -429,11 +446,15 @@ void GetStartupArgument(Service::Interface* self) {
429 StartupArgumentType startup_argument_type = static_cast<StartupArgumentType>(cmd_buff[2]); 446 StartupArgumentType startup_argument_type = static_cast<StartupArgumentType>(cmd_buff[2]);
430 447
431 if (parameter_size >= 0x300) { 448 if (parameter_size >= 0x300) {
432 LOG_ERROR(Service_APT, "Parameter size is outside the valid range (capped to 0x300): parameter_size=0x%08x", parameter_size); 449 LOG_ERROR(
450 Service_APT,
451 "Parameter size is outside the valid range (capped to 0x300): parameter_size=0x%08x",
452 parameter_size);
433 return; 453 return;
434 } 454 }
435 455
436 LOG_WARNING(Service_APT,"(stubbed) called startup_argument_type=%u , parameter_size=0x%08x , parameter_value=0x%08x", 456 LOG_WARNING(Service_APT, "(stubbed) called startup_argument_type=%u , parameter_size=0x%08x , "
457 "parameter_value=0x%08x",
437 startup_argument_type, parameter_size, Memory::Read32(cmd_buff[41])); 458 startup_argument_type, parameter_size, Memory::Read32(cmd_buff[41]));
438 459
439 cmd_buff[1] = RESULT_SUCCESS.raw; 460 cmd_buff[1] = RESULT_SUCCESS.raw;
@@ -484,8 +505,10 @@ void Init() {
484 if (file.IsOpen()) { 505 if (file.IsOpen()) {
485 // Create shared font memory object 506 // Create shared font memory object
486 using Kernel::MemoryPermission; 507 using Kernel::MemoryPermission;
487 shared_font_mem = Kernel::SharedMemory::Create(nullptr, 0x332000, // 3272 KB 508 shared_font_mem =
488 MemoryPermission::ReadWrite, MemoryPermission::Read, 0, Kernel::MemoryRegion::SYSTEM, "APT:SharedFont"); 509 Kernel::SharedMemory::Create(nullptr, 0x332000, // 3272 KB
510 MemoryPermission::ReadWrite, MemoryPermission::Read, 0,
511 Kernel::MemoryRegion::SYSTEM, "APT:SharedFont");
489 // Read shared font data 512 // Read shared font data
490 file.ReadBytes(shared_font_mem->GetPointer(), file.GetSize()); 513 file.ReadBytes(shared_font_mem->GetPointer(), file.GetSize());
491 } else { 514 } else {
@@ -497,7 +520,8 @@ void Init() {
497 520
498 cpu_percent = 0; 521 cpu_percent = 0;
499 unknown_ns_state_field = 0; 522 unknown_ns_state_field = 0;
500 screen_capture_post_permission = ScreencapPostPermission::CleanThePermission; // TODO(JamePeng): verify the initial value 523 screen_capture_post_permission =
524 ScreencapPostPermission::CleanThePermission; // TODO(JamePeng): verify the initial value
501 525
502 // TODO(bunnei): Check if these are created in Initialize or on APT process startup. 526 // TODO(bunnei): Check if these are created in Initialize or on APT process startup.
503 notification_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Notification"); 527 notification_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Notification");
diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h
index 077a6a316..fe8b8a7b8 100644
--- a/src/core/hle/service/apt/apt.h
+++ b/src/core/hle/service/apt/apt.h
@@ -46,58 +46,58 @@ static_assert(sizeof(CaptureBufferInfo) == 0x20, "CaptureBufferInfo struct has i
46 46
47/// Signals used by APT functions 47/// Signals used by APT functions
48enum class SignalType : u32 { 48enum class SignalType : u32 {
49 None = 0x0, 49 None = 0x0,
50 AppJustStarted = 0x1, 50 AppJustStarted = 0x1,
51 LibAppJustStarted = 0x2, 51 LibAppJustStarted = 0x2,
52 LibAppFinished = 0x3, 52 LibAppFinished = 0x3,
53 LibAppClosed = 0xA, 53 LibAppClosed = 0xA,
54 ReturningToApp = 0xB, 54 ReturningToApp = 0xB,
55 ExitingApp = 0xC, 55 ExitingApp = 0xC,
56}; 56};
57 57
58/// App Id's used by APT functions 58/// App Id's used by APT functions
59enum class AppletId : u32 { 59enum class AppletId : u32 {
60 HomeMenu = 0x101, 60 HomeMenu = 0x101,
61 AlternateMenu = 0x103, 61 AlternateMenu = 0x103,
62 Camera = 0x110, 62 Camera = 0x110,
63 FriendsList = 0x112, 63 FriendsList = 0x112,
64 GameNotes = 0x113, 64 GameNotes = 0x113,
65 InternetBrowser = 0x114, 65 InternetBrowser = 0x114,
66 InstructionManual = 0x115, 66 InstructionManual = 0x115,
67 Notifications = 0x116, 67 Notifications = 0x116,
68 Miiverse = 0x117, 68 Miiverse = 0x117,
69 MiiversePost = 0x118, 69 MiiversePost = 0x118,
70 AmiiboSettings = 0x119, 70 AmiiboSettings = 0x119,
71 SoftwareKeyboard1 = 0x201, 71 SoftwareKeyboard1 = 0x201,
72 Ed1 = 0x202, 72 Ed1 = 0x202,
73 PnoteApp = 0x204, 73 PnoteApp = 0x204,
74 SnoteApp = 0x205, 74 SnoteApp = 0x205,
75 Error = 0x206, 75 Error = 0x206,
76 Mint = 0x207, 76 Mint = 0x207,
77 Extrapad = 0x208, 77 Extrapad = 0x208,
78 Memolib = 0x209, 78 Memolib = 0x209,
79 Application = 0x300, 79 Application = 0x300,
80 AnyLibraryApplet = 0x400, 80 AnyLibraryApplet = 0x400,
81 SoftwareKeyboard2 = 0x401, 81 SoftwareKeyboard2 = 0x401,
82 Ed2 = 0x402, 82 Ed2 = 0x402,
83 PnoteApp2 = 0x404, 83 PnoteApp2 = 0x404,
84 SnoteApp2 = 0x405, 84 SnoteApp2 = 0x405,
85 Error2 = 0x406, 85 Error2 = 0x406,
86 Mint2 = 0x407, 86 Mint2 = 0x407,
87 Extrapad2 = 0x408, 87 Extrapad2 = 0x408,
88 Memolib2 = 0x409, 88 Memolib2 = 0x409,
89}; 89};
90 90
91enum class StartupArgumentType : u32 { 91enum class StartupArgumentType : u32 {
92 OtherApp = 0, 92 OtherApp = 0,
93 Restart = 1, 93 Restart = 1,
94 OtherMedia = 2, 94 OtherMedia = 2,
95}; 95};
96 96
97enum class ScreencapPostPermission : u32 { 97enum class ScreencapPostPermission : u32 {
98 CleanThePermission = 0, //TODO(JamePeng): verify what "zero" means 98 CleanThePermission = 0, // TODO(JamePeng): verify what "zero" means
99 NoExplicitSetting = 1, 99 NoExplicitSetting = 1,
100 EnableScreenshotPostingToMiiverse = 2, 100 EnableScreenshotPostingToMiiverse = 2,
101 DisableScreenshotPostingToMiiverse = 3 101 DisableScreenshotPostingToMiiverse = 3
102}; 102};
103 103
@@ -182,9 +182,12 @@ void GetAppletManInfo(Service::Interface* self);
182void GetAppletInfo(Service::Interface* self); 182void GetAppletInfo(Service::Interface* self);
183 183
184/** 184/**
185 * APT::IsRegistered service function. This returns whether the specified AppID is registered with NS yet. 185 * APT::IsRegistered service function. This returns whether the specified AppID is registered with
186 * An AppID is "registered" once the process associated with the AppID uses APT:Enable. Home Menu uses this 186 * NS yet.
187 * command to determine when the launched process is running and to determine when to stop using GSP etc, 187 * An AppID is "registered" once the process associated with the AppID uses APT:Enable. Home Menu
188 * uses this
189 * command to determine when the launched process is running and to determine when to stop using GSP
190 * etc,
188 * while displaying the "Nintendo 3DS" loading screen. 191 * while displaying the "Nintendo 3DS" loading screen.
189 * Inputs: 192 * Inputs:
190 * 1 : AppID 193 * 1 : AppID
@@ -260,9 +263,11 @@ void GlanceParameter(Service::Interface* self);
260 * clears the flag which indicates that parameter data is available 263 * clears the flag which indicates that parameter data is available
261 * (same flag cleared by APT:ReceiveParameter). 264 * (same flag cleared by APT:ReceiveParameter).
262 * Inputs: 265 * Inputs:
263 * 1 : Flag, when non-zero NS will compare the word after this one with a field in the NS state. 266 * 1 : Flag, when non-zero NS will compare the word after this one with a field in the NS
267 * state.
264 * 2 : Unknown, this is the same as the first unknown field returned by APT:ReceiveParameter. 268 * 2 : Unknown, this is the same as the first unknown field returned by APT:ReceiveParameter.
265 * 3 : Flag, when non-zero NS will compare the word after this one with a field in the NS state. 269 * 3 : Flag, when non-zero NS will compare the word after this one with a field in the NS
270 * state.
266 * 4 : AppID 271 * 4 : AppID
267 * Outputs: 272 * Outputs:
268 * 0 : Return header 273 * 0 : Return header
diff --git a/src/core/hle/service/apt/apt_a.cpp b/src/core/hle/service/apt/apt_a.cpp
index 6c44c491c..7d47d7675 100644
--- a/src/core/hle/service/apt/apt_a.cpp
+++ b/src/core/hle/service/apt/apt_a.cpp
@@ -9,35 +9,34 @@ namespace Service {
9namespace APT { 9namespace APT {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010040, GetLockHandle, "GetLockHandle?"}, 12 {0x00010040, GetLockHandle, "GetLockHandle?"},
13 {0x00020080, Initialize, "Initialize?"}, 13 {0x00020080, Initialize, "Initialize?"},
14 {0x00030040, Enable, "Enable?"}, 14 {0x00030040, Enable, "Enable?"},
15 {0x00040040, nullptr, "Finalize?"}, 15 {0x00040040, nullptr, "Finalize?"},
16 {0x00050040, GetAppletManInfo, "GetAppletManInfo"}, 16 {0x00050040, GetAppletManInfo, "GetAppletManInfo"},
17 {0x00060040, GetAppletInfo, "GetAppletInfo"}, 17 {0x00060040, GetAppletInfo, "GetAppletInfo"},
18 {0x00090040, IsRegistered, "IsRegistered"}, 18 {0x00090040, IsRegistered, "IsRegistered"},
19 {0x000B0040, InquireNotification, "InquireNotification"}, 19 {0x000B0040, InquireNotification, "InquireNotification"},
20 {0x000C0104, SendParameter, "SendParameter"}, 20 {0x000C0104, SendParameter, "SendParameter"},
21 {0x000D0080, ReceiveParameter, "ReceiveParameter"}, 21 {0x000D0080, ReceiveParameter, "ReceiveParameter"},
22 {0x000E0080, GlanceParameter, "GlanceParameter"}, 22 {0x000E0080, GlanceParameter, "GlanceParameter"},
23 {0x000F0100, CancelParameter, "CancelParameter"}, 23 {0x000F0100, CancelParameter, "CancelParameter"},
24 {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, 24 {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"},
25 {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, 25 {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"},
26 {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, 26 {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"},
27 {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, 27 {0x001E0084, StartLibraryApplet, "StartLibraryApplet"},
28 {0x003B0040, nullptr, "CancelLibraryApplet?"}, 28 {0x003B0040, nullptr, "CancelLibraryApplet?"},
29 {0x003E0080, nullptr, "ReplySleepQuery"}, 29 {0x003E0080, nullptr, "ReplySleepQuery"},
30 {0x00430040, NotifyToWait, "NotifyToWait?"}, 30 {0x00430040, NotifyToWait, "NotifyToWait?"},
31 {0x00440000, GetSharedFont, "GetSharedFont?"}, 31 {0x00440000, GetSharedFont, "GetSharedFont?"},
32 {0x004B00C2, AppletUtility, "AppletUtility?"}, 32 {0x004B00C2, AppletUtility, "AppletUtility?"},
33 {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, 33 {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"},
34 {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, 34 {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"},
35 {0x00510080, GetStartupArgument, "GetStartupArgument"}, 35 {0x00510080, GetStartupArgument, "GetStartupArgument"},
36 {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"}, 36 {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"},
37 {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"}, 37 {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"},
38 {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, 38 {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"},
39 {0x01020000, CheckNew3DS, "CheckNew3DS"} 39 {0x01020000, CheckNew3DS, "CheckNew3DS"}};
40};
41 40
42APT_A_Interface::APT_A_Interface() { 41APT_A_Interface::APT_A_Interface() {
43 Register(FunctionTable); 42 Register(FunctionTable);
diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp
index c70f2201f..76e71669c 100644
--- a/src/core/hle/service/apt/apt_s.cpp
+++ b/src/core/hle/service/apt/apt_s.cpp
@@ -9,95 +9,94 @@ namespace Service {
9namespace APT { 9namespace APT {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010040, GetLockHandle, "GetLockHandle"}, 12 {0x00010040, GetLockHandle, "GetLockHandle"},
13 {0x00020080, Initialize, "Initialize"}, 13 {0x00020080, Initialize, "Initialize"},
14 {0x00030040, Enable, "Enable"}, 14 {0x00030040, Enable, "Enable"},
15 {0x00040040, nullptr, "Finalize"}, 15 {0x00040040, nullptr, "Finalize"},
16 {0x00050040, GetAppletManInfo, "GetAppletManInfo"}, 16 {0x00050040, GetAppletManInfo, "GetAppletManInfo"},
17 {0x00060040, GetAppletInfo, "GetAppletInfo"}, 17 {0x00060040, GetAppletInfo, "GetAppletInfo"},
18 {0x00070000, nullptr, "GetLastSignaledAppletId"}, 18 {0x00070000, nullptr, "GetLastSignaledAppletId"},
19 {0x00080000, nullptr, "CountRegisteredApplet"}, 19 {0x00080000, nullptr, "CountRegisteredApplet"},
20 {0x00090040, nullptr, "IsRegistered"}, 20 {0x00090040, nullptr, "IsRegistered"},
21 {0x000A0040, nullptr, "GetAttribute"}, 21 {0x000A0040, nullptr, "GetAttribute"},
22 {0x000B0040, InquireNotification, "InquireNotification"}, 22 {0x000B0040, InquireNotification, "InquireNotification"},
23 {0x000C0104, nullptr, "SendParameter"}, 23 {0x000C0104, nullptr, "SendParameter"},
24 {0x000D0080, ReceiveParameter, "ReceiveParameter"}, 24 {0x000D0080, ReceiveParameter, "ReceiveParameter"},
25 {0x000E0080, GlanceParameter, "GlanceParameter"}, 25 {0x000E0080, GlanceParameter, "GlanceParameter"},
26 {0x000F0100, nullptr, "CancelParameter"}, 26 {0x000F0100, nullptr, "CancelParameter"},
27 {0x001000C2, nullptr, "DebugFunc"}, 27 {0x001000C2, nullptr, "DebugFunc"},
28 {0x001100C0, nullptr, "MapProgramIdForDebug"}, 28 {0x001100C0, nullptr, "MapProgramIdForDebug"},
29 {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"}, 29 {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"},
30 {0x00130000, nullptr, "GetPreparationState"}, 30 {0x00130000, nullptr, "GetPreparationState"},
31 {0x00140040, nullptr, "SetPreparationState"}, 31 {0x00140040, nullptr, "SetPreparationState"},
32 {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, 32 {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"},
33 {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, 33 {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"},
34 {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, 34 {0x00170040, nullptr, "FinishPreloadingLibraryApplet"},
35 {0x00180040, PrepareToStartLibraryApplet,"PrepareToStartLibraryApplet"}, 35 {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"},
36 {0x00190040, nullptr, "PrepareToStartSystemApplet"}, 36 {0x00190040, nullptr, "PrepareToStartSystemApplet"},
37 {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, 37 {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"},
38 {0x001B00C4, nullptr, "StartApplication"}, 38 {0x001B00C4, nullptr, "StartApplication"},
39 {0x001C0000, nullptr, "WakeupApplication"}, 39 {0x001C0000, nullptr, "WakeupApplication"},
40 {0x001D0000, nullptr, "CancelApplication"}, 40 {0x001D0000, nullptr, "CancelApplication"},
41 {0x001E0084, nullptr, "StartLibraryApplet"}, 41 {0x001E0084, nullptr, "StartLibraryApplet"},
42 {0x001F0084, nullptr, "StartSystemApplet"}, 42 {0x001F0084, nullptr, "StartSystemApplet"},
43 {0x00200044, nullptr, "StartNewestHomeMenu"}, 43 {0x00200044, nullptr, "StartNewestHomeMenu"},
44 {0x00210000, nullptr, "OrderToCloseApplication"}, 44 {0x00210000, nullptr, "OrderToCloseApplication"},
45 {0x00220040, nullptr, "PrepareToCloseApplication"}, 45 {0x00220040, nullptr, "PrepareToCloseApplication"},
46 {0x00230040, nullptr, "PrepareToJumpToApplication"}, 46 {0x00230040, nullptr, "PrepareToJumpToApplication"},
47 {0x00240044, nullptr, "JumpToApplication"}, 47 {0x00240044, nullptr, "JumpToApplication"},
48 {0x002500C0, nullptr, "PrepareToCloseLibraryApplet"}, 48 {0x002500C0, nullptr, "PrepareToCloseLibraryApplet"},
49 {0x00260000, nullptr, "PrepareToCloseSystemApplet"}, 49 {0x00260000, nullptr, "PrepareToCloseSystemApplet"},
50 {0x00270044, nullptr, "CloseApplication"}, 50 {0x00270044, nullptr, "CloseApplication"},
51 {0x00280044, nullptr, "CloseLibraryApplet"}, 51 {0x00280044, nullptr, "CloseLibraryApplet"},
52 {0x00290044, nullptr, "CloseSystemApplet"}, 52 {0x00290044, nullptr, "CloseSystemApplet"},
53 {0x002A0000, nullptr, "OrderToCloseSystemApplet"}, 53 {0x002A0000, nullptr, "OrderToCloseSystemApplet"},
54 {0x002B0000, nullptr, "PrepareToJumpToHomeMenu"}, 54 {0x002B0000, nullptr, "PrepareToJumpToHomeMenu"},
55 {0x002C0044, nullptr, "JumpToHomeMenu"}, 55 {0x002C0044, nullptr, "JumpToHomeMenu"},
56 {0x002D0000, nullptr, "PrepareToLeaveHomeMenu"}, 56 {0x002D0000, nullptr, "PrepareToLeaveHomeMenu"},
57 {0x002E0044, nullptr, "LeaveHomeMenu"}, 57 {0x002E0044, nullptr, "LeaveHomeMenu"},
58 {0x002F0040, nullptr, "PrepareToLeaveResidentApplet"}, 58 {0x002F0040, nullptr, "PrepareToLeaveResidentApplet"},
59 {0x00300044, nullptr, "LeaveResidentApplet"}, 59 {0x00300044, nullptr, "LeaveResidentApplet"},
60 {0x00310100, nullptr, "PrepareToDoApplicationJump"}, 60 {0x00310100, nullptr, "PrepareToDoApplicationJump"},
61 {0x00320084, nullptr, "DoApplicationJump"}, 61 {0x00320084, nullptr, "DoApplicationJump"},
62 {0x00330000, nullptr, "GetProgramIdOnApplicationJump"}, 62 {0x00330000, nullptr, "GetProgramIdOnApplicationJump"},
63 {0x00340084, nullptr, "SendDeliverArg"}, 63 {0x00340084, nullptr, "SendDeliverArg"},
64 {0x00350080, nullptr, "ReceiveDeliverArg"}, 64 {0x00350080, nullptr, "ReceiveDeliverArg"},
65 {0x00360040, nullptr, "LoadSysMenuArg"}, 65 {0x00360040, nullptr, "LoadSysMenuArg"},
66 {0x00370042, nullptr, "StoreSysMenuArg"}, 66 {0x00370042, nullptr, "StoreSysMenuArg"},
67 {0x00380040, nullptr, "PreloadResidentApplet"}, 67 {0x00380040, nullptr, "PreloadResidentApplet"},
68 {0x00390040, nullptr, "PrepareToStartResidentApplet"}, 68 {0x00390040, nullptr, "PrepareToStartResidentApplet"},
69 {0x003A0044, nullptr, "StartResidentApplet"}, 69 {0x003A0044, nullptr, "StartResidentApplet"},
70 {0x003B0040, nullptr, "CancelLibraryApplet"}, 70 {0x003B0040, nullptr, "CancelLibraryApplet"},
71 {0x003C0042, nullptr, "SendDspSleep"}, 71 {0x003C0042, nullptr, "SendDspSleep"},
72 {0x003D0042, nullptr, "SendDspWakeUp"}, 72 {0x003D0042, nullptr, "SendDspWakeUp"},
73 {0x003E0080, nullptr, "ReplySleepQuery"}, 73 {0x003E0080, nullptr, "ReplySleepQuery"},
74 {0x003F0040, nullptr, "ReplySleepNotificationComplete"}, 74 {0x003F0040, nullptr, "ReplySleepNotificationComplete"},
75 {0x00400042, nullptr, "SendCaptureBufferInfo"}, 75 {0x00400042, nullptr, "SendCaptureBufferInfo"},
76 {0x00410040, nullptr, "ReceiveCaptureBufferInfo"}, 76 {0x00410040, nullptr, "ReceiveCaptureBufferInfo"},
77 {0x00420080, nullptr, "SleepSystem"}, 77 {0x00420080, nullptr, "SleepSystem"},
78 {0x00430040, NotifyToWait, "NotifyToWait"}, 78 {0x00430040, NotifyToWait, "NotifyToWait"},
79 {0x00440000, GetSharedFont, "GetSharedFont"}, 79 {0x00440000, GetSharedFont, "GetSharedFont"},
80 {0x00450040, nullptr, "GetWirelessRebootInfo"}, 80 {0x00450040, nullptr, "GetWirelessRebootInfo"},
81 {0x00460104, nullptr, "Wrap"}, 81 {0x00460104, nullptr, "Wrap"},
82 {0x00470104, nullptr, "Unwrap"}, 82 {0x00470104, nullptr, "Unwrap"},
83 {0x00480100, nullptr, "GetProgramInfo"}, 83 {0x00480100, nullptr, "GetProgramInfo"},
84 {0x00490180, nullptr, "Reboot"}, 84 {0x00490180, nullptr, "Reboot"},
85 {0x004A0040, nullptr, "GetCaptureInfo"}, 85 {0x004A0040, nullptr, "GetCaptureInfo"},
86 {0x004B00C2, AppletUtility, "AppletUtility"}, 86 {0x004B00C2, AppletUtility, "AppletUtility"},
87 {0x004C0000, nullptr, "SetFatalErrDispMode"}, 87 {0x004C0000, nullptr, "SetFatalErrDispMode"},
88 {0x004D0080, nullptr, "GetAppletProgramInfo"}, 88 {0x004D0080, nullptr, "GetAppletProgramInfo"},
89 {0x004E0000, nullptr, "HardwareResetAsync"}, 89 {0x004E0000, nullptr, "HardwareResetAsync"},
90 {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, 90 {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"},
91 {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, 91 {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"},
92 {0x00510080, GetStartupArgument, "GetStartupArgument"}, 92 {0x00510080, GetStartupArgument, "GetStartupArgument"},
93 {0x00520104, nullptr, "Wrap1"}, 93 {0x00520104, nullptr, "Wrap1"},
94 {0x00530104, nullptr, "Unwrap1"}, 94 {0x00530104, nullptr, "Unwrap1"},
95 {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"}, 95 {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"},
96 {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"}, 96 {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"},
97 {0x00580002, nullptr, "GetProgramID"}, 97 {0x00580002, nullptr, "GetProgramID"},
98 {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, 98 {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"},
99 {0x01020000, CheckNew3DS, "CheckNew3DS"} 99 {0x01020000, CheckNew3DS, "CheckNew3DS"}};
100};
101 100
102APT_S_Interface::APT_S_Interface() { 101APT_S_Interface::APT_S_Interface() {
103 Register(FunctionTable); 102 Register(FunctionTable);
diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp
index 7bb804ffa..9c6223dd7 100644
--- a/src/core/hle/service/apt/apt_u.cpp
+++ b/src/core/hle/service/apt/apt_u.cpp
@@ -9,95 +9,94 @@ namespace Service {
9namespace APT { 9namespace APT {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010040, GetLockHandle, "GetLockHandle"}, 12 {0x00010040, GetLockHandle, "GetLockHandle"},
13 {0x00020080, Initialize, "Initialize"}, 13 {0x00020080, Initialize, "Initialize"},
14 {0x00030040, Enable, "Enable"}, 14 {0x00030040, Enable, "Enable"},
15 {0x00040040, nullptr, "Finalize"}, 15 {0x00040040, nullptr, "Finalize"},
16 {0x00050040, GetAppletManInfo, "GetAppletManInfo"}, 16 {0x00050040, GetAppletManInfo, "GetAppletManInfo"},
17 {0x00060040, GetAppletInfo, "GetAppletInfo"}, 17 {0x00060040, GetAppletInfo, "GetAppletInfo"},
18 {0x00070000, nullptr, "GetLastSignaledAppletId"}, 18 {0x00070000, nullptr, "GetLastSignaledAppletId"},
19 {0x00080000, nullptr, "CountRegisteredApplet"}, 19 {0x00080000, nullptr, "CountRegisteredApplet"},
20 {0x00090040, IsRegistered, "IsRegistered"}, 20 {0x00090040, IsRegistered, "IsRegistered"},
21 {0x000A0040, nullptr, "GetAttribute"}, 21 {0x000A0040, nullptr, "GetAttribute"},
22 {0x000B0040, InquireNotification, "InquireNotification"}, 22 {0x000B0040, InquireNotification, "InquireNotification"},
23 {0x000C0104, SendParameter, "SendParameter"}, 23 {0x000C0104, SendParameter, "SendParameter"},
24 {0x000D0080, ReceiveParameter, "ReceiveParameter"}, 24 {0x000D0080, ReceiveParameter, "ReceiveParameter"},
25 {0x000E0080, GlanceParameter, "GlanceParameter"}, 25 {0x000E0080, GlanceParameter, "GlanceParameter"},
26 {0x000F0100, CancelParameter, "CancelParameter"}, 26 {0x000F0100, CancelParameter, "CancelParameter"},
27 {0x001000C2, nullptr, "DebugFunc"}, 27 {0x001000C2, nullptr, "DebugFunc"},
28 {0x001100C0, nullptr, "MapProgramIdForDebug"}, 28 {0x001100C0, nullptr, "MapProgramIdForDebug"},
29 {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"}, 29 {0x00120040, nullptr, "SetHomeMenuAppletIdForDebug"},
30 {0x00130000, nullptr, "GetPreparationState"}, 30 {0x00130000, nullptr, "GetPreparationState"},
31 {0x00140040, nullptr, "SetPreparationState"}, 31 {0x00140040, nullptr, "SetPreparationState"},
32 {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"}, 32 {0x00150140, PrepareToStartApplication, "PrepareToStartApplication"},
33 {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"}, 33 {0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"},
34 {0x00170040, nullptr, "FinishPreloadingLibraryApplet"}, 34 {0x00170040, nullptr, "FinishPreloadingLibraryApplet"},
35 {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"}, 35 {0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"},
36 {0x00190040, nullptr, "PrepareToStartSystemApplet"}, 36 {0x00190040, nullptr, "PrepareToStartSystemApplet"},
37 {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"}, 37 {0x001A0000, nullptr, "PrepareToStartNewestHomeMenu"},
38 {0x001B00C4, nullptr, "StartApplication"}, 38 {0x001B00C4, nullptr, "StartApplication"},
39 {0x001C0000, nullptr, "WakeupApplication"}, 39 {0x001C0000, nullptr, "WakeupApplication"},
40 {0x001D0000, nullptr, "CancelApplication"}, 40 {0x001D0000, nullptr, "CancelApplication"},
41 {0x001E0084, StartLibraryApplet, "StartLibraryApplet"}, 41 {0x001E0084, StartLibraryApplet, "StartLibraryApplet"},
42 {0x001F0084, nullptr, "StartSystemApplet"}, 42 {0x001F0084, nullptr, "StartSystemApplet"},
43 {0x00200044, nullptr, "StartNewestHomeMenu"}, 43 {0x00200044, nullptr, "StartNewestHomeMenu"},
44 {0x00210000, nullptr, "OrderToCloseApplication"}, 44 {0x00210000, nullptr, "OrderToCloseApplication"},
45 {0x00220040, nullptr, "PrepareToCloseApplication"}, 45 {0x00220040, nullptr, "PrepareToCloseApplication"},
46 {0x00230040, nullptr, "PrepareToJumpToApplication"}, 46 {0x00230040, nullptr, "PrepareToJumpToApplication"},
47 {0x00240044, nullptr, "JumpToApplication"}, 47 {0x00240044, nullptr, "JumpToApplication"},
48 {0x002500C0, nullptr, "PrepareToCloseLibraryApplet"}, 48 {0x002500C0, nullptr, "PrepareToCloseLibraryApplet"},
49 {0x00260000, nullptr, "PrepareToCloseSystemApplet"}, 49 {0x00260000, nullptr, "PrepareToCloseSystemApplet"},
50 {0x00270044, nullptr, "CloseApplication"}, 50 {0x00270044, nullptr, "CloseApplication"},
51 {0x00280044, nullptr, "CloseLibraryApplet"}, 51 {0x00280044, nullptr, "CloseLibraryApplet"},
52 {0x00290044, nullptr, "CloseSystemApplet"}, 52 {0x00290044, nullptr, "CloseSystemApplet"},
53 {0x002A0000, nullptr, "OrderToCloseSystemApplet"}, 53 {0x002A0000, nullptr, "OrderToCloseSystemApplet"},
54 {0x002B0000, nullptr, "PrepareToJumpToHomeMenu"}, 54 {0x002B0000, nullptr, "PrepareToJumpToHomeMenu"},
55 {0x002C0044, nullptr, "JumpToHomeMenu"}, 55 {0x002C0044, nullptr, "JumpToHomeMenu"},
56 {0x002D0000, nullptr, "PrepareToLeaveHomeMenu"}, 56 {0x002D0000, nullptr, "PrepareToLeaveHomeMenu"},
57 {0x002E0044, nullptr, "LeaveHomeMenu"}, 57 {0x002E0044, nullptr, "LeaveHomeMenu"},
58 {0x002F0040, nullptr, "PrepareToLeaveResidentApplet"}, 58 {0x002F0040, nullptr, "PrepareToLeaveResidentApplet"},
59 {0x00300044, nullptr, "LeaveResidentApplet"}, 59 {0x00300044, nullptr, "LeaveResidentApplet"},
60 {0x00310100, nullptr, "PrepareToDoApplicationJump"}, 60 {0x00310100, nullptr, "PrepareToDoApplicationJump"},
61 {0x00320084, nullptr, "DoApplicationJump"}, 61 {0x00320084, nullptr, "DoApplicationJump"},
62 {0x00330000, nullptr, "GetProgramIdOnApplicationJump"}, 62 {0x00330000, nullptr, "GetProgramIdOnApplicationJump"},
63 {0x00340084, nullptr, "SendDeliverArg"}, 63 {0x00340084, nullptr, "SendDeliverArg"},
64 {0x00350080, nullptr, "ReceiveDeliverArg"}, 64 {0x00350080, nullptr, "ReceiveDeliverArg"},
65 {0x00360040, nullptr, "LoadSysMenuArg"}, 65 {0x00360040, nullptr, "LoadSysMenuArg"},
66 {0x00370042, nullptr, "StoreSysMenuArg"}, 66 {0x00370042, nullptr, "StoreSysMenuArg"},
67 {0x00380040, nullptr, "PreloadResidentApplet"}, 67 {0x00380040, nullptr, "PreloadResidentApplet"},
68 {0x00390040, nullptr, "PrepareToStartResidentApplet"}, 68 {0x00390040, nullptr, "PrepareToStartResidentApplet"},
69 {0x003A0044, nullptr, "StartResidentApplet"}, 69 {0x003A0044, nullptr, "StartResidentApplet"},
70 {0x003B0040, nullptr, "CancelLibraryApplet"}, 70 {0x003B0040, nullptr, "CancelLibraryApplet"},
71 {0x003C0042, nullptr, "SendDspSleep"}, 71 {0x003C0042, nullptr, "SendDspSleep"},
72 {0x003D0042, nullptr, "SendDspWakeUp"}, 72 {0x003D0042, nullptr, "SendDspWakeUp"},
73 {0x003E0080, nullptr, "ReplySleepQuery"}, 73 {0x003E0080, nullptr, "ReplySleepQuery"},
74 {0x003F0040, nullptr, "ReplySleepNotificationComplete"}, 74 {0x003F0040, nullptr, "ReplySleepNotificationComplete"},
75 {0x00400042, nullptr, "SendCaptureBufferInfo"}, 75 {0x00400042, nullptr, "SendCaptureBufferInfo"},
76 {0x00410040, nullptr, "ReceiveCaptureBufferInfo"}, 76 {0x00410040, nullptr, "ReceiveCaptureBufferInfo"},
77 {0x00420080, nullptr, "SleepSystem"}, 77 {0x00420080, nullptr, "SleepSystem"},
78 {0x00430040, NotifyToWait, "NotifyToWait"}, 78 {0x00430040, NotifyToWait, "NotifyToWait"},
79 {0x00440000, GetSharedFont, "GetSharedFont"}, 79 {0x00440000, GetSharedFont, "GetSharedFont"},
80 {0x00450040, nullptr, "GetWirelessRebootInfo"}, 80 {0x00450040, nullptr, "GetWirelessRebootInfo"},
81 {0x00460104, nullptr, "Wrap"}, 81 {0x00460104, nullptr, "Wrap"},
82 {0x00470104, nullptr, "Unwrap"}, 82 {0x00470104, nullptr, "Unwrap"},
83 {0x00480100, nullptr, "GetProgramInfo"}, 83 {0x00480100, nullptr, "GetProgramInfo"},
84 {0x00490180, nullptr, "Reboot"}, 84 {0x00490180, nullptr, "Reboot"},
85 {0x004A0040, nullptr, "GetCaptureInfo"}, 85 {0x004A0040, nullptr, "GetCaptureInfo"},
86 {0x004B00C2, AppletUtility, "AppletUtility"}, 86 {0x004B00C2, AppletUtility, "AppletUtility"},
87 {0x004C0000, nullptr, "SetFatalErrDispMode"}, 87 {0x004C0000, nullptr, "SetFatalErrDispMode"},
88 {0x004D0080, nullptr, "GetAppletProgramInfo"}, 88 {0x004D0080, nullptr, "GetAppletProgramInfo"},
89 {0x004E0000, nullptr, "HardwareResetAsync"}, 89 {0x004E0000, nullptr, "HardwareResetAsync"},
90 {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"}, 90 {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"},
91 {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"}, 91 {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"},
92 {0x00510080, GetStartupArgument, "GetStartupArgument"}, 92 {0x00510080, GetStartupArgument, "GetStartupArgument"},
93 {0x00520104, nullptr, "Wrap1"}, 93 {0x00520104, nullptr, "Wrap1"},
94 {0x00530104, nullptr, "Unwrap1"}, 94 {0x00530104, nullptr, "Unwrap1"},
95 {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"}, 95 {0x00550040, SetScreenCapPostPermission, "SetScreenCapPostPermission"},
96 {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"}, 96 {0x00560000, GetScreenCapPostPermission, "GetScreenCapPostPermission"},
97 {0x00580002, nullptr, "GetProgramID"}, 97 {0x00580002, nullptr, "GetProgramID"},
98 {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"}, 98 {0x01010000, CheckNew3DSApp, "CheckNew3DSApp"},
99 {0x01020000, CheckNew3DS, "CheckNew3DS"} 99 {0x01020000, CheckNew3DS, "CheckNew3DS"}};
100};
101 100
102APT_U_Interface::APT_U_Interface() { 101APT_U_Interface::APT_U_Interface() {
103 Register(FunctionTable); 102 Register(FunctionTable);
diff --git a/src/core/hle/service/boss/boss.cpp b/src/core/hle/service/boss/boss.cpp
index 419ec976e..867b31fbf 100644
--- a/src/core/hle/service/boss/boss.cpp
+++ b/src/core/hle/service/boss/boss.cpp
@@ -2,10 +2,10 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/hle/service/service.h"
6#include "core/hle/service/boss/boss.h" 5#include "core/hle/service/boss/boss.h"
7#include "core/hle/service/boss/boss_p.h" 6#include "core/hle/service/boss/boss_p.h"
8#include "core/hle/service/boss/boss_u.h" 7#include "core/hle/service/boss/boss_u.h"
8#include "core/hle/service/service.h"
9 9
10namespace Service { 10namespace Service {
11namespace BOSS { 11namespace BOSS {
diff --git a/src/core/hle/service/boss/boss_p.cpp b/src/core/hle/service/boss/boss_p.cpp
index c498abe4e..dfee8d055 100644
--- a/src/core/hle/service/boss/boss_p.cpp
+++ b/src/core/hle/service/boss/boss_p.cpp
@@ -11,7 +11,7 @@ namespace BOSS {
11// const Interface::FunctionInfo FunctionTable[] = { }; 11// const Interface::FunctionInfo FunctionTable[] = { };
12 12
13BOSS_P_Interface::BOSS_P_Interface() { 13BOSS_P_Interface::BOSS_P_Interface() {
14 //Register(FunctionTable); 14 // Register(FunctionTable);
15} 15}
16 16
17} // namespace BOSS 17} // namespace BOSS
diff --git a/src/core/hle/service/boss/boss_u.cpp b/src/core/hle/service/boss/boss_u.cpp
index d59babe71..6affa23b1 100644
--- a/src/core/hle/service/boss/boss_u.cpp
+++ b/src/core/hle/service/boss/boss_u.cpp
@@ -8,10 +8,10 @@ namespace Service {
8namespace BOSS { 8namespace BOSS {
9 9
10const Interface::FunctionInfo FunctionTable[] = { 10const Interface::FunctionInfo FunctionTable[] = {
11 {0x00020100, nullptr, "GetStorageInfo"}, 11 {0x00020100, nullptr, "GetStorageInfo"},
12 {0x000C0082, nullptr, "UnregisterTask"}, 12 {0x000C0082, nullptr, "UnregisterTask"},
13 {0x001E0042, nullptr, "CancelTask"}, 13 {0x001E0042, nullptr, "CancelTask"},
14 {0x00330042, nullptr, "StartBgImmediate"}, 14 {0x00330042, nullptr, "StartBgImmediate"},
15}; 15};
16 16
17BOSS_U_Interface::BOSS_U_Interface() { 17BOSS_U_Interface::BOSS_U_Interface() {
diff --git a/src/core/hle/service/cam/cam.cpp b/src/core/hle/service/cam/cam.cpp
index 6edcf9610..ec1f9c749 100644
--- a/src/core/hle/service/cam/cam.cpp
+++ b/src/core/hle/service/cam/cam.cpp
@@ -71,15 +71,15 @@ void GetBufferErrorInterruptEvent(Service::Interface* self) {
71} 71}
72 72
73void SetReceiving(Service::Interface* self) { 73void SetReceiving(Service::Interface* self) {
74 u32* cmd_buff = Kernel::GetCommandBuffer(); 74 u32* cmd_buff = Kernel::GetCommandBuffer();
75 75
76 VAddr dest = cmd_buff[1]; 76 VAddr dest = cmd_buff[1];
77 u8 port = cmd_buff[2] & 0xFF; 77 u8 port = cmd_buff[2] & 0xFF;
78 u32 image_size = cmd_buff[3]; 78 u32 image_size = cmd_buff[3];
79 u16 trans_unit = cmd_buff[4] & 0xFFFF; 79 u16 trans_unit = cmd_buff[4] & 0xFFFF;
80 80
81 Kernel::Event* completion_event = (Port)port == Port::Cam2 ? 81 Kernel::Event* completion_event =
82 completion_event_cam2.get() : completion_event_cam1.get(); 82 (Port)port == Port::Cam2 ? completion_event_cam2.get() : completion_event_cam1.get();
83 83
84 completion_event->Signal(); 84 completion_event->Signal();
85 85
@@ -89,36 +89,36 @@ void SetReceiving(Service::Interface* self) {
89 cmd_buff[3] = Kernel::g_handle_table.Create(completion_event).MoveFrom(); 89 cmd_buff[3] = Kernel::g_handle_table.Create(completion_event).MoveFrom();
90 90
91 LOG_WARNING(Service_CAM, "(STUBBED) called, addr=0x%X, port=%d, image_size=%d, trans_unit=%d", 91 LOG_WARNING(Service_CAM, "(STUBBED) called, addr=0x%X, port=%d, image_size=%d, trans_unit=%d",
92 dest, port, image_size, trans_unit); 92 dest, port, image_size, trans_unit);
93} 93}
94 94
95void SetTransferLines(Service::Interface* self) { 95void SetTransferLines(Service::Interface* self) {
96 u32* cmd_buff = Kernel::GetCommandBuffer(); 96 u32* cmd_buff = Kernel::GetCommandBuffer();
97 97
98 u8 port = cmd_buff[1] & 0xFF; 98 u8 port = cmd_buff[1] & 0xFF;
99 u16 transfer_lines = cmd_buff[2] & 0xFFFF; 99 u16 transfer_lines = cmd_buff[2] & 0xFFFF;
100 u16 width = cmd_buff[3] & 0xFFFF; 100 u16 width = cmd_buff[3] & 0xFFFF;
101 u16 height = cmd_buff[4] & 0xFFFF; 101 u16 height = cmd_buff[4] & 0xFFFF;
102 102
103 cmd_buff[0] = IPC::MakeHeader(0x9, 1, 0); 103 cmd_buff[0] = IPC::MakeHeader(0x9, 1, 0);
104 cmd_buff[1] = RESULT_SUCCESS.raw; 104 cmd_buff[1] = RESULT_SUCCESS.raw;
105 105
106 LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, lines=%d, width=%d, height=%d", 106 LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, lines=%d, width=%d, height=%d", port,
107 port, transfer_lines, width, height); 107 transfer_lines, width, height);
108} 108}
109 109
110void GetMaxLines(Service::Interface* self) { 110void GetMaxLines(Service::Interface* self) {
111 u32* cmd_buff = Kernel::GetCommandBuffer(); 111 u32* cmd_buff = Kernel::GetCommandBuffer();
112 112
113 u16 width = cmd_buff[1] & 0xFFFF; 113 u16 width = cmd_buff[1] & 0xFFFF;
114 u16 height = cmd_buff[2] & 0xFFFF; 114 u16 height = cmd_buff[2] & 0xFFFF;
115 115
116 cmd_buff[0] = IPC::MakeHeader(0xA, 2, 0); 116 cmd_buff[0] = IPC::MakeHeader(0xA, 2, 0);
117 cmd_buff[1] = RESULT_SUCCESS.raw; 117 cmd_buff[1] = RESULT_SUCCESS.raw;
118 cmd_buff[2] = TRANSFER_BYTES / (2 * width); 118 cmd_buff[2] = TRANSFER_BYTES / (2 * width);
119 119
120 LOG_WARNING(Service_CAM, "(STUBBED) called, width=%d, height=%d, lines = %d", 120 LOG_WARNING(Service_CAM, "(STUBBED) called, width=%d, height=%d, lines = %d", width, height,
121 width, height, cmd_buff[2]); 121 cmd_buff[2]);
122} 122}
123 123
124void GetTransferBytes(Service::Interface* self) { 124void GetTransferBytes(Service::Interface* self) {
@@ -136,7 +136,7 @@ void GetTransferBytes(Service::Interface* self) {
136void SetTrimming(Service::Interface* self) { 136void SetTrimming(Service::Interface* self) {
137 u32* cmd_buff = Kernel::GetCommandBuffer(); 137 u32* cmd_buff = Kernel::GetCommandBuffer();
138 138
139 u8 port = cmd_buff[1] & 0xFF; 139 u8 port = cmd_buff[1] & 0xFF;
140 bool trim = (cmd_buff[2] & 0xFF) != 0; 140 bool trim = (cmd_buff[2] & 0xFF) != 0;
141 141
142 cmd_buff[0] = IPC::MakeHeader(0xE, 1, 0); 142 cmd_buff[0] = IPC::MakeHeader(0xE, 1, 0);
@@ -148,17 +148,17 @@ void SetTrimming(Service::Interface* self) {
148void SetTrimmingParamsCenter(Service::Interface* self) { 148void SetTrimmingParamsCenter(Service::Interface* self) {
149 u32* cmd_buff = Kernel::GetCommandBuffer(); 149 u32* cmd_buff = Kernel::GetCommandBuffer();
150 150
151 u8 port = cmd_buff[1] & 0xFF; 151 u8 port = cmd_buff[1] & 0xFF;
152 s16 trimW = cmd_buff[2] & 0xFFFF; 152 s16 trimW = cmd_buff[2] & 0xFFFF;
153 s16 trimH = cmd_buff[3] & 0xFFFF; 153 s16 trimH = cmd_buff[3] & 0xFFFF;
154 s16 camW = cmd_buff[4] & 0xFFFF; 154 s16 camW = cmd_buff[4] & 0xFFFF;
155 s16 camH = cmd_buff[5] & 0xFFFF; 155 s16 camH = cmd_buff[5] & 0xFFFF;
156 156
157 cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0); 157 cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0);
158 cmd_buff[1] = RESULT_SUCCESS.raw; 158 cmd_buff[1] = RESULT_SUCCESS.raw;
159 159
160 LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, trimW=%d, trimH=%d, camW=%d, camH=%d", 160 LOG_WARNING(Service_CAM, "(STUBBED) called, port=%d, trimW=%d, trimH=%d, camW=%d, camH=%d",
161 port, trimW, trimH, camW, camH); 161 port, trimW, trimH, camW, camH);
162} 162}
163 163
164void Activate(Service::Interface* self) { 164void Activate(Service::Interface* self) {
@@ -169,36 +169,35 @@ void Activate(Service::Interface* self) {
169 cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0); 169 cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0);
170 cmd_buff[1] = RESULT_SUCCESS.raw; 170 cmd_buff[1] = RESULT_SUCCESS.raw;
171 171
172 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d", 172 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d", cam_select);
173 cam_select);
174} 173}
175 174
176void FlipImage(Service::Interface* self) { 175void FlipImage(Service::Interface* self) {
177 u32* cmd_buff = Kernel::GetCommandBuffer(); 176 u32* cmd_buff = Kernel::GetCommandBuffer();
178 177
179 u8 cam_select = cmd_buff[1] & 0xFF; 178 u8 cam_select = cmd_buff[1] & 0xFF;
180 u8 flip = cmd_buff[2] & 0xFF; 179 u8 flip = cmd_buff[2] & 0xFF;
181 u8 context = cmd_buff[3] & 0xFF; 180 u8 context = cmd_buff[3] & 0xFF;
182 181
183 cmd_buff[0] = IPC::MakeHeader(0x1D, 1, 0); 182 cmd_buff[0] = IPC::MakeHeader(0x1D, 1, 0);
184 cmd_buff[1] = RESULT_SUCCESS.raw; 183 cmd_buff[1] = RESULT_SUCCESS.raw;
185 184
186 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, flip=%d, context=%d", 185 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, flip=%d, context=%d", cam_select,
187 cam_select, flip, context); 186 flip, context);
188} 187}
189 188
190void SetSize(Service::Interface* self) { 189void SetSize(Service::Interface* self) {
191 u32* cmd_buff = Kernel::GetCommandBuffer(); 190 u32* cmd_buff = Kernel::GetCommandBuffer();
192 191
193 u8 cam_select = cmd_buff[1] & 0xFF; 192 u8 cam_select = cmd_buff[1] & 0xFF;
194 u8 size = cmd_buff[2] & 0xFF; 193 u8 size = cmd_buff[2] & 0xFF;
195 u8 context = cmd_buff[3] & 0xFF; 194 u8 context = cmd_buff[3] & 0xFF;
196 195
197 cmd_buff[0] = IPC::MakeHeader(0x1F, 1, 0); 196 cmd_buff[0] = IPC::MakeHeader(0x1F, 1, 0);
198 cmd_buff[1] = RESULT_SUCCESS.raw; 197 cmd_buff[1] = RESULT_SUCCESS.raw;
199 198
200 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, size=%d, context=%d", 199 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, size=%d, context=%d", cam_select,
201 cam_select, size, context); 200 size, context);
202} 201}
203 202
204void SetFrameRate(Service::Interface* self) { 203void SetFrameRate(Service::Interface* self) {
@@ -210,8 +209,8 @@ void SetFrameRate(Service::Interface* self) {
210 cmd_buff[0] = IPC::MakeHeader(0x20, 1, 0); 209 cmd_buff[0] = IPC::MakeHeader(0x20, 1, 0);
211 cmd_buff[1] = RESULT_SUCCESS.raw; 210 cmd_buff[1] = RESULT_SUCCESS.raw;
212 211
213 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, frame_rate=%d", 212 LOG_WARNING(Service_CAM, "(STUBBED) called, cam_select=%d, frame_rate=%d", cam_select,
214 cam_select, frame_rate); 213 frame_rate);
215} 214}
216 215
217void GetStereoCameraCalibrationData(Service::Interface* self) { 216void GetStereoCameraCalibrationData(Service::Interface* self) {
@@ -293,10 +292,14 @@ void Init() {
293 AddService(new CAM_S_Interface); 292 AddService(new CAM_S_Interface);
294 AddService(new CAM_U_Interface); 293 AddService(new CAM_U_Interface);
295 294
296 completion_event_cam1 = Kernel::Event::Create(ResetType::OneShot, "CAM_U::completion_event_cam1"); 295 completion_event_cam1 =
297 completion_event_cam2 = Kernel::Event::Create(ResetType::OneShot, "CAM_U::completion_event_cam2"); 296 Kernel::Event::Create(ResetType::OneShot, "CAM_U::completion_event_cam1");
298 interrupt_error_event = Kernel::Event::Create(ResetType::OneShot, "CAM_U::interrupt_error_event"); 297 completion_event_cam2 =
299 vsync_interrupt_error_event = Kernel::Event::Create(ResetType::OneShot, "CAM_U::vsync_interrupt_error_event"); 298 Kernel::Event::Create(ResetType::OneShot, "CAM_U::completion_event_cam2");
299 interrupt_error_event =
300 Kernel::Event::Create(ResetType::OneShot, "CAM_U::interrupt_error_event");
301 vsync_interrupt_error_event =
302 Kernel::Event::Create(ResetType::OneShot, "CAM_U::vsync_interrupt_error_event");
300} 303}
301 304
302void Shutdown() { 305void Shutdown() {
diff --git a/src/core/hle/service/cam/cam.h b/src/core/hle/service/cam/cam.h
index 2f4923728..a87183493 100644
--- a/src/core/hle/service/cam/cam.h
+++ b/src/core/hle/service/cam/cam.h
@@ -14,12 +14,7 @@
14namespace Service { 14namespace Service {
15namespace CAM { 15namespace CAM {
16 16
17enum class Port : u8 { 17enum class Port : u8 { None = 0, Cam1 = 1, Cam2 = 2, Both = Cam1 | Cam2 };
18 None = 0,
19 Cam1 = 1,
20 Cam2 = 2,
21 Both = Cam1 | Cam2
22};
23 18
24enum class CameraSelect : u8 { 19enum class CameraSelect : u8 {
25 None = 0, 20 None = 0,
@@ -32,28 +27,11 @@ enum class CameraSelect : u8 {
32 All = Out1 | In1 | Out2 27 All = Out1 | In1 | Out2
33}; 28};
34 29
35enum class Effect : u8 { 30enum class Effect : u8 { None = 0, Mono = 1, Sepia = 2, Negative = 3, Negafilm = 4, Sepia01 = 5 };
36 None = 0,
37 Mono = 1,
38 Sepia = 2,
39 Negative = 3,
40 Negafilm = 4,
41 Sepia01 = 5
42};
43 31
44enum class Context : u8 { 32enum class Context : u8 { None = 0, A = 1, B = 2, Both = A | B };
45 None = 0,
46 A = 1,
47 B = 2,
48 Both = A | B
49};
50 33
51enum class Flip : u8 { 34enum class Flip : u8 { None = 0, Horizontal = 1, Vertical = 2, Reverse = 3 };
52 None = 0,
53 Horizontal = 1,
54 Vertical = 2,
55 Reverse = 3
56};
57 35
58enum class Size : u8 { 36enum class Size : u8 {
59 VGA = 0, 37 VGA = 0,
@@ -83,11 +61,7 @@ enum class FrameRate : u8 {
83 Rate_30_To_10 = 12 61 Rate_30_To_10 = 12
84}; 62};
85 63
86enum class ShutterSoundType : u8 { 64enum class ShutterSoundType : u8 { Normal = 0, Movie = 1, MovieEnd = 2 };
87 Normal = 0,
88 Movie = 1,
89 MovieEnd = 2
90};
91 65
92enum class WhiteBalance : u8 { 66enum class WhiteBalance : u8 {
93 BalanceAuto = 0, 67 BalanceAuto = 0,
@@ -106,13 +80,7 @@ enum class WhiteBalance : u8 {
106 BalanceShade = Balance7000K 80 BalanceShade = Balance7000K
107}; 81};
108 82
109enum class PhotoMode : u8 { 83enum class PhotoMode : u8 { Normal = 0, Portrait = 1, Landscape = 2, Nightview = 3, Letter0 = 4 };
110 Normal = 0,
111 Portrait = 1,
112 Landscape = 2,
113 Nightview = 3,
114 Letter0 = 4
115};
116 84
117enum class LensCorrection : u8 { 85enum class LensCorrection : u8 {
118 Off = 0, 86 Off = 0,
@@ -140,21 +108,18 @@ enum class Contrast : u8 {
140 High = Pattern07 108 High = Pattern07
141}; 109};
142 110
143enum class OutputFormat : u8 { 111enum class OutputFormat : u8 { YUV422 = 0, RGB565 = 1 };
144 YUV422 = 0,
145 RGB565 = 1
146};
147 112
148/// Stereo camera calibration data. 113/// Stereo camera calibration data.
149struct StereoCameraCalibrationData { 114struct StereoCameraCalibrationData {
150 u8 isValidRotationXY; ///< Bool indicating whether the X and Y rotation data is valid. 115 u8 isValidRotationXY; ///< Bool indicating whether the X and Y rotation data is valid.
151 INSERT_PADDING_BYTES(3); 116 INSERT_PADDING_BYTES(3);
152 float_le scale; ///< Scale to match the left camera image with the right. 117 float_le scale; ///< Scale to match the left camera image with the right.
153 float_le rotationZ; ///< Z axis rotation to match the left camera image with the right. 118 float_le rotationZ; ///< Z axis rotation to match the left camera image with the right.
154 float_le translationX; ///< X axis translation to match the left camera image with the right. 119 float_le translationX; ///< X axis translation to match the left camera image with the right.
155 float_le translationY; ///< Y axis translation to match the left camera image with the right. 120 float_le translationY; ///< Y axis translation to match the left camera image with the right.
156 float_le rotationX; ///< X axis rotation to match the left camera image with the right. 121 float_le rotationX; ///< X axis rotation to match the left camera image with the right.
157 float_le rotationY; ///< Y axis rotation to match the left camera image with the right. 122 float_le rotationY; ///< Y axis rotation to match the left camera image with the right.
158 float_le angleOfViewRight; ///< Right camera angle of view. 123 float_le angleOfViewRight; ///< Right camera angle of view.
159 float_le angleOfViewLeft; ///< Left camera angle of view. 124 float_le angleOfViewLeft; ///< Left camera angle of view.
160 float_le distanceToChart; ///< Distance between cameras and measurement chart. 125 float_le distanceToChart; ///< Distance between cameras and measurement chart.
@@ -163,7 +128,8 @@ struct StereoCameraCalibrationData {
163 s16_le imageHeight; ///< Image height. 128 s16_le imageHeight; ///< Image height.
164 INSERT_PADDING_BYTES(16); 129 INSERT_PADDING_BYTES(16);
165}; 130};
166static_assert(sizeof(StereoCameraCalibrationData) == 64, "StereoCameraCalibrationData structure size is wrong"); 131static_assert(sizeof(StereoCameraCalibrationData) == 64,
132 "StereoCameraCalibrationData structure size is wrong");
167 133
168struct PackageParameterCameraSelect { 134struct PackageParameterCameraSelect {
169 CameraSelect camera; 135 CameraSelect camera;
@@ -188,7 +154,8 @@ struct PackageParameterCameraSelect {
188 s16 auto_white_balance_window_height; 154 s16 auto_white_balance_window_height;
189}; 155};
190 156
191static_assert(sizeof(PackageParameterCameraSelect) == 28, "PackageParameterCameraSelect structure size is wrong"); 157static_assert(sizeof(PackageParameterCameraSelect) == 28,
158 "PackageParameterCameraSelect structure size is wrong");
192 159
193/** 160/**
194 * Unknown 161 * Unknown
diff --git a/src/core/hle/service/cam/cam_c.cpp b/src/core/hle/service/cam/cam_c.cpp
index 8fa7abc85..93b047c1a 100644
--- a/src/core/hle/service/cam/cam_c.cpp
+++ b/src/core/hle/service/cam/cam_c.cpp
@@ -8,10 +8,10 @@ namespace Service {
8namespace CAM { 8namespace CAM {
9 9
10// Empty arrays are illegal -- commented out until an entry is added. 10// Empty arrays are illegal -- commented out until an entry is added.
11//const Interface::FunctionInfo FunctionTable[] = { }; 11// const Interface::FunctionInfo FunctionTable[] = { };
12 12
13CAM_C_Interface::CAM_C_Interface() { 13CAM_C_Interface::CAM_C_Interface() {
14 //Register(FunctionTable); 14 // Register(FunctionTable);
15} 15}
16 16
17} // namespace CAM 17} // namespace CAM
diff --git a/src/core/hle/service/cam/cam_q.cpp b/src/core/hle/service/cam/cam_q.cpp
index d3ba91e9d..2ba853606 100644
--- a/src/core/hle/service/cam/cam_q.cpp
+++ b/src/core/hle/service/cam/cam_q.cpp
@@ -8,10 +8,10 @@ namespace Service {
8namespace CAM { 8namespace CAM {
9 9
10// Empty arrays are illegal -- commented out until an entry is added. 10// Empty arrays are illegal -- commented out until an entry is added.
11//const Interface::FunctionInfo FunctionTable[] = { }; 11// const Interface::FunctionInfo FunctionTable[] = { };
12 12
13CAM_Q_Interface::CAM_Q_Interface() { 13CAM_Q_Interface::CAM_Q_Interface() {
14 //Register(FunctionTable); 14 // Register(FunctionTable);
15} 15}
16 16
17} // namespace CAM 17} // namespace CAM
diff --git a/src/core/hle/service/cam/cam_s.cpp b/src/core/hle/service/cam/cam_s.cpp
index 2a13984d8..f1c6da587 100644
--- a/src/core/hle/service/cam/cam_s.cpp
+++ b/src/core/hle/service/cam/cam_s.cpp
@@ -8,10 +8,10 @@ namespace Service {
8namespace CAM { 8namespace CAM {
9 9
10// Empty arrays are illegal -- commented out until an entry is added. 10// Empty arrays are illegal -- commented out until an entry is added.
11//const Interface::FunctionInfo FunctionTable[] = { }; 11// const Interface::FunctionInfo FunctionTable[] = { };
12 12
13CAM_S_Interface::CAM_S_Interface() { 13CAM_S_Interface::CAM_S_Interface() {
14 //Register(FunctionTable); 14 // Register(FunctionTable);
15} 15}
16 16
17} // namespace CAM 17} // namespace CAM
diff --git a/src/core/hle/service/cam/cam_u.cpp b/src/core/hle/service/cam/cam_u.cpp
index a1070ebb2..af2123e5b 100644
--- a/src/core/hle/service/cam/cam_u.cpp
+++ b/src/core/hle/service/cam/cam_u.cpp
@@ -9,68 +9,68 @@ namespace Service {
9namespace CAM { 9namespace CAM {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010040, StartCapture, "StartCapture"}, 12 {0x00010040, StartCapture, "StartCapture"},
13 {0x00020040, StopCapture, "StopCapture"}, 13 {0x00020040, StopCapture, "StopCapture"},
14 {0x00030040, nullptr, "IsBusy"}, 14 {0x00030040, nullptr, "IsBusy"},
15 {0x00040040, nullptr, "ClearBuffer"}, 15 {0x00040040, nullptr, "ClearBuffer"},
16 {0x00050040, GetVsyncInterruptEvent, "GetVsyncInterruptEvent"}, 16 {0x00050040, GetVsyncInterruptEvent, "GetVsyncInterruptEvent"},
17 {0x00060040, GetBufferErrorInterruptEvent, "GetBufferErrorInterruptEvent"}, 17 {0x00060040, GetBufferErrorInterruptEvent, "GetBufferErrorInterruptEvent"},
18 {0x00070102, SetReceiving, "SetReceiving"}, 18 {0x00070102, SetReceiving, "SetReceiving"},
19 {0x00080040, nullptr, "IsFinishedReceiving"}, 19 {0x00080040, nullptr, "IsFinishedReceiving"},
20 {0x00090100, SetTransferLines, "SetTransferLines"}, 20 {0x00090100, SetTransferLines, "SetTransferLines"},
21 {0x000A0080, GetMaxLines, "GetMaxLines"}, 21 {0x000A0080, GetMaxLines, "GetMaxLines"},
22 {0x000B0100, nullptr, "SetTransferBytes"}, 22 {0x000B0100, nullptr, "SetTransferBytes"},
23 {0x000C0040, GetTransferBytes, "GetTransferBytes"}, 23 {0x000C0040, GetTransferBytes, "GetTransferBytes"},
24 {0x000D0080, nullptr, "GetMaxBytes"}, 24 {0x000D0080, nullptr, "GetMaxBytes"},
25 {0x000E0080, SetTrimming, "SetTrimming"}, 25 {0x000E0080, SetTrimming, "SetTrimming"},
26 {0x000F0040, nullptr, "IsTrimming"}, 26 {0x000F0040, nullptr, "IsTrimming"},
27 {0x00100140, nullptr, "SetTrimmingParams"}, 27 {0x00100140, nullptr, "SetTrimmingParams"},
28 {0x00110040, nullptr, "GetTrimmingParams"}, 28 {0x00110040, nullptr, "GetTrimmingParams"},
29 {0x00120140, SetTrimmingParamsCenter, "SetTrimmingParamsCenter"}, 29 {0x00120140, SetTrimmingParamsCenter, "SetTrimmingParamsCenter"},
30 {0x00130040, Activate, "Activate"}, 30 {0x00130040, Activate, "Activate"},
31 {0x00140080, nullptr, "SwitchContext"}, 31 {0x00140080, nullptr, "SwitchContext"},
32 {0x00150080, nullptr, "SetExposure"}, 32 {0x00150080, nullptr, "SetExposure"},
33 {0x00160080, nullptr, "SetWhiteBalance"}, 33 {0x00160080, nullptr, "SetWhiteBalance"},
34 {0x00170080, nullptr, "SetWhiteBalanceWithoutBaseUp"}, 34 {0x00170080, nullptr, "SetWhiteBalanceWithoutBaseUp"},
35 {0x00180080, nullptr, "SetSharpness"}, 35 {0x00180080, nullptr, "SetSharpness"},
36 {0x00190080, nullptr, "SetAutoExposure"}, 36 {0x00190080, nullptr, "SetAutoExposure"},
37 {0x001A0040, nullptr, "IsAutoExposure"}, 37 {0x001A0040, nullptr, "IsAutoExposure"},
38 {0x001B0080, nullptr, "SetAutoWhiteBalance"}, 38 {0x001B0080, nullptr, "SetAutoWhiteBalance"},
39 {0x001C0040, nullptr, "IsAutoWhiteBalance"}, 39 {0x001C0040, nullptr, "IsAutoWhiteBalance"},
40 {0x001D00C0, FlipImage, "FlipImage"}, 40 {0x001D00C0, FlipImage, "FlipImage"},
41 {0x001E0200, nullptr, "SetDetailSize"}, 41 {0x001E0200, nullptr, "SetDetailSize"},
42 {0x001F00C0, SetSize, "SetSize"}, 42 {0x001F00C0, SetSize, "SetSize"},
43 {0x00200080, SetFrameRate, "SetFrameRate"}, 43 {0x00200080, SetFrameRate, "SetFrameRate"},
44 {0x00210080, nullptr, "SetPhotoMode"}, 44 {0x00210080, nullptr, "SetPhotoMode"},
45 {0x002200C0, nullptr, "SetEffect"}, 45 {0x002200C0, nullptr, "SetEffect"},
46 {0x00230080, nullptr, "SetContrast"}, 46 {0x00230080, nullptr, "SetContrast"},
47 {0x00240080, nullptr, "SetLensCorrection"}, 47 {0x00240080, nullptr, "SetLensCorrection"},
48 {0x002500C0, nullptr, "SetOutputFormat"}, 48 {0x002500C0, nullptr, "SetOutputFormat"},
49 {0x00260140, nullptr, "SetAutoExposureWindow"}, 49 {0x00260140, nullptr, "SetAutoExposureWindow"},
50 {0x00270140, nullptr, "SetAutoWhiteBalanceWindow"}, 50 {0x00270140, nullptr, "SetAutoWhiteBalanceWindow"},
51 {0x00280080, nullptr, "SetNoiseFilter"}, 51 {0x00280080, nullptr, "SetNoiseFilter"},
52 {0x00290080, nullptr, "SynchronizeVsyncTiming"}, 52 {0x00290080, nullptr, "SynchronizeVsyncTiming"},
53 {0x002A0080, nullptr, "GetLatestVsyncTiming"}, 53 {0x002A0080, nullptr, "GetLatestVsyncTiming"},
54 {0x002B0000, GetStereoCameraCalibrationData, "GetStereoCameraCalibrationData"}, 54 {0x002B0000, GetStereoCameraCalibrationData, "GetStereoCameraCalibrationData"},
55 {0x002C0400, nullptr, "SetStereoCameraCalibrationData"}, 55 {0x002C0400, nullptr, "SetStereoCameraCalibrationData"},
56 {0x002D00C0, nullptr, "WriteRegisterI2c"}, 56 {0x002D00C0, nullptr, "WriteRegisterI2c"},
57 {0x002E00C0, nullptr, "WriteMcuVariableI2c"}, 57 {0x002E00C0, nullptr, "WriteMcuVariableI2c"},
58 {0x002F0080, nullptr, "ReadRegisterI2cExclusive"}, 58 {0x002F0080, nullptr, "ReadRegisterI2cExclusive"},
59 {0x00300080, nullptr, "ReadMcuVariableI2cExclusive"}, 59 {0x00300080, nullptr, "ReadMcuVariableI2cExclusive"},
60 {0x00310180, nullptr, "SetImageQualityCalibrationData"}, 60 {0x00310180, nullptr, "SetImageQualityCalibrationData"},
61 {0x00320000, nullptr, "GetImageQualityCalibrationData"}, 61 {0x00320000, nullptr, "GetImageQualityCalibrationData"},
62 {0x003302C0, nullptr, "SetPackageParameterWithoutContext"}, 62 {0x003302C0, nullptr, "SetPackageParameterWithoutContext"},
63 {0x00340140, nullptr, "SetPackageParameterWithContext"}, 63 {0x00340140, nullptr, "SetPackageParameterWithContext"},
64 {0x003501C0, nullptr, "SetPackageParameterWithContextDetail"}, 64 {0x003501C0, nullptr, "SetPackageParameterWithContextDetail"},
65 {0x00360000, GetSuitableY2rStandardCoefficient, "GetSuitableY2rStandardCoefficient"}, 65 {0x00360000, GetSuitableY2rStandardCoefficient, "GetSuitableY2rStandardCoefficient"},
66 {0x00370202, nullptr, "PlayShutterSoundWithWave"}, 66 {0x00370202, nullptr, "PlayShutterSoundWithWave"},
67 {0x00380040, PlayShutterSound, "PlayShutterSound"}, 67 {0x00380040, PlayShutterSound, "PlayShutterSound"},
68 {0x00390000, DriverInitialize, "DriverInitialize"}, 68 {0x00390000, DriverInitialize, "DriverInitialize"},
69 {0x003A0000, DriverFinalize, "DriverFinalize"}, 69 {0x003A0000, DriverFinalize, "DriverFinalize"},
70 {0x003B0000, nullptr, "GetActivatedCamera"}, 70 {0x003B0000, nullptr, "GetActivatedCamera"},
71 {0x003C0000, nullptr, "GetSleepCamera"}, 71 {0x003C0000, nullptr, "GetSleepCamera"},
72 {0x003D0040, nullptr, "SetSleepCamera"}, 72 {0x003D0040, nullptr, "SetSleepCamera"},
73 {0x003E0040, nullptr, "SetBrightnessSynchronization"}, 73 {0x003E0040, nullptr, "SetBrightnessSynchronization"},
74}; 74};
75 75
76CAM_U_Interface::CAM_U_Interface() { 76CAM_U_Interface::CAM_U_Interface() {
diff --git a/src/core/hle/service/cecd/cecd.cpp b/src/core/hle/service/cecd/cecd.cpp
index 50c03495e..65a1d850b 100644
--- a/src/core/hle/service/cecd/cecd.cpp
+++ b/src/core/hle/service/cecd/cecd.cpp
@@ -5,10 +5,10 @@
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6 6
7#include "core/hle/kernel/event.h" 7#include "core/hle/kernel/event.h"
8#include "core/hle/service/service.h"
9#include "core/hle/service/cecd/cecd.h" 8#include "core/hle/service/cecd/cecd.h"
10#include "core/hle/service/cecd/cecd_s.h" 9#include "core/hle/service/cecd/cecd_s.h"
11#include "core/hle/service/cecd/cecd_u.h" 10#include "core/hle/service/cecd/cecd_u.h"
11#include "core/hle/service/service.h"
12 12
13namespace Service { 13namespace Service {
14namespace CECD { 14namespace CECD {
@@ -28,7 +28,7 @@ void GetCecStateAbbreviated(Service::Interface* self) {
28void GetCecInfoEventHandle(Service::Interface* self) { 28void GetCecInfoEventHandle(Service::Interface* self) {
29 u32* cmd_buff = Kernel::GetCommandBuffer(); 29 u32* cmd_buff = Kernel::GetCommandBuffer();
30 30
31 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 31 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
32 cmd_buff[3] = Kernel::g_handle_table.Create(cecinfo_event).MoveFrom(); // Event handle 32 cmd_buff[3] = Kernel::g_handle_table.Create(cecinfo_event).MoveFrom(); // Event handle
33 33
34 LOG_WARNING(Service_CECD, "(STUBBED) called"); 34 LOG_WARNING(Service_CECD, "(STUBBED) called");
@@ -37,7 +37,7 @@ void GetCecInfoEventHandle(Service::Interface* self) {
37void GetChangeStateEventHandle(Service::Interface* self) { 37void GetChangeStateEventHandle(Service::Interface* self) {
38 u32* cmd_buff = Kernel::GetCommandBuffer(); 38 u32* cmd_buff = Kernel::GetCommandBuffer();
39 39
40 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 40 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
41 cmd_buff[3] = Kernel::g_handle_table.Create(change_state_event).MoveFrom(); // Event handle 41 cmd_buff[3] = Kernel::g_handle_table.Create(change_state_event).MoveFrom(); // Event handle
42 42
43 LOG_WARNING(Service_CECD, "(STUBBED) called"); 43 LOG_WARNING(Service_CECD, "(STUBBED) called");
@@ -48,7 +48,8 @@ void Init() {
48 AddService(new CECD_U_Interface); 48 AddService(new CECD_U_Interface);
49 49
50 cecinfo_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD_U::cecinfo_event"); 50 cecinfo_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD_U::cecinfo_event");
51 change_state_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD_U::change_state_event"); 51 change_state_event =
52 Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD_U::change_state_event");
52} 53}
53 54
54void Shutdown() { 55void Shutdown() {
diff --git a/src/core/hle/service/cecd/cecd.h b/src/core/hle/service/cecd/cecd.h
index 435611363..ea97f9266 100644
--- a/src/core/hle/service/cecd/cecd.h
+++ b/src/core/hle/service/cecd/cecd.h
@@ -11,11 +11,13 @@ class Interface;
11namespace CECD { 11namespace CECD {
12 12
13enum class CecStateAbbreviated { 13enum class CecStateAbbreviated {
14 CEC_STATE_ABBREV_IDLE = 1, ///< Corresponds to CEC_STATE_IDLE 14 CEC_STATE_ABBREV_IDLE = 1, ///< Corresponds to CEC_STATE_IDLE
15 CEC_STATE_ABBREV_NOT_LOCAL = 2, ///< Corresponds to CEC_STATEs *FINISH*, *POST, and OVER_BOSS 15 CEC_STATE_ABBREV_NOT_LOCAL = 2, ///< Corresponds to CEC_STATEs *FINISH*, *POST, and OVER_BOSS
16 CEC_STATE_ABBREV_SCANNING = 3, ///< Corresponds to CEC_STATE_SCANNING 16 CEC_STATE_ABBREV_SCANNING = 3, ///< Corresponds to CEC_STATE_SCANNING
17 CEC_STATE_ABBREV_WLREADY = 4, ///< Corresponds to CEC_STATE_WIRELESS_READY when some unknown bool is true 17 CEC_STATE_ABBREV_WLREADY =
18 CEC_STATE_ABBREV_OTHER = 5, ///< Corresponds to CEC_STATEs besides *FINISH*, *POST, and OVER_BOSS and those listed here 18 4, ///< Corresponds to CEC_STATE_WIRELESS_READY when some unknown bool is true
19 CEC_STATE_ABBREV_OTHER = 5, ///< Corresponds to CEC_STATEs besides *FINISH*, *POST, and
20 /// OVER_BOSS and those listed here
19}; 21};
20 22
21/** 23/**
diff --git a/src/core/hle/service/cecd/cecd_s.cpp b/src/core/hle/service/cecd/cecd_s.cpp
index bfd821c07..7477b9320 100644
--- a/src/core/hle/service/cecd/cecd_s.cpp
+++ b/src/core/hle/service/cecd/cecd_s.cpp
@@ -8,10 +8,10 @@ namespace Service {
8namespace CECD { 8namespace CECD {
9 9
10// Empty arrays are illegal -- commented out until an entry is added. 10// Empty arrays are illegal -- commented out until an entry is added.
11//const Interface::FunctionInfo FunctionTable[] = { }; 11// const Interface::FunctionInfo FunctionTable[] = { };
12 12
13CECD_S_Interface::CECD_S_Interface() { 13CECD_S_Interface::CECD_S_Interface() {
14 //Register(FunctionTable); 14 // Register(FunctionTable);
15} 15}
16 16
17} // namespace CECD 17} // namespace CECD
diff --git a/src/core/hle/service/cecd/cecd_u.cpp b/src/core/hle/service/cecd/cecd_u.cpp
index be6d4d8f6..4b747de7b 100644
--- a/src/core/hle/service/cecd/cecd_u.cpp
+++ b/src/core/hle/service/cecd/cecd_u.cpp
@@ -9,10 +9,10 @@ namespace Service {
9namespace CECD { 9namespace CECD {
10 10
11static const Interface::FunctionInfo FunctionTable[] = { 11static const Interface::FunctionInfo FunctionTable[] = {
12 {0x000E0000, GetCecStateAbbreviated, "GetCecStateAbbreviated"}, 12 {0x000E0000, GetCecStateAbbreviated, "GetCecStateAbbreviated"},
13 {0x000F0000, GetCecInfoEventHandle, "GetCecInfoEventHandle"}, 13 {0x000F0000, GetCecInfoEventHandle, "GetCecInfoEventHandle"},
14 {0x00100000, GetChangeStateEventHandle, "GetChangeStateEventHandle"}, 14 {0x00100000, GetChangeStateEventHandle, "GetChangeStateEventHandle"},
15 {0x00120104, nullptr, "ReadSavedData"}, 15 {0x00120104, nullptr, "ReadSavedData"},
16}; 16};
17 17
18CECD_U_Interface::CECD_U_Interface() { 18CECD_U_Interface::CECD_U_Interface() {
diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp
index a5dc47322..fe97a69d1 100644
--- a/src/core/hle/service/cfg/cfg.cpp
+++ b/src/core/hle/service/cfg/cfg.cpp
@@ -11,7 +11,6 @@
11 11
12#include "core/file_sys/archive_systemsavedata.h" 12#include "core/file_sys/archive_systemsavedata.h"
13#include "core/file_sys/file_backend.h" 13#include "core/file_sys/file_backend.h"
14#include "core/settings.h"
15#include "core/hle/result.h" 14#include "core/hle/result.h"
16#include "core/hle/service/cfg/cfg.h" 15#include "core/hle/service/cfg/cfg.h"
17#include "core/hle/service/cfg/cfg_i.h" 16#include "core/hle/service/cfg/cfg_i.h"
@@ -19,6 +18,7 @@
19#include "core/hle/service/cfg/cfg_u.h" 18#include "core/hle/service/cfg/cfg_u.h"
20#include "core/hle/service/fs/archive.h" 19#include "core/hle/service/fs/archive.h"
21#include "core/hle/service/service.h" 20#include "core/hle/service/service.h"
21#include "core/settings.h"
22 22
23namespace Service { 23namespace Service {
24namespace CFG { 24namespace CFG {
@@ -33,25 +33,29 @@ namespace {
33 * contains information about the blocks in the file 33 * contains information about the blocks in the file
34 */ 34 */
35struct SaveFileConfig { 35struct SaveFileConfig {
36 u16 total_entries; ///< The total number of set entries in the config file 36 u16 total_entries; ///< The total number of set entries in the config file
37 u16 data_entries_offset; ///< The offset where the data for the blocks start, this is hardcoded to 0x455C as per hardware 37 u16 data_entries_offset; ///< The offset where the data for the blocks start, this is hardcoded
38 SaveConfigBlockEntry block_entries[CONFIG_FILE_MAX_BLOCK_ENTRIES]; ///< The block headers, the maximum possible value is 1479 as per hardware 38 /// to 0x455C as per hardware
39 u32 unknown; ///< This field is unknown, possibly padding, 0 has been observed in hardware 39 SaveConfigBlockEntry block_entries[CONFIG_FILE_MAX_BLOCK_ENTRIES]; ///< The block headers, the
40 /// maximum possible value is
41 /// 1479 as per hardware
42 u32 unknown; ///< This field is unknown, possibly padding, 0 has been observed in hardware
40}; 43};
41static_assert(sizeof(SaveFileConfig) == 0x455C, "SaveFileConfig header must be exactly 0x455C bytes"); 44static_assert(sizeof(SaveFileConfig) == 0x455C,
45 "SaveFileConfig header must be exactly 0x455C bytes");
42 46
43enum ConfigBlockID { 47enum ConfigBlockID {
44 StereoCameraSettingsBlockID = 0x00050005, 48 StereoCameraSettingsBlockID = 0x00050005,
45 SoundOutputModeBlockID = 0x00070001, 49 SoundOutputModeBlockID = 0x00070001,
46 ConsoleUniqueIDBlockID = 0x00090001, 50 ConsoleUniqueIDBlockID = 0x00090001,
47 UsernameBlockID = 0x000A0000, 51 UsernameBlockID = 0x000A0000,
48 BirthdayBlockID = 0x000A0001, 52 BirthdayBlockID = 0x000A0001,
49 LanguageBlockID = 0x000A0002, 53 LanguageBlockID = 0x000A0002,
50 CountryInfoBlockID = 0x000B0000, 54 CountryInfoBlockID = 0x000B0000,
51 CountryNameBlockID = 0x000B0001, 55 CountryNameBlockID = 0x000B0001,
52 StateNameBlockID = 0x000B0002, 56 StateNameBlockID = 0x000B0002,
53 EULAVersionBlockID = 0x000D0000, 57 EULAVersionBlockID = 0x000D0000,
54 ConsoleModelBlockID = 0x000F0004, 58 ConsoleModelBlockID = 0x000F0004,
55}; 59};
56 60
57struct UsernameBlock { 61struct UsernameBlock {
@@ -68,8 +72,8 @@ struct BirthdayBlock {
68static_assert(sizeof(BirthdayBlock) == 2, "BirthdayBlock must be exactly 2 bytes"); 72static_assert(sizeof(BirthdayBlock) == 2, "BirthdayBlock must be exactly 2 bytes");
69 73
70struct ConsoleModelInfo { 74struct ConsoleModelInfo {
71 u8 model; ///< The console model (3DS, 2DS, etc) 75 u8 model; ///< The console model (3DS, 2DS, etc)
72 u8 unknown[3]; ///< Unknown data 76 u8 unknown[3]; ///< Unknown data
73}; 77};
74static_assert(sizeof(ConsoleModelInfo) == 4, "ConsoleModelInfo must be exactly 4 bytes"); 78static_assert(sizeof(ConsoleModelInfo) == 4, "ConsoleModelInfo must be exactly 4 bytes");
75 79
@@ -78,36 +82,36 @@ struct ConsoleCountryInfo {
78 u8 country_code; ///< The country code of the console 82 u8 country_code; ///< The country code of the console
79}; 83};
80static_assert(sizeof(ConsoleCountryInfo) == 4, "ConsoleCountryInfo must be exactly 4 bytes"); 84static_assert(sizeof(ConsoleCountryInfo) == 4, "ConsoleCountryInfo must be exactly 4 bytes");
81
82} 85}
83 86
84static const u64 CFG_SAVE_ID = 0x00010017; 87static const u64 CFG_SAVE_ID = 0x00010017;
85static const u64 CONSOLE_UNIQUE_ID = 0xDEADC0DE; 88static const u64 CONSOLE_UNIQUE_ID = 0xDEADC0DE;
86static const ConsoleModelInfo CONSOLE_MODEL = { NINTENDO_3DS_XL, { 0, 0, 0 } }; 89static const ConsoleModelInfo CONSOLE_MODEL = {NINTENDO_3DS_XL, {0, 0, 0}};
87static const u8 CONSOLE_LANGUAGE = LANGUAGE_EN; 90static const u8 CONSOLE_LANGUAGE = LANGUAGE_EN;
88static const UsernameBlock CONSOLE_USERNAME_BLOCK = { u"CITRA", 0, 0 }; 91static const UsernameBlock CONSOLE_USERNAME_BLOCK = {u"CITRA", 0, 0};
89static const BirthdayBlock PROFILE_BIRTHDAY = { 3, 25 }; // March 25th, 2014 92static const BirthdayBlock PROFILE_BIRTHDAY = {3, 25}; // March 25th, 2014
90static const u8 SOUND_OUTPUT_MODE = SOUND_SURROUND; 93static const u8 SOUND_OUTPUT_MODE = SOUND_SURROUND;
91static const u8 UNITED_STATES_COUNTRY_ID = 49; 94static const u8 UNITED_STATES_COUNTRY_ID = 49;
92/// TODO(Subv): Find what the other bytes are 95/// TODO(Subv): Find what the other bytes are
93static const ConsoleCountryInfo COUNTRY_INFO = { { 0, 0, 0 }, UNITED_STATES_COUNTRY_ID }; 96static const ConsoleCountryInfo COUNTRY_INFO = {{0, 0, 0}, UNITED_STATES_COUNTRY_ID};
94 97
95/** 98/**
96 * TODO(Subv): Find out what this actually is, these values fix some NaN uniforms in some games, 99 * TODO(Subv): Find out what this actually is, these values fix some NaN uniforms in some games,
97 * for example Nintendo Zone 100 * for example Nintendo Zone
98 * Thanks Normmatt for providing this information 101 * Thanks Normmatt for providing this information
99 */ 102 */
100static const std::array<float, 8> STEREO_CAMERA_SETTINGS = {{ 103static const std::array<float, 8> STEREO_CAMERA_SETTINGS = {
101 62.0f, 289.0f, 76.80000305175781f, 46.08000183105469f, 104 {62.0f, 289.0f, 76.80000305175781f, 46.08000183105469f, 10.0f, 5.0f, 55.58000183105469f,
102 10.0f, 5.0f, 55.58000183105469f, 21.56999969482422f 105 21.56999969482422f}};
103}}; 106static_assert(sizeof(STEREO_CAMERA_SETTINGS) == 0x20,
104static_assert(sizeof(STEREO_CAMERA_SETTINGS) == 0x20, "STEREO_CAMERA_SETTINGS must be exactly 0x20 bytes"); 107 "STEREO_CAMERA_SETTINGS must be exactly 0x20 bytes");
105 108
106static const u32 CONFIG_SAVEFILE_SIZE = 0x8000; 109static const u32 CONFIG_SAVEFILE_SIZE = 0x8000;
107static std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer; 110static std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer;
108 111
109static Service::FS::ArchiveHandle cfg_system_save_data_archive; 112static Service::FS::ArchiveHandle cfg_system_save_data_archive;
110static const std::vector<u8> cfg_system_savedata_id = { 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x01, 0x00 }; 113static const std::vector<u8> cfg_system_savedata_id = {0x00, 0x00, 0x00, 0x00,
114 0x17, 0x00, 0x01, 0x00};
111 115
112void GetCountryCodeString(Service::Interface* self) { 116void GetCountryCodeString(Service::Interface* self) {
113 u32* cmd_buff = Kernel::GetCommandBuffer(); 117 u32* cmd_buff = Kernel::GetCommandBuffer();
@@ -115,7 +119,9 @@ void GetCountryCodeString(Service::Interface* self) {
115 119
116 if (country_code_id >= country_codes.size() || 0 == country_codes[country_code_id]) { 120 if (country_code_id >= country_codes.size() || 0 == country_codes[country_code_id]) {
117 LOG_ERROR(Service_CFG, "requested country code id=%d is invalid", country_code_id); 121 LOG_ERROR(Service_CFG, "requested country code id=%d is invalid", country_code_id);
118 cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; 122 cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config,
123 ErrorSummary::WrongArgument, ErrorLevel::Permanent)
124 .raw;
119 return; 125 return;
120 } 126 }
121 127
@@ -139,8 +145,11 @@ void GetCountryCodeID(Service::Interface* self) {
139 } 145 }
140 146
141 if (0 == country_code_id) { 147 if (0 == country_code_id) {
142 LOG_ERROR(Service_CFG, "requested country code name=%c%c is invalid", country_code & 0xff, country_code >> 8); 148 LOG_ERROR(Service_CFG, "requested country code name=%c%c is invalid", country_code & 0xff,
143 cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; 149 country_code >> 8);
150 cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config,
151 ErrorSummary::WrongArgument, ErrorLevel::Permanent)
152 .raw;
144 cmd_buff[2] = 0xFFFF; 153 cmd_buff[2] = 0xFFFF;
145 return; 154 return;
146 } 155 }
@@ -185,8 +194,8 @@ void GetSystemModel(Service::Interface* self) {
185 u32 data; 194 u32 data;
186 195
187 // TODO(Subv): Find out the correct error codes 196 // TODO(Subv): Find out the correct error codes
188 cmd_buff[1] = Service::CFG::GetConfigInfoBlock(0x000F0004, 4, 0x8, 197 cmd_buff[1] =
189 reinterpret_cast<u8*>(&data)).raw; 198 Service::CFG::GetConfigInfoBlock(0x000F0004, 4, 0x8, reinterpret_cast<u8*>(&data)).raw;
190 cmd_buff[2] = data & 0xFF; 199 cmd_buff[2] = data & 0xFF;
191} 200}
192 201
@@ -195,8 +204,8 @@ void GetModelNintendo2DS(Service::Interface* self) {
195 u32 data; 204 u32 data;
196 205
197 // TODO(Subv): Find out the correct error codes 206 // TODO(Subv): Find out the correct error codes
198 cmd_buff[1] = Service::CFG::GetConfigInfoBlock(0x000F0004, 4, 0x8, 207 cmd_buff[1] =
199 reinterpret_cast<u8*>(&data)).raw; 208 Service::CFG::GetConfigInfoBlock(0x000F0004, 4, 0x8, reinterpret_cast<u8*>(&data)).raw;
200 209
201 u8 model = data & 0xFF; 210 u8 model = data & 0xFF;
202 if (model == Service::CFG::NINTENDO_2DS) 211 if (model == Service::CFG::NINTENDO_2DS)
@@ -267,24 +276,29 @@ static ResultVal<void*> GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 fl
267 // Read the header 276 // Read the header
268 SaveFileConfig* config = reinterpret_cast<SaveFileConfig*>(cfg_config_file_buffer.data()); 277 SaveFileConfig* config = reinterpret_cast<SaveFileConfig*>(cfg_config_file_buffer.data());
269 278
270 auto itr = std::find_if(std::begin(config->block_entries), std::end(config->block_entries), 279 auto itr =
271 [&](const SaveConfigBlockEntry& entry) { 280 std::find_if(std::begin(config->block_entries), std::end(config->block_entries),
272 return entry.block_id == block_id; 281 [&](const SaveConfigBlockEntry& entry) { return entry.block_id == block_id; });
273 });
274 282
275 if (itr == std::end(config->block_entries)) { 283 if (itr == std::end(config->block_entries)) {
276 LOG_ERROR(Service_CFG, "Config block 0x%X with flags %u and size %u was not found", block_id, flag, size); 284 LOG_ERROR(Service_CFG, "Config block 0x%X with flags %u and size %u was not found",
277 return ResultCode(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 285 block_id, flag, size);
286 return ResultCode(ErrorDescription::NotFound, ErrorModule::Config,
287 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
278 } 288 }
279 289
280 if ((itr->flags & flag) == 0) { 290 if ((itr->flags & flag) == 0) {
281 LOG_ERROR(Service_CFG, "Invalid flag %u for config block 0x%X with size %u", flag, block_id, size); 291 LOG_ERROR(Service_CFG, "Invalid flag %u for config block 0x%X with size %u", flag, block_id,
282 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 292 size);
293 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::Config,
294 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
283 } 295 }
284 296
285 if (itr->size != size) { 297 if (itr->size != size) {
286 LOG_ERROR(Service_CFG, "Invalid size %u for config block 0x%X with flags %u", size, block_id, flag); 298 LOG_ERROR(Service_CFG, "Invalid size %u for config block 0x%X with flags %u", size,
287 return ResultCode(ErrorDescription::InvalidSize, ErrorModule::Config, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 299 block_id, flag);
300 return ResultCode(ErrorDescription::InvalidSize, ErrorModule::Config,
301 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
288 } 302 }
289 303
290 void* pointer; 304 void* pointer;
@@ -318,7 +332,7 @@ ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* da
318 return ResultCode(-1); // TODO(Subv): Find the right error code 332 return ResultCode(-1); // TODO(Subv): Find the right error code
319 333
320 // Insert the block header with offset 0 for now 334 // Insert the block header with offset 0 for now
321 config->block_entries[config->total_entries] = { block_id, 0, size, flags }; 335 config->block_entries[config->total_entries] = {block_id, 0, size, flags};
322 if (size > 4) { 336 if (size > 4) {
323 u32 offset = config->data_entries_offset; 337 u32 offset = config->data_entries_offset;
324 // Perform a search to locate the next offset for the new data 338 // Perform a search to locate the next offset for the new data
@@ -326,8 +340,7 @@ ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* da
326 for (int i = config->total_entries - 1; i >= 0; --i) { 340 for (int i = config->total_entries - 1; i >= 0; --i) {
327 // Ignore the blocks that don't have a separate data offset 341 // Ignore the blocks that don't have a separate data offset
328 if (config->block_entries[i].size > 4) { 342 if (config->block_entries[i].size > 4) {
329 offset = config->block_entries[i].offset_or_data + 343 offset = config->block_entries[i].offset_or_data + config->block_entries[i].size;
330 config->block_entries[i].size;
331 break; 344 break;
332 } 345 }
333 } 346 }
@@ -336,8 +349,7 @@ ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* da
336 349
337 // Write the data at the new offset 350 // Write the data at the new offset
338 memcpy(&cfg_config_file_buffer[offset], data, size); 351 memcpy(&cfg_config_file_buffer[offset], data, size);
339 } 352 } else {
340 else {
341 // The offset_or_data field in the header contains the data itself if it's 4 bytes or less 353 // The offset_or_data field in the header contains the data itself if it's 4 bytes or less
342 memcpy(&config->block_entries[config->total_entries].offset_or_data, data, size); 354 memcpy(&config->block_entries[config->total_entries].offset_or_data, data, size);
343 } 355 }
@@ -384,28 +396,40 @@ ResultCode FormatConfig() {
384 396
385 // 0x00030001 - Unknown 397 // 0x00030001 - Unknown
386 res = CreateConfigInfoBlk(0x00030001, 0x8, 0xE, zero_buffer); 398 res = CreateConfigInfoBlk(0x00030001, 0x8, 0xE, zero_buffer);
387 if (!res.IsSuccess()) return res; 399 if (!res.IsSuccess())
400 return res;
388 401
389 res = CreateConfigInfoBlk(StereoCameraSettingsBlockID, sizeof(STEREO_CAMERA_SETTINGS), 0xE, STEREO_CAMERA_SETTINGS.data()); 402 res = CreateConfigInfoBlk(StereoCameraSettingsBlockID, sizeof(STEREO_CAMERA_SETTINGS), 0xE,
390 if (!res.IsSuccess()) return res; 403 STEREO_CAMERA_SETTINGS.data());
404 if (!res.IsSuccess())
405 return res;
391 406
392 res = CreateConfigInfoBlk(SoundOutputModeBlockID, sizeof(SOUND_OUTPUT_MODE), 0xE, &SOUND_OUTPUT_MODE); 407 res = CreateConfigInfoBlk(SoundOutputModeBlockID, sizeof(SOUND_OUTPUT_MODE), 0xE,
393 if (!res.IsSuccess()) return res; 408 &SOUND_OUTPUT_MODE);
409 if (!res.IsSuccess())
410 return res;
394 411
395 res = CreateConfigInfoBlk(ConsoleUniqueIDBlockID, sizeof(CONSOLE_UNIQUE_ID), 0xE, &CONSOLE_UNIQUE_ID); 412 res = CreateConfigInfoBlk(ConsoleUniqueIDBlockID, sizeof(CONSOLE_UNIQUE_ID), 0xE,
396 if (!res.IsSuccess()) return res; 413 &CONSOLE_UNIQUE_ID);
414 if (!res.IsSuccess())
415 return res;
397 416
398 res = CreateConfigInfoBlk(UsernameBlockID, sizeof(CONSOLE_USERNAME_BLOCK), 0xE, &CONSOLE_USERNAME_BLOCK); 417 res = CreateConfigInfoBlk(UsernameBlockID, sizeof(CONSOLE_USERNAME_BLOCK), 0xE,
399 if (!res.IsSuccess()) return res; 418 &CONSOLE_USERNAME_BLOCK);
419 if (!res.IsSuccess())
420 return res;
400 421
401 res = CreateConfigInfoBlk(BirthdayBlockID, sizeof(PROFILE_BIRTHDAY), 0xE, &PROFILE_BIRTHDAY); 422 res = CreateConfigInfoBlk(BirthdayBlockID, sizeof(PROFILE_BIRTHDAY), 0xE, &PROFILE_BIRTHDAY);
402 if (!res.IsSuccess()) return res; 423 if (!res.IsSuccess())
424 return res;
403 425
404 res = CreateConfigInfoBlk(LanguageBlockID, sizeof(CONSOLE_LANGUAGE), 0xE, &CONSOLE_LANGUAGE); 426 res = CreateConfigInfoBlk(LanguageBlockID, sizeof(CONSOLE_LANGUAGE), 0xE, &CONSOLE_LANGUAGE);
405 if (!res.IsSuccess()) return res; 427 if (!res.IsSuccess())
428 return res;
406 429
407 res = CreateConfigInfoBlk(CountryInfoBlockID, sizeof(COUNTRY_INFO), 0xE, &COUNTRY_INFO); 430 res = CreateConfigInfoBlk(CountryInfoBlockID, sizeof(COUNTRY_INFO), 0xE, &COUNTRY_INFO);
408 if (!res.IsSuccess()) return res; 431 if (!res.IsSuccess())
432 return res;
409 433
410 u16_le country_name_buffer[16][0x40] = {}; 434 u16_le country_name_buffer[16][0x40] = {};
411 std::u16string region_name = Common::UTF8ToUTF16("Gensokyo"); 435 std::u16string region_name = Common::UTF8ToUTF16("Gensokyo");
@@ -413,34 +437,44 @@ ResultCode FormatConfig() {
413 std::copy(region_name.cbegin(), region_name.cend(), country_name_buffer[i]); 437 std::copy(region_name.cbegin(), region_name.cend(), country_name_buffer[i]);
414 } 438 }
415 // 0x000B0001 - Localized names for the profile Country 439 // 0x000B0001 - Localized names for the profile Country
416 res = CreateConfigInfoBlk(CountryNameBlockID, sizeof(country_name_buffer), 0xE, country_name_buffer); 440 res = CreateConfigInfoBlk(CountryNameBlockID, sizeof(country_name_buffer), 0xE,
417 if (!res.IsSuccess()) return res; 441 country_name_buffer);
442 if (!res.IsSuccess())
443 return res;
418 // 0x000B0002 - Localized names for the profile State/Province 444 // 0x000B0002 - Localized names for the profile State/Province
419 res = CreateConfigInfoBlk(StateNameBlockID, sizeof(country_name_buffer), 0xE, country_name_buffer); 445 res = CreateConfigInfoBlk(StateNameBlockID, sizeof(country_name_buffer), 0xE,
420 if (!res.IsSuccess()) return res; 446 country_name_buffer);
447 if (!res.IsSuccess())
448 return res;
421 449
422 // 0x000B0003 - Unknown, related to country/address (zip code?) 450 // 0x000B0003 - Unknown, related to country/address (zip code?)
423 res = CreateConfigInfoBlk(0x000B0003, 0x4, 0xE, zero_buffer); 451 res = CreateConfigInfoBlk(0x000B0003, 0x4, 0xE, zero_buffer);
424 if (!res.IsSuccess()) return res; 452 if (!res.IsSuccess())
453 return res;
425 454
426 // 0x000C0000 - Unknown 455 // 0x000C0000 - Unknown
427 res = CreateConfigInfoBlk(0x000C0000, 0xC0, 0xE, zero_buffer); 456 res = CreateConfigInfoBlk(0x000C0000, 0xC0, 0xE, zero_buffer);
428 if (!res.IsSuccess()) return res; 457 if (!res.IsSuccess())
458 return res;
429 459
430 // 0x000C0001 - Unknown 460 // 0x000C0001 - Unknown
431 res = CreateConfigInfoBlk(0x000C0001, 0x14, 0xE, zero_buffer); 461 res = CreateConfigInfoBlk(0x000C0001, 0x14, 0xE, zero_buffer);
432 if (!res.IsSuccess()) return res; 462 if (!res.IsSuccess())
463 return res;
433 464
434 // 0x000D0000 - Accepted EULA version 465 // 0x000D0000 - Accepted EULA version
435 res = CreateConfigInfoBlk(EULAVersionBlockID, 0x4, 0xE, zero_buffer); 466 res = CreateConfigInfoBlk(EULAVersionBlockID, 0x4, 0xE, zero_buffer);
436 if (!res.IsSuccess()) return res; 467 if (!res.IsSuccess())
468 return res;
437 469
438 res = CreateConfigInfoBlk(ConsoleModelBlockID, sizeof(CONSOLE_MODEL), 0xC, &CONSOLE_MODEL); 470 res = CreateConfigInfoBlk(ConsoleModelBlockID, sizeof(CONSOLE_MODEL), 0xC, &CONSOLE_MODEL);
439 if (!res.IsSuccess()) return res; 471 if (!res.IsSuccess())
472 return res;
440 473
441 // 0x00170000 - Unknown 474 // 0x00170000 - Unknown
442 res = CreateConfigInfoBlk(0x00170000, 0x4, 0xE, zero_buffer); 475 res = CreateConfigInfoBlk(0x00170000, 0x4, 0xE, zero_buffer);
443 if (!res.IsSuccess()) return res; 476 if (!res.IsSuccess())
477 return res;
444 478
445 // Save the buffer to the file 479 // Save the buffer to the file
446 res = UpdateConfigNANDSavegame(); 480 res = UpdateConfigNANDSavegame();
@@ -452,15 +486,18 @@ ResultCode FormatConfig() {
452ResultCode LoadConfigNANDSaveFile() { 486ResultCode LoadConfigNANDSaveFile() {
453 // Open the SystemSaveData archive 0x00010017 487 // Open the SystemSaveData archive 0x00010017
454 FileSys::Path archive_path(cfg_system_savedata_id); 488 FileSys::Path archive_path(cfg_system_savedata_id);
455 auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); 489 auto archive_result =
490 Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path);
456 491
457 // If the archive didn't exist, create the files inside 492 // If the archive didn't exist, create the files inside
458 if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { 493 if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) {
459 // Format the archive to create the directories 494 // Format the archive to create the directories
460 Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SystemSaveData, FileSys::ArchiveFormatInfo(), archive_path); 495 Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SystemSaveData,
496 FileSys::ArchiveFormatInfo(), archive_path);
461 497
462 // Open it again to get a valid archive now that the folder exists 498 // Open it again to get a valid archive now that the folder exists
463 archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); 499 archive_result =
500 Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path);
464 } 501 }
465 502
466 ASSERT_MSG(archive_result.Succeeded(), "Could not open the CFG SystemSaveData archive!"); 503 ASSERT_MSG(archive_result.Succeeded(), "Could not open the CFG SystemSaveData archive!");
@@ -515,7 +552,7 @@ std::u16string GetUsername() {
515} 552}
516 553
517void SetBirthday(u8 month, u8 day) { 554void SetBirthday(u8 month, u8 day) {
518 BirthdayBlock block = { month, day }; 555 BirthdayBlock block = {month, day};
519 SetConfigInfoBlock(BirthdayBlockID, sizeof(block), 4, &block); 556 SetConfigInfoBlock(BirthdayBlockID, sizeof(block), 4, &block);
520} 557}
521 558
diff --git a/src/core/hle/service/cfg/cfg.h b/src/core/hle/service/cfg/cfg.h
index 18f60f4ca..8cb231d72 100644
--- a/src/core/hle/service/cfg/cfg.h
+++ b/src/core/hle/service/cfg/cfg.h
@@ -40,16 +40,13 @@ enum SystemLanguage {
40 LANGUAGE_TW = 11 40 LANGUAGE_TW = 11
41}; 41};
42 42
43enum SoundOutputMode { 43enum SoundOutputMode { SOUND_MONO = 0, SOUND_STEREO = 1, SOUND_SURROUND = 2 };
44 SOUND_MONO = 0,
45 SOUND_STEREO = 1,
46 SOUND_SURROUND = 2
47};
48 44
49/// Block header in the config savedata file 45/// Block header in the config savedata file
50struct SaveConfigBlockEntry { 46struct SaveConfigBlockEntry {
51 u32 block_id; ///< The id of the current block 47 u32 block_id; ///< The id of the current block
52 u32 offset_or_data; ///< This is the absolute offset to the block data if the size is greater than 4 bytes, otherwise it contains the data itself 48 u32 offset_or_data; ///< This is the absolute offset to the block data if the size is greater
49 /// than 4 bytes, otherwise it contains the data itself
53 u16 size; ///< The size of the block 50 u16 size; ///< The size of the block
54 u16 flags; ///< The flags of the block, possibly used for access control 51 u16 flags; ///< The flags of the block, possibly used for access control
55}; 52};
@@ -244,7 +241,8 @@ ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output);
244ResultCode SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input); 241ResultCode SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input);
245 242
246/** 243/**
247 * Creates a block with the specified id and writes the input data to the cfg savegame buffer in memory. 244 * Creates a block with the specified id and writes the input data to the cfg savegame buffer in
245 * memory.
248 * The config savegame file in the filesystem is not updated. 246 * The config savegame file in the filesystem is not updated.
249 * @param block_id The id of the block we want to create 247 * @param block_id The id of the block we want to create
250 * @param size The size of the block we want to create 248 * @param size The size of the block we want to create
diff --git a/src/core/hle/service/cfg/cfg_i.cpp b/src/core/hle/service/cfg/cfg_i.cpp
index 8b0db785f..2ff52c8b8 100644
--- a/src/core/hle/service/cfg/cfg_i.cpp
+++ b/src/core/hle/service/cfg/cfg_i.cpp
@@ -10,49 +10,49 @@ namespace CFG {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 // cfg common 12 // cfg common
13 {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"}, 13 {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"},
14 {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"}, 14 {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"},
15 {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"}, 15 {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"},
16 {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"}, 16 {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"},
17 {0x00050000, GetSystemModel, "GetSystemModel"}, 17 {0x00050000, GetSystemModel, "GetSystemModel"},
18 {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"}, 18 {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"},
19 {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, 19 {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"},
20 {0x00080080, nullptr, "GoThroughTable"}, 20 {0x00080080, nullptr, "GoThroughTable"},
21 {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, 21 {0x00090040, GetCountryCodeString, "GetCountryCodeString"},
22 {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, 22 {0x000A0040, GetCountryCodeID, "GetCountryCodeID"},
23 // cfg:i 23 // cfg:i
24 {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, 24 {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"},
25 {0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, 25 {0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"},
26 {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, 26 {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
27 {0x04040042, nullptr, "GetLocalFriendCodeSeedData"}, 27 {0x04040042, nullptr, "GetLocalFriendCodeSeedData"},
28 {0x04050000, nullptr, "GetLocalFriendCodeSeed"}, 28 {0x04050000, nullptr, "GetLocalFriendCodeSeed"},
29 {0x04060000, SecureInfoGetRegion, "SecureInfoGetRegion"}, 29 {0x04060000, SecureInfoGetRegion, "SecureInfoGetRegion"},
30 {0x04070000, nullptr, "SecureInfoGetByte101"}, 30 {0x04070000, nullptr, "SecureInfoGetByte101"},
31 {0x04080042, nullptr, "SecureInfoGetSerialNo"}, 31 {0x04080042, nullptr, "SecureInfoGetSerialNo"},
32 {0x04090000, nullptr, "UpdateConfigBlk00040003"}, 32 {0x04090000, nullptr, "UpdateConfigBlk00040003"},
33 {0x08010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, 33 {0x08010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"},
34 {0x08020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, 34 {0x08020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"},
35 {0x08030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, 35 {0x08030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
36 {0x080400C2, nullptr, "CreateConfigInfoBlk"}, 36 {0x080400C2, nullptr, "CreateConfigInfoBlk"},
37 {0x08050000, nullptr, "DeleteConfigNANDSavefile"}, 37 {0x08050000, nullptr, "DeleteConfigNANDSavefile"},
38 {0x08060000, FormatConfig, "FormatConfig"}, 38 {0x08060000, FormatConfig, "FormatConfig"},
39 {0x08080000, nullptr, "UpdateConfigBlk1"}, 39 {0x08080000, nullptr, "UpdateConfigBlk1"},
40 {0x08090000, nullptr, "UpdateConfigBlk2"}, 40 {0x08090000, nullptr, "UpdateConfigBlk2"},
41 {0x080A0000, nullptr, "UpdateConfigBlk3"}, 41 {0x080A0000, nullptr, "UpdateConfigBlk3"},
42 {0x080B0082, nullptr, "SetGetLocalFriendCodeSeedData"}, 42 {0x080B0082, nullptr, "SetGetLocalFriendCodeSeedData"},
43 {0x080C0042, nullptr, "SetLocalFriendCodeSeedSignature"}, 43 {0x080C0042, nullptr, "SetLocalFriendCodeSeedSignature"},
44 {0x080D0000, nullptr, "DeleteCreateNANDLocalFriendCodeSeed"}, 44 {0x080D0000, nullptr, "DeleteCreateNANDLocalFriendCodeSeed"},
45 {0x080E0000, nullptr, "VerifySigLocalFriendCodeSeed"}, 45 {0x080E0000, nullptr, "VerifySigLocalFriendCodeSeed"},
46 {0x080F0042, nullptr, "GetLocalFriendCodeSeedData"}, 46 {0x080F0042, nullptr, "GetLocalFriendCodeSeedData"},
47 {0x08100000, nullptr, "GetLocalFriendCodeSeed"}, 47 {0x08100000, nullptr, "GetLocalFriendCodeSeed"},
48 {0x08110084, nullptr, "SetSecureInfo"}, 48 {0x08110084, nullptr, "SetSecureInfo"},
49 {0x08120000, nullptr, "DeleteCreateNANDSecureInfo"}, 49 {0x08120000, nullptr, "DeleteCreateNANDSecureInfo"},
50 {0x08130000, nullptr, "VerifySigSecureInfo"}, 50 {0x08130000, nullptr, "VerifySigSecureInfo"},
51 {0x08140042, nullptr, "SecureInfoGetData"}, 51 {0x08140042, nullptr, "SecureInfoGetData"},
52 {0x08150042, nullptr, "SecureInfoGetSignature"}, 52 {0x08150042, nullptr, "SecureInfoGetSignature"},
53 {0x08160000, SecureInfoGetRegion, "SecureInfoGetRegion"}, 53 {0x08160000, SecureInfoGetRegion, "SecureInfoGetRegion"},
54 {0x08170000, nullptr, "SecureInfoGetByte101"}, 54 {0x08170000, nullptr, "SecureInfoGetByte101"},
55 {0x08180042, nullptr, "SecureInfoGetSerialNo"}, 55 {0x08180042, nullptr, "SecureInfoGetSerialNo"},
56}; 56};
57 57
58CFG_I_Interface::CFG_I_Interface() { 58CFG_I_Interface::CFG_I_Interface() {
diff --git a/src/core/hle/service/cfg/cfg_s.cpp b/src/core/hle/service/cfg/cfg_s.cpp
index 12b458783..eed26dec7 100644
--- a/src/core/hle/service/cfg/cfg_s.cpp
+++ b/src/core/hle/service/cfg/cfg_s.cpp
@@ -10,26 +10,26 @@ namespace CFG {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 // cfg common 12 // cfg common
13 {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"}, 13 {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"},
14 {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"}, 14 {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"},
15 {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"}, 15 {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"},
16 {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"}, 16 {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"},
17 {0x00050000, GetSystemModel, "GetSystemModel"}, 17 {0x00050000, GetSystemModel, "GetSystemModel"},
18 {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"}, 18 {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"},
19 {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, 19 {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"},
20 {0x00080080, nullptr, "GoThroughTable"}, 20 {0x00080080, nullptr, "GoThroughTable"},
21 {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, 21 {0x00090040, GetCountryCodeString, "GetCountryCodeString"},
22 {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, 22 {0x000A0040, GetCountryCodeID, "GetCountryCodeID"},
23 // cfg:s 23 // cfg:s
24 {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"}, 24 {0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"},
25 {0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"}, 25 {0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"},
26 {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"}, 26 {0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
27 {0x04040042, nullptr, "GetLocalFriendCodeSeedData"}, 27 {0x04040042, nullptr, "GetLocalFriendCodeSeedData"},
28 {0x04050000, nullptr, "GetLocalFriendCodeSeed"}, 28 {0x04050000, nullptr, "GetLocalFriendCodeSeed"},
29 {0x04060000, nullptr, "SecureInfoGetRegion"}, 29 {0x04060000, nullptr, "SecureInfoGetRegion"},
30 {0x04070000, nullptr, "SecureInfoGetByte101"}, 30 {0x04070000, nullptr, "SecureInfoGetByte101"},
31 {0x04080042, nullptr, "SecureInfoGetSerialNo"}, 31 {0x04080042, nullptr, "SecureInfoGetSerialNo"},
32 {0x04090000, nullptr, "UpdateConfigBlk00040003"}, 32 {0x04090000, nullptr, "UpdateConfigBlk00040003"},
33}; 33};
34 34
35CFG_S_Interface::CFG_S_Interface() { 35CFG_S_Interface::CFG_S_Interface() {
diff --git a/src/core/hle/service/cfg/cfg_u.cpp b/src/core/hle/service/cfg/cfg_u.cpp
index 606f7b2eb..f28217134 100644
--- a/src/core/hle/service/cfg/cfg_u.cpp
+++ b/src/core/hle/service/cfg/cfg_u.cpp
@@ -10,16 +10,16 @@ namespace CFG {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 // cfg common 12 // cfg common
13 {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"}, 13 {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"},
14 {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"}, 14 {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"},
15 {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"}, 15 {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"},
16 {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"}, 16 {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"},
17 {0x00050000, GetSystemModel, "GetSystemModel"}, 17 {0x00050000, GetSystemModel, "GetSystemModel"},
18 {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"}, 18 {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"},
19 {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"}, 19 {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"},
20 {0x00080080, nullptr, "GoThroughTable"}, 20 {0x00080080, nullptr, "GoThroughTable"},
21 {0x00090040, GetCountryCodeString, "GetCountryCodeString"}, 21 {0x00090040, GetCountryCodeString, "GetCountryCodeString"},
22 {0x000A0040, GetCountryCodeID, "GetCountryCodeID"}, 22 {0x000A0040, GetCountryCodeID, "GetCountryCodeID"},
23}; 23};
24 24
25CFG_U_Interface::CFG_U_Interface() { 25CFG_U_Interface::CFG_U_Interface() {
diff --git a/src/core/hle/service/csnd_snd.cpp b/src/core/hle/service/csnd_snd.cpp
index 913c8dc09..e777ea9d6 100644
--- a/src/core/hle/service/csnd_snd.cpp
+++ b/src/core/hle/service/csnd_snd.cpp
@@ -2,12 +2,12 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/hle/service/csnd_snd.h"
5#include <cstring> 6#include <cstring>
6#include "common/alignment.h" 7#include "common/alignment.h"
7#include "core/hle/hle.h" 8#include "core/hle/hle.h"
8#include "core/hle/kernel/mutex.h" 9#include "core/hle/kernel/mutex.h"
9#include "core/hle/kernel/shared_memory.h" 10#include "core/hle/kernel/shared_memory.h"
10#include "core/hle/service/csnd_snd.h"
11 11
12//////////////////////////////////////////////////////////////////////////////////////////////////// 12////////////////////////////////////////////////////////////////////////////////////////////////////
13// Namespace CSND_SND 13// Namespace CSND_SND
@@ -15,18 +15,18 @@
15namespace CSND_SND { 15namespace CSND_SND {
16 16
17const Interface::FunctionInfo FunctionTable[] = { 17const Interface::FunctionInfo FunctionTable[] = {
18 {0x00010140, Initialize, "Initialize"}, 18 {0x00010140, Initialize, "Initialize"},
19 {0x00020000, Shutdown, "Shutdown"}, 19 {0x00020000, Shutdown, "Shutdown"},
20 {0x00030040, ExecuteType0Commands, "ExecuteType0Commands"}, 20 {0x00030040, ExecuteType0Commands, "ExecuteType0Commands"},
21 {0x00040080, nullptr, "ExecuteType1Commands"}, 21 {0x00040080, nullptr, "ExecuteType1Commands"},
22 {0x00050000, AcquireSoundChannels, "AcquireSoundChannels"}, 22 {0x00050000, AcquireSoundChannels, "AcquireSoundChannels"},
23 {0x00060000, nullptr, "ReleaseSoundChannels"}, 23 {0x00060000, nullptr, "ReleaseSoundChannels"},
24 {0x00070000, nullptr, "AcquireCaptureDevice"}, 24 {0x00070000, nullptr, "AcquireCaptureDevice"},
25 {0x00080040, nullptr, "ReleaseCaptureDevice"}, 25 {0x00080040, nullptr, "ReleaseCaptureDevice"},
26 {0x00090082, nullptr, "FlushDataCache"}, 26 {0x00090082, nullptr, "FlushDataCache"},
27 {0x000A0082, nullptr, "StoreDataCache"}, 27 {0x000A0082, nullptr, "StoreDataCache"},
28 {0x000B0082, nullptr, "InvalidateDataCache"}, 28 {0x000B0082, nullptr, "InvalidateDataCache"},
29 {0x000C0000, nullptr, "Reset"}, 29 {0x000C0000, nullptr, "Reset"},
30}; 30};
31 31
32//////////////////////////////////////////////////////////////////////////////////////////////////// 32////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -44,9 +44,9 @@ void Initialize(Service::Interface* self) {
44 44
45 u32 size = Common::AlignUp(cmd_buff[1], Memory::PAGE_SIZE); 45 u32 size = Common::AlignUp(cmd_buff[1], Memory::PAGE_SIZE);
46 using Kernel::MemoryPermission; 46 using Kernel::MemoryPermission;
47 shared_memory = Kernel::SharedMemory::Create(nullptr, size, 47 shared_memory = Kernel::SharedMemory::Create(nullptr, size, MemoryPermission::ReadWrite,
48 MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 48 MemoryPermission::ReadWrite, 0,
49 0, Kernel::MemoryRegion::BASE, "CSND:SharedMemory"); 49 Kernel::MemoryRegion::BASE, "CSND:SharedMemory");
50 50
51 mutex = Kernel::Mutex::Create(false); 51 mutex = Kernel::Mutex::Create(false);
52 52
@@ -58,7 +58,7 @@ void Initialize(Service::Interface* self) {
58 58
59void ExecuteType0Commands(Service::Interface* self) { 59void ExecuteType0Commands(Service::Interface* self) {
60 u32* const cmd_buff = Kernel::GetCommandBuffer(); 60 u32* const cmd_buff = Kernel::GetCommandBuffer();
61 u8* const ptr = shared_memory->GetPointer(cmd_buff[1]); 61 u8* const ptr = shared_memory->GetPointer(cmd_buff[1]);
62 62
63 if (shared_memory != nullptr && ptr != nullptr) { 63 if (shared_memory != nullptr && ptr != nullptr) {
64 Type0Command command; 64 Type0Command command;
diff --git a/src/core/hle/service/csnd_snd.h b/src/core/hle/service/csnd_snd.h
index e861f3327..a146d116b 100644
--- a/src/core/hle/service/csnd_snd.h
+++ b/src/core/hle/service/csnd_snd.h
@@ -25,7 +25,7 @@ struct Type0Command {
25 u32 command_id; 25 u32 command_id;
26 u32 finished; 26 u32 finished;
27 u32 flags; 27 u32 flags;
28 u8 parameters[20]; 28 u8 parameters[20];
29}; 29};
30 30
31void Initialize(Service::Interface* self); 31void Initialize(Service::Interface* self);
diff --git a/src/core/hle/service/dlp/dlp.cpp b/src/core/hle/service/dlp/dlp.cpp
index 7c8db794b..fd124e819 100644
--- a/src/core/hle/service/dlp/dlp.cpp
+++ b/src/core/hle/service/dlp/dlp.cpp
@@ -2,11 +2,11 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/hle/service/service.h"
6#include "core/hle/service/dlp/dlp.h" 5#include "core/hle/service/dlp/dlp.h"
7#include "core/hle/service/dlp/dlp_clnt.h" 6#include "core/hle/service/dlp/dlp_clnt.h"
8#include "core/hle/service/dlp/dlp_fkcl.h" 7#include "core/hle/service/dlp/dlp_fkcl.h"
9#include "core/hle/service/dlp/dlp_srvr.h" 8#include "core/hle/service/dlp/dlp_srvr.h"
9#include "core/hle/service/service.h"
10 10
11namespace Service { 11namespace Service {
12namespace DLP { 12namespace DLP {
diff --git a/src/core/hle/service/dlp/dlp_clnt.cpp b/src/core/hle/service/dlp/dlp_clnt.cpp
index 0b31d47df..56f934b3f 100644
--- a/src/core/hle/service/dlp/dlp_clnt.cpp
+++ b/src/core/hle/service/dlp/dlp_clnt.cpp
@@ -8,8 +8,7 @@ namespace Service {
8namespace DLP { 8namespace DLP {
9 9
10const Interface::FunctionInfo FunctionTable[] = { 10const Interface::FunctionInfo FunctionTable[] = {
11 {0x000100C3, nullptr, "Initialize"}, 11 {0x000100C3, nullptr, "Initialize"}, {0x00110000, nullptr, "GetWirelessRebootPassphrase"},
12 {0x00110000, nullptr, "GetWirelessRebootPassphrase"},
13}; 12};
14 13
15DLP_CLNT_Interface::DLP_CLNT_Interface() { 14DLP_CLNT_Interface::DLP_CLNT_Interface() {
diff --git a/src/core/hle/service/dlp/dlp_fkcl.cpp b/src/core/hle/service/dlp/dlp_fkcl.cpp
index a845260e5..29b9d52e0 100644
--- a/src/core/hle/service/dlp/dlp_fkcl.cpp
+++ b/src/core/hle/service/dlp/dlp_fkcl.cpp
@@ -8,8 +8,7 @@ namespace Service {
8namespace DLP { 8namespace DLP {
9 9
10const Interface::FunctionInfo FunctionTable[] = { 10const Interface::FunctionInfo FunctionTable[] = {
11 {0x00010083, nullptr, "Initialize"}, 11 {0x00010083, nullptr, "Initialize"}, {0x000F0000, nullptr, "GetWirelessRebootPassphrase"},
12 {0x000F0000, nullptr, "GetWirelessRebootPassphrase"},
13}; 12};
14 13
15DLP_FKCL_Interface::DLP_FKCL_Interface() { 14DLP_FKCL_Interface::DLP_FKCL_Interface() {
diff --git a/src/core/hle/service/dlp/dlp_srvr.cpp b/src/core/hle/service/dlp/dlp_srvr.cpp
index da9b30f56..113f6a79f 100644
--- a/src/core/hle/service/dlp/dlp_srvr.cpp
+++ b/src/core/hle/service/dlp/dlp_srvr.cpp
@@ -2,10 +2,10 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/hle/service/dlp/dlp_srvr.h"
5#include "common/common_types.h" 6#include "common/common_types.h"
6#include "common/logging/log.h" 7#include "common/logging/log.h"
7#include "core/hle/result.h" 8#include "core/hle/result.h"
8#include "core/hle/service/dlp/dlp_srvr.h"
9 9
10namespace Service { 10namespace Service {
11namespace DLP { 11namespace DLP {
@@ -20,10 +20,10 @@ static void unk_0x000E0040(Interface* self) {
20} 20}
21 21
22const Interface::FunctionInfo FunctionTable[] = { 22const Interface::FunctionInfo FunctionTable[] = {
23 {0x00010183, nullptr, "Initialize"}, 23 {0x00010183, nullptr, "Initialize"},
24 {0x00020000, nullptr, "Finalize"}, 24 {0x00020000, nullptr, "Finalize"},
25 {0x000800C0, nullptr, "SendWirelessRebootPassphrase"}, 25 {0x000800C0, nullptr, "SendWirelessRebootPassphrase"},
26 {0x000E0040, unk_0x000E0040, "unk_0x000E0040"}, 26 {0x000E0040, unk_0x000E0040, "unk_0x000E0040"},
27}; 27};
28 28
29DLP_SRVR_Interface::DLP_SRVR_Interface() { 29DLP_SRVR_Interface::DLP_SRVR_Interface() {
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp
index c8aadd9db..70e92c30c 100644
--- a/src/core/hle/service/dsp_dsp.cpp
+++ b/src/core/hle/service/dsp_dsp.cpp
@@ -23,9 +23,7 @@ namespace DSP_DSP {
23static Kernel::SharedPtr<Kernel::Event> semaphore_event; 23static Kernel::SharedPtr<Kernel::Event> semaphore_event;
24 24
25/// There are three types of interrupts 25/// There are three types of interrupts
26enum class InterruptType { 26enum class InterruptType { Zero, One, Pipe };
27 Zero, One, Pipe
28};
29constexpr size_t NUM_INTERRUPT_TYPE = 3; 27constexpr size_t NUM_INTERRUPT_TYPE = 3;
30 28
31class InterruptEvents final { 29class InterruptEvents final {
@@ -57,9 +55,8 @@ public:
57 // Actual service implementation only has 6 'slots' for interrupts. 55 // Actual service implementation only has 6 'slots' for interrupts.
58 constexpr size_t max_number_of_interrupt_events = 6; 56 constexpr size_t max_number_of_interrupt_events = 6;
59 57
60 size_t number = std::count_if(pipe.begin(), pipe.end(), [](const auto& evt) { 58 size_t number =
61 return evt != nullptr; 59 std::count_if(pipe.begin(), pipe.end(), [](const auto& evt) { return evt != nullptr; });
62 });
63 60
64 if (zero != nullptr) 61 if (zero != nullptr)
65 number++; 62 number++;
@@ -105,7 +102,8 @@ static void ConvertProcessAddressFromDspDram(Service::Interface* self) {
105 cmd_buff[0] = IPC::MakeHeader(0xC, 2, 0); 102 cmd_buff[0] = IPC::MakeHeader(0xC, 2, 0);
106 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 103 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
107 104
108 // TODO(merry): There is a per-region offset missing in this calculation (that seems to be always zero). 105 // TODO(merry): There is a per-region offset missing in this calculation (that seems to be
106 // always zero).
109 cmd_buff[2] = (addr << 1) + (Memory::DSP_RAM_VADDR + 0x40000); 107 cmd_buff[2] = (addr << 1) + (Memory::DSP_RAM_VADDR + 0x40000);
110 108
111 LOG_DEBUG(Service_DSP, "addr=0x%08X", addr); 109 LOG_DEBUG(Service_DSP, "addr=0x%08X", addr);
@@ -126,15 +124,15 @@ static void ConvertProcessAddressFromDspDram(Service::Interface* self) {
126static void LoadComponent(Service::Interface* self) { 124static void LoadComponent(Service::Interface* self) {
127 u32* cmd_buff = Kernel::GetCommandBuffer(); 125 u32* cmd_buff = Kernel::GetCommandBuffer();
128 126
129 u32 size = cmd_buff[1]; 127 u32 size = cmd_buff[1];
130 u32 prog_mask = cmd_buff[2]; 128 u32 prog_mask = cmd_buff[2];
131 u32 data_mask = cmd_buff[3]; 129 u32 data_mask = cmd_buff[3];
132 u32 desc = cmd_buff[4]; 130 u32 desc = cmd_buff[4];
133 u32 buffer = cmd_buff[5]; 131 u32 buffer = cmd_buff[5];
134 132
135 cmd_buff[0] = IPC::MakeHeader(0x11, 2, 2); 133 cmd_buff[0] = IPC::MakeHeader(0x11, 2, 2);
136 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 134 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
137 cmd_buff[2] = 1; // Pretend that we actually loaded the DSP firmware 135 cmd_buff[2] = 1; // Pretend that we actually loaded the DSP firmware
138 cmd_buff[3] = desc; 136 cmd_buff[3] = desc;
139 cmd_buff[4] = buffer; 137 cmd_buff[4] = buffer;
140 138
@@ -145,12 +143,15 @@ static void LoadComponent(Service::Interface* self) {
145 std::vector<u8> component_data(size); 143 std::vector<u8> component_data(size);
146 Memory::ReadBlock(buffer, component_data.data(), component_data.size()); 144 Memory::ReadBlock(buffer, component_data.data(), component_data.size());
147 145
148 LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64, Common::ComputeHash64(component_data.data(), component_data.size())); 146 LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64,
147 Common::ComputeHash64(component_data.data(), component_data.size()));
149 // Some versions of the firmware have the location of DSP structures listed here. 148 // Some versions of the firmware have the location of DSP structures listed here.
150 ASSERT(size > 0x37C); 149 ASSERT(size > 0x37C);
151 LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64, Common::ComputeHash64(component_data.data() + 0x340, 60)); 150 LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64,
151 Common::ComputeHash64(component_data.data() + 0x340, 60));
152 152
153 LOG_WARNING(Service_DSP, "(STUBBED) called size=0x%X, prog_mask=0x%08X, data_mask=0x%08X, buffer=0x%08X", 153 LOG_WARNING(Service_DSP,
154 "(STUBBED) called size=0x%X, prog_mask=0x%08X, data_mask=0x%08X, buffer=0x%08X",
154 size, prog_mask, data_mask, buffer); 155 size, prog_mask, data_mask, buffer);
155} 156}
156 157
@@ -187,13 +188,14 @@ static void GetSemaphoreEventHandle(Service::Interface* self) {
187static void FlushDataCache(Service::Interface* self) { 188static void FlushDataCache(Service::Interface* self) {
188 u32* cmd_buff = Kernel::GetCommandBuffer(); 189 u32* cmd_buff = Kernel::GetCommandBuffer();
189 u32 address = cmd_buff[1]; 190 u32 address = cmd_buff[1];
190 u32 size = cmd_buff[2]; 191 u32 size = cmd_buff[2];
191 u32 process = cmd_buff[4]; 192 u32 process = cmd_buff[4];
192 193
193 cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0); 194 cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0);
194 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 195 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
195 196
196 LOG_TRACE(Service_DSP, "called address=0x%08X, size=0x%X, process=0x%08X", address, size, process); 197 LOG_TRACE(Service_DSP, "called address=0x%08X, size=0x%X, process=0x%08X", address, size,
198 process);
197} 199}
198 200
199/** 201/**
@@ -224,23 +226,29 @@ static void RegisterInterruptEvents(Service::Interface* self) {
224 auto evt = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]); 226 auto evt = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]);
225 227
226 if (!evt) { 228 if (!evt) {
227 LOG_INFO(Service_DSP, "Invalid event handle! type=%u, pipe=%u, event_handle=0x%08X", type_index, pipe_index, event_handle); 229 LOG_INFO(Service_DSP, "Invalid event handle! type=%u, pipe=%u, event_handle=0x%08X",
230 type_index, pipe_index, event_handle);
228 ASSERT(false); // TODO: This should really be handled at an IPC translation layer. 231 ASSERT(false); // TODO: This should really be handled at an IPC translation layer.
229 } 232 }
230 233
231 if (interrupt_events.HasTooManyEventsRegistered()) { 234 if (interrupt_events.HasTooManyEventsRegistered()) {
232 LOG_INFO(Service_DSP, "Ran out of space to register interrupts (Attempted to register type=%u, pipe=%u, event_handle=0x%08X)", 235 LOG_INFO(Service_DSP, "Ran out of space to register interrupts (Attempted to register "
236 "type=%u, pipe=%u, event_handle=0x%08X)",
233 type_index, pipe_index, event_handle); 237 type_index, pipe_index, event_handle);
234 cmd_buff[1] = ResultCode(ErrorDescription::InvalidResultValue, ErrorModule::DSP, ErrorSummary::OutOfResource, ErrorLevel::Status).raw; 238 cmd_buff[1] = ResultCode(ErrorDescription::InvalidResultValue, ErrorModule::DSP,
239 ErrorSummary::OutOfResource, ErrorLevel::Status)
240 .raw;
235 return; 241 return;
236 } 242 }
237 243
238 interrupt_events.Get(type, pipe) = evt; 244 interrupt_events.Get(type, pipe) = evt;
239 LOG_INFO(Service_DSP, "Registered type=%u, pipe=%u, event_handle=0x%08X", type_index, pipe_index, event_handle); 245 LOG_INFO(Service_DSP, "Registered type=%u, pipe=%u, event_handle=0x%08X", type_index,
246 pipe_index, event_handle);
240 cmd_buff[1] = RESULT_SUCCESS.raw; 247 cmd_buff[1] = RESULT_SUCCESS.raw;
241 } else { 248 } else {
242 interrupt_events.Get(type, pipe) = nullptr; 249 interrupt_events.Get(type, pipe) = nullptr;
243 LOG_INFO(Service_DSP, "Unregistered interrupt=%u, channel=%u, event_handle=0x%08X", type_index, pipe_index, event_handle); 250 LOG_INFO(Service_DSP, "Unregistered interrupt=%u, channel=%u, event_handle=0x%08X",
251 type_index, pipe_index, event_handle);
244 cmd_buff[1] = RESULT_SUCCESS.raw; 252 cmd_buff[1] = RESULT_SUCCESS.raw;
245 } 253 }
246} 254}
@@ -282,13 +290,18 @@ static void WriteProcessPipe(Service::Interface* self) {
282 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); 290 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index);
283 291
284 if (IPC::StaticBufferDesc(size, 1) != cmd_buff[3]) { 292 if (IPC::StaticBufferDesc(size, 1) != cmd_buff[3]) {
285 LOG_ERROR(Service_DSP, "IPC static buffer descriptor failed validation (0x%X). pipe=%u, size=0x%X, buffer=0x%08X", cmd_buff[3], pipe_index, size, buffer); 293 LOG_ERROR(Service_DSP, "IPC static buffer descriptor failed validation (0x%X). pipe=%u, "
294 "size=0x%X, buffer=0x%08X",
295 cmd_buff[3], pipe_index, size, buffer);
286 cmd_buff[0] = IPC::MakeHeader(0, 1, 0); 296 cmd_buff[0] = IPC::MakeHeader(0, 1, 0);
287 cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; 297 cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS,
298 ErrorSummary::WrongArgument, ErrorLevel::Permanent)
299 .raw;
288 return; 300 return;
289 } 301 }
290 302
291 ASSERT_MSG(Memory::IsValidVirtualAddress(buffer), "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer); 303 ASSERT_MSG(Memory::IsValidVirtualAddress(buffer),
304 "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer);
292 305
293 std::vector<u8> message(size); 306 std::vector<u8> message(size);
294 for (u32 i = 0; i < size; i++) { 307 for (u32 i = 0; i < size; i++) {
@@ -327,7 +340,9 @@ static void ReadPipeIfPossible(Service::Interface* self) {
327 340
328 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); 341 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index);
329 342
330 ASSERT_MSG(Memory::IsValidVirtualAddress(addr), "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr); 343 ASSERT_MSG(Memory::IsValidVirtualAddress(addr),
344 "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown,
345 size, addr);
331 346
332 cmd_buff[0] = IPC::MakeHeader(0x10, 1, 2); 347 cmd_buff[0] = IPC::MakeHeader(0x10, 1, 2);
333 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 348 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
@@ -343,7 +358,9 @@ static void ReadPipeIfPossible(Service::Interface* self) {
343 cmd_buff[3] = IPC::StaticBufferDesc(size, 0); 358 cmd_buff[3] = IPC::StaticBufferDesc(size, 0);
344 cmd_buff[4] = addr; 359 cmd_buff[4] = addr;
345 360
346 LOG_DEBUG(Service_DSP, "pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X", pipe_index, unknown, size, addr, cmd_buff[2]); 361 LOG_DEBUG(Service_DSP,
362 "pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X",
363 pipe_index, unknown, size, addr, cmd_buff[2]);
347} 364}
348 365
349/** 366/**
@@ -367,7 +384,9 @@ static void ReadPipe(Service::Interface* self) {
367 384
368 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); 385 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index);
369 386
370 ASSERT_MSG(Memory::IsValidVirtualAddress(addr), "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr); 387 ASSERT_MSG(Memory::IsValidVirtualAddress(addr),
388 "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown,
389 size, addr);
371 390
372 if (DSP::HLE::GetPipeReadableSize(pipe) >= size) { 391 if (DSP::HLE::GetPipeReadableSize(pipe) >= size) {
373 std::vector<u8> response = DSP::HLE::PipeRead(pipe, size); 392 std::vector<u8> response = DSP::HLE::PipeRead(pipe, size);
@@ -384,7 +403,9 @@ static void ReadPipe(Service::Interface* self) {
384 UNREACHABLE(); 403 UNREACHABLE();
385 } 404 }
386 405
387 LOG_DEBUG(Service_DSP, "pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X", pipe_index, unknown, size, addr, cmd_buff[2]); 406 LOG_DEBUG(Service_DSP,
407 "pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X",
408 pipe_index, unknown, size, addr, cmd_buff[2]);
388} 409}
389 410
390/** 411/**
@@ -408,7 +429,8 @@ static void GetPipeReadableSize(Service::Interface* self) {
408 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 429 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
409 cmd_buff[2] = static_cast<u32>(DSP::HLE::GetPipeReadableSize(pipe)); 430 cmd_buff[2] = static_cast<u32>(DSP::HLE::GetPipeReadableSize(pipe));
410 431
411 LOG_DEBUG(Service_DSP, "pipe=%u, unknown=0x%08X, return cmd_buff[2]=0x%08X", pipe_index, unknown, cmd_buff[2]); 432 LOG_DEBUG(Service_DSP, "pipe=%u, unknown=0x%08X, return cmd_buff[2]=0x%08X", pipe_index,
433 unknown, cmd_buff[2]);
412} 434}
413 435
414/** 436/**
@@ -443,7 +465,7 @@ static void GetHeadphoneStatus(Service::Interface* self) {
443 465
444 cmd_buff[0] = IPC::MakeHeader(0x1F, 2, 0); 466 cmd_buff[0] = IPC::MakeHeader(0x1F, 2, 0);
445 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 467 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
446 cmd_buff[2] = 0; // Not using headphones 468 cmd_buff[2] = 0; // Not using headphones
447 469
448 LOG_DEBUG(Service_DSP, "called"); 470 LOG_DEBUG(Service_DSP, "called");
449} 471}
@@ -466,7 +488,8 @@ static void RecvData(Service::Interface* self) {
466 488
467 ASSERT_MSG(register_number == 0, "Unknown register_number %u", register_number); 489 ASSERT_MSG(register_number == 0, "Unknown register_number %u", register_number);
468 490
469 // Application reads this after requesting DSP shutdown, to verify the DSP has indeed shutdown or slept. 491 // Application reads this after requesting DSP shutdown, to verify the DSP has indeed shutdown
492 // or slept.
470 493
471 cmd_buff[0] = IPC::MakeHeader(0x1, 2, 0); 494 cmd_buff[0] = IPC::MakeHeader(0x1, 2, 0);
472 cmd_buff[1] = RESULT_SUCCESS.raw; 495 cmd_buff[1] = RESULT_SUCCESS.raw;
@@ -512,39 +535,39 @@ static void RecvDataIsReady(Service::Interface* self) {
512} 535}
513 536
514const Interface::FunctionInfo FunctionTable[] = { 537const Interface::FunctionInfo FunctionTable[] = {
515 {0x00010040, RecvData, "RecvData"}, 538 {0x00010040, RecvData, "RecvData"},
516 {0x00020040, RecvDataIsReady, "RecvDataIsReady"}, 539 {0x00020040, RecvDataIsReady, "RecvDataIsReady"},
517 {0x00030080, nullptr, "SendData"}, 540 {0x00030080, nullptr, "SendData"},
518 {0x00040040, nullptr, "SendDataIsEmpty"}, 541 {0x00040040, nullptr, "SendDataIsEmpty"},
519 {0x000500C2, nullptr, "SendFifoEx"}, 542 {0x000500C2, nullptr, "SendFifoEx"},
520 {0x000600C0, nullptr, "RecvFifoEx"}, 543 {0x000600C0, nullptr, "RecvFifoEx"},
521 {0x00070040, SetSemaphore, "SetSemaphore"}, 544 {0x00070040, SetSemaphore, "SetSemaphore"},
522 {0x00080000, nullptr, "GetSemaphore"}, 545 {0x00080000, nullptr, "GetSemaphore"},
523 {0x00090040, nullptr, "ClearSemaphore"}, 546 {0x00090040, nullptr, "ClearSemaphore"},
524 {0x000A0040, nullptr, "MaskSemaphore"}, 547 {0x000A0040, nullptr, "MaskSemaphore"},
525 {0x000B0000, nullptr, "CheckSemaphoreRequest"}, 548 {0x000B0000, nullptr, "CheckSemaphoreRequest"},
526 {0x000C0040, ConvertProcessAddressFromDspDram, "ConvertProcessAddressFromDspDram"}, 549 {0x000C0040, ConvertProcessAddressFromDspDram, "ConvertProcessAddressFromDspDram"},
527 {0x000D0082, WriteProcessPipe, "WriteProcessPipe"}, 550 {0x000D0082, WriteProcessPipe, "WriteProcessPipe"},
528 {0x000E00C0, ReadPipe, "ReadPipe"}, 551 {0x000E00C0, ReadPipe, "ReadPipe"},
529 {0x000F0080, GetPipeReadableSize, "GetPipeReadableSize"}, 552 {0x000F0080, GetPipeReadableSize, "GetPipeReadableSize"},
530 {0x001000C0, ReadPipeIfPossible, "ReadPipeIfPossible"}, 553 {0x001000C0, ReadPipeIfPossible, "ReadPipeIfPossible"},
531 {0x001100C2, LoadComponent, "LoadComponent"}, 554 {0x001100C2, LoadComponent, "LoadComponent"},
532 {0x00120000, nullptr, "UnloadComponent"}, 555 {0x00120000, nullptr, "UnloadComponent"},
533 {0x00130082, FlushDataCache, "FlushDataCache"}, 556 {0x00130082, FlushDataCache, "FlushDataCache"},
534 {0x00140082, nullptr, "InvalidateDCache"}, 557 {0x00140082, nullptr, "InvalidateDCache"},
535 {0x00150082, RegisterInterruptEvents, "RegisterInterruptEvents"}, 558 {0x00150082, RegisterInterruptEvents, "RegisterInterruptEvents"},
536 {0x00160000, GetSemaphoreEventHandle, "GetSemaphoreEventHandle"}, 559 {0x00160000, GetSemaphoreEventHandle, "GetSemaphoreEventHandle"},
537 {0x00170040, SetSemaphoreMask, "SetSemaphoreMask"}, 560 {0x00170040, SetSemaphoreMask, "SetSemaphoreMask"},
538 {0x00180040, nullptr, "GetPhysicalAddress"}, 561 {0x00180040, nullptr, "GetPhysicalAddress"},
539 {0x00190040, nullptr, "GetVirtualAddress"}, 562 {0x00190040, nullptr, "GetVirtualAddress"},
540 {0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"}, 563 {0x001A0042, nullptr, "SetIirFilterI2S1_cmd1"},
541 {0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"}, 564 {0x001B0042, nullptr, "SetIirFilterI2S1_cmd2"},
542 {0x001C0082, nullptr, "SetIirFilterEQ"}, 565 {0x001C0082, nullptr, "SetIirFilterEQ"},
543 {0x001D00C0, nullptr, "ReadMultiEx_SPI2"}, 566 {0x001D00C0, nullptr, "ReadMultiEx_SPI2"},
544 {0x001E00C2, nullptr, "WriteMultiEx_SPI2"}, 567 {0x001E00C2, nullptr, "WriteMultiEx_SPI2"},
545 {0x001F0000, GetHeadphoneStatus, "GetHeadphoneStatus"}, 568 {0x001F0000, GetHeadphoneStatus, "GetHeadphoneStatus"},
546 {0x00200040, nullptr, "ForceHeadphoneOut"}, 569 {0x00200040, nullptr, "ForceHeadphoneOut"},
547 {0x00210000, nullptr, "GetIsDspOccupied"}, 570 {0x00210000, nullptr, "GetIsDspOccupied"},
548}; 571};
549 572
550//////////////////////////////////////////////////////////////////////////////////////////////////// 573////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp
index 5f9cf6e94..2cd8269de 100644
--- a/src/core/hle/service/err_f.cpp
+++ b/src/core/hle/service/err_f.cpp
@@ -35,70 +35,70 @@ union ErrInfo {
35 u8 specifier; 35 u8 specifier;
36 36
37 struct { 37 struct {
38 u8 specifier; // 0x0 38 u8 specifier; // 0x0
39 u8 rev_high; // 0x1 39 u8 rev_high; // 0x1
40 u16 rev_low; // 0x2 40 u16 rev_low; // 0x2
41 RSL result_code; // 0x4 41 RSL result_code; // 0x4
42 u32 address; // 0x8 42 u32 address; // 0x8
43 INSERT_PADDING_BYTES(4); // 0xC 43 INSERT_PADDING_BYTES(4); // 0xC
44 u32 pid_low; // 0x10 44 u32 pid_low; // 0x10
45 u32 pid_high; // 0x14 45 u32 pid_high; // 0x14
46 u32 aid_low; // 0x18 46 u32 aid_low; // 0x18
47 u32 aid_high; // 0x1C 47 u32 aid_high; // 0x1C
48 } errtype1; 48 } errtype1;
49 49
50 struct { 50 struct {
51 u8 specifier; // 0x0 51 u8 specifier; // 0x0
52 u8 rev_high; // 0x1 52 u8 rev_high; // 0x1
53 u16 rev_low; // 0x2 53 u16 rev_low; // 0x2
54 INSERT_PADDING_BYTES(0xC); // 0x4 54 INSERT_PADDING_BYTES(0xC); // 0x4
55 u32 pid_low; // 0x10 55 u32 pid_low; // 0x10
56 u32 pid_high; // 0x14 56 u32 pid_high; // 0x14
57 u32 aid_low; // 0x18 57 u32 aid_low; // 0x18
58 u32 aid_high; // 0x1C 58 u32 aid_high; // 0x1C
59 u8 error_type; // 0x20 59 u8 error_type; // 0x20
60 INSERT_PADDING_BYTES(3); // 0x21 60 INSERT_PADDING_BYTES(3); // 0x21
61 u32 fault_status_reg; // 0x24 61 u32 fault_status_reg; // 0x24
62 u32 fault_addr; // 0x28 62 u32 fault_addr; // 0x28
63 u32 fpexc; // 0x2C 63 u32 fpexc; // 0x2C
64 u32 finst; // 0x30 64 u32 finst; // 0x30
65 u32 finst2; // 0x34 65 u32 finst2; // 0x34
66 INSERT_PADDING_BYTES(0x34); // 0x38 66 INSERT_PADDING_BYTES(0x34); // 0x38
67 u32 sp; // 0x6C 67 u32 sp; // 0x6C
68 u32 pc; // 0x70 68 u32 pc; // 0x70
69 u32 lr; // 0x74 69 u32 lr; // 0x74
70 u32 cpsr; // 0x78 70 u32 cpsr; // 0x78
71 } errtype3; 71 } errtype3;
72 72
73 struct { 73 struct {
74 u8 specifier; // 0x0 74 u8 specifier; // 0x0
75 u8 rev_high; // 0x1 75 u8 rev_high; // 0x1
76 u16 rev_low; // 0x2 76 u16 rev_low; // 0x2
77 RSL result_code; // 0x4 77 RSL result_code; // 0x4
78 INSERT_PADDING_BYTES(8); // 0x8 78 INSERT_PADDING_BYTES(8); // 0x8
79 u32 pid_low; // 0x10 79 u32 pid_low; // 0x10
80 u32 pid_high; // 0x14 80 u32 pid_high; // 0x14
81 u32 aid_low; // 0x18 81 u32 aid_low; // 0x18
82 u32 aid_high; // 0x1C 82 u32 aid_high; // 0x1C
83 char debug_string1[0x2E]; // 0x20 83 char debug_string1[0x2E]; // 0x20
84 char debug_string2[0x2E]; // 0x4E 84 char debug_string2[0x2E]; // 0x4E
85 } errtype4; 85 } errtype4;
86}; 86};
87 87
88enum { 88enum { PrefetchAbort = 0, DataAbort = 1, UndefInstr = 2, VectorFP = 3 };
89 PrefetchAbort = 0,
90 DataAbort = 1,
91 UndefInstr = 2,
92 VectorFP = 3
93};
94 89
95static std::string GetErrInfo3Type(u8 type_code) { 90static std::string GetErrInfo3Type(u8 type_code) {
96 switch (type_code) { 91 switch (type_code) {
97 case PrefetchAbort: return "Prefetch Abort"; 92 case PrefetchAbort:
98 case DataAbort: return "Data Abort"; 93 return "Prefetch Abort";
99 case UndefInstr: return "Undefined Instruction"; 94 case DataAbort:
100 case VectorFP: return "Vector Floating Point"; 95 return "Data Abort";
101 default: return "unknown"; 96 case UndefInstr:
97 return "Undefined Instruction";
98 case VectorFP:
99 return "Vector Floating Point";
100 default:
101 return "unknown";
102 } 102 }
103} 103}
104 104
@@ -110,8 +110,7 @@ static void ThrowFatalError(Service::Interface* self) {
110 110
111 switch (errinfo->specifier) { 111 switch (errinfo->specifier) {
112 case ErrSpecifier0: 112 case ErrSpecifier0:
113 case ErrSpecifier1: 113 case ErrSpecifier1: {
114 {
115 const auto& errtype = errinfo->errtype1; 114 const auto& errtype = errinfo->errtype1;
116 LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); 115 LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high);
117 LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16)); 116 LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16));
@@ -119,15 +118,14 @@ static void ThrowFatalError(Service::Interface* self) {
119 LOG_CRITICAL(Service_ERR, "ADR: 0x%08X", errtype.address); 118 LOG_CRITICAL(Service_ERR, "ADR: 0x%08X", errtype.address);
120 119
121 LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw); 120 LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw);
122 LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value()); 121 LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value());
123 LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value()); 122 LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value());
124 LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value()); 123 LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value());
125 LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value()); 124 LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value());
126 break; 125 break;
127 } 126 }
128 127
129 case ErrSpecifier3: 128 case ErrSpecifier3: {
130 {
131 const auto& errtype = errinfo->errtype3; 129 const auto& errtype = errinfo->errtype3;
132 LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); 130 LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high);
133 LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16)); 131 LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16));
@@ -154,18 +152,17 @@ static void ThrowFatalError(Service::Interface* self) {
154 break; 152 break;
155 } 153 }
156 154
157 case ErrSpecifier4: 155 case ErrSpecifier4: {
158 {
159 const auto& errtype = errinfo->errtype4; 156 const auto& errtype = errinfo->errtype4;
160 LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high); 157 LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high);
161 LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16)); 158 LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16));
162 LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high); 159 LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high);
163 160
164 LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw); 161 LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw);
165 LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value()); 162 LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value());
166 LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value()); 163 LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value());
167 LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value()); 164 LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value());
168 LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value()); 165 LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value());
169 166
170 LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string1); 167 LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string1);
171 LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string2); 168 LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string2);
@@ -176,9 +173,7 @@ static void ThrowFatalError(Service::Interface* self) {
176 cmd_buff[1] = 0; // No error 173 cmd_buff[1] = 0; // No error
177} 174}
178 175
179const Interface::FunctionInfo FunctionTable[] = { 176const Interface::FunctionInfo FunctionTable[] = {{0x00010800, ThrowFatalError, "ThrowFatalError"}};
180 {0x00010800, ThrowFatalError, "ThrowFatalError"}
181};
182 177
183//////////////////////////////////////////////////////////////////////////////////////////////////// 178////////////////////////////////////////////////////////////////////////////////////////////////////
184// Interface class 179// Interface class
diff --git a/src/core/hle/service/frd/frd.cpp b/src/core/hle/service/frd/frd.cpp
index 29d144365..1e9fe178f 100644
--- a/src/core/hle/service/frd/frd.cpp
+++ b/src/core/hle/service/frd/frd.cpp
@@ -4,10 +4,10 @@
4 4
5#include "common/string_util.h" 5#include "common/string_util.h"
6 6
7#include "core/hle/service/service.h"
8#include "core/hle/service/frd/frd.h" 7#include "core/hle/service/frd/frd.h"
9#include "core/hle/service/frd/frd_a.h" 8#include "core/hle/service/frd/frd_a.h"
10#include "core/hle/service/frd/frd_u.h" 9#include "core/hle/service/frd/frd_u.h"
10#include "core/hle/service/service.h"
11 11
12namespace Service { 12namespace Service {
13namespace FRD { 13namespace FRD {
@@ -43,7 +43,7 @@ void GetFriendKeyList(Service::Interface* self) {
43 } 43 }
44 44
45 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 45 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
46 cmd_buff[2] = 0; // 0 friends 46 cmd_buff[2] = 0; // 0 friends
47 LOG_WARNING(Service_FRD, "(STUBBED) called, unknown=%d, frd_count=%d, frd_key_addr=0x%08X", 47 LOG_WARNING(Service_FRD, "(STUBBED) called, unknown=%d, frd_count=%d, frd_key_addr=0x%08X",
48 unknown, frd_count, frd_key_addr); 48 unknown, frd_count, frd_key_addr);
49} 49}
@@ -61,25 +61,27 @@ void GetFriendProfile(Service::Interface* self) {
61 } 61 }
62 62
63 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 63 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
64 LOG_WARNING(Service_FRD, "(STUBBED) called, count=%d, frd_key_addr=0x%08X, profiles_addr=0x%08X", 64 LOG_WARNING(Service_FRD,
65 count, frd_key_addr, profiles_addr); 65 "(STUBBED) called, count=%d, frd_key_addr=0x%08X, profiles_addr=0x%08X", count,
66 frd_key_addr, profiles_addr);
66} 67}
67 68
68void GetFriendAttributeFlags(Service::Interface* self) { 69void GetFriendAttributeFlags(Service::Interface* self) {
69 u32* cmd_buff = Kernel::GetCommandBuffer(); 70 u32* cmd_buff = Kernel::GetCommandBuffer();
70 71
71 u32 count = cmd_buff[1]; 72 u32 count = cmd_buff[1];
72 u32 frd_key_addr = cmd_buff[3]; 73 u32 frd_key_addr = cmd_buff[3];
73 u32 attr_flags_addr = cmd_buff[65]; 74 u32 attr_flags_addr = cmd_buff[65];
74 75
75 for (u32 i = 0; i < count; ++i) { 76 for (u32 i = 0; i < count; ++i) {
76 //TODO:(mailwl) figure out AttributeFlag size and zero all buffer. Assume 1 byte 77 // TODO:(mailwl) figure out AttributeFlag size and zero all buffer. Assume 1 byte
77 Memory::Write8(attr_flags_addr + i, 0); 78 Memory::Write8(attr_flags_addr + i, 0);
78 } 79 }
79 80
80 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 81 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
81 LOG_WARNING(Service_FRD, "(STUBBED) called, count=%d, frd_key_addr=0x%08X, attr_flags_addr=0x%08X", 82 LOG_WARNING(Service_FRD,
82 count, frd_key_addr, attr_flags_addr); 83 "(STUBBED) called, count=%d, frd_key_addr=0x%08X, attr_flags_addr=0x%08X", count,
84 frd_key_addr, attr_flags_addr);
83} 85}
84 86
85void GetMyFriendKey(Service::Interface* self) { 87void GetMyFriendKey(Service::Interface* self) {
diff --git a/src/core/hle/service/frd/frd_a.cpp b/src/core/hle/service/frd/frd_a.cpp
index 818d610f3..cfc37210b 100644
--- a/src/core/hle/service/frd/frd_a.cpp
+++ b/src/core/hle/service/frd/frd_a.cpp
@@ -11,7 +11,7 @@ namespace FRD {
11// const Interface::FunctionInfo FunctionTable[] = { }; 11// const Interface::FunctionInfo FunctionTable[] = { };
12 12
13FRD_A_Interface::FRD_A_Interface() { 13FRD_A_Interface::FRD_A_Interface() {
14 //Register(FunctionTable); 14 // Register(FunctionTable);
15} 15}
16 16
17} // namespace FRD 17} // namespace FRD
diff --git a/src/core/hle/service/frd/frd_u.cpp b/src/core/hle/service/frd/frd_u.cpp
index db8666416..bd1c9c16b 100644
--- a/src/core/hle/service/frd/frd_u.cpp
+++ b/src/core/hle/service/frd/frd_u.cpp
@@ -9,59 +9,59 @@ namespace Service {
9namespace FRD { 9namespace FRD {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010000, nullptr, "HasLoggedIn"}, 12 {0x00010000, nullptr, "HasLoggedIn"},
13 {0x00020000, nullptr, "IsOnline"}, 13 {0x00020000, nullptr, "IsOnline"},
14 {0x00030000, nullptr, "Login"}, 14 {0x00030000, nullptr, "Login"},
15 {0x00040000, nullptr, "Logout"}, 15 {0x00040000, nullptr, "Logout"},
16 {0x00050000, GetMyFriendKey, "GetMyFriendKey"}, 16 {0x00050000, GetMyFriendKey, "GetMyFriendKey"},
17 {0x00060000, nullptr, "GetMyPreference"}, 17 {0x00060000, nullptr, "GetMyPreference"},
18 {0x00070000, nullptr, "GetMyProfile"}, 18 {0x00070000, nullptr, "GetMyProfile"},
19 {0x00080000, GetMyPresence, "GetMyPresence"}, 19 {0x00080000, GetMyPresence, "GetMyPresence"},
20 {0x00090000, GetMyScreenName, "GetMyScreenName"}, 20 {0x00090000, GetMyScreenName, "GetMyScreenName"},
21 {0x000A0000, nullptr, "GetMyMii"}, 21 {0x000A0000, nullptr, "GetMyMii"},
22 {0x000B0000, nullptr, "GetMyLocalAccountId"}, 22 {0x000B0000, nullptr, "GetMyLocalAccountId"},
23 {0x000C0000, nullptr, "GetMyPlayingGame"}, 23 {0x000C0000, nullptr, "GetMyPlayingGame"},
24 {0x000D0000, nullptr, "GetMyFavoriteGame"}, 24 {0x000D0000, nullptr, "GetMyFavoriteGame"},
25 {0x000E0000, nullptr, "GetMyNcPrincipalId"}, 25 {0x000E0000, nullptr, "GetMyNcPrincipalId"},
26 {0x000F0000, nullptr, "GetMyComment"}, 26 {0x000F0000, nullptr, "GetMyComment"},
27 {0x00100040, nullptr, "GetMyPassword"}, 27 {0x00100040, nullptr, "GetMyPassword"},
28 {0x00110080, GetFriendKeyList, "GetFriendKeyList"}, 28 {0x00110080, GetFriendKeyList, "GetFriendKeyList"},
29 {0x00120042, nullptr, "GetFriendPresence"}, 29 {0x00120042, nullptr, "GetFriendPresence"},
30 {0x00130142, nullptr, "GetFriendScreenName"}, 30 {0x00130142, nullptr, "GetFriendScreenName"},
31 {0x00140044, nullptr, "GetFriendMii"}, 31 {0x00140044, nullptr, "GetFriendMii"},
32 {0x00150042, GetFriendProfile, "GetFriendProfile"}, 32 {0x00150042, GetFriendProfile, "GetFriendProfile"},
33 {0x00160042, nullptr, "GetFriendRelationship"}, 33 {0x00160042, nullptr, "GetFriendRelationship"},
34 {0x00170042, GetFriendAttributeFlags, "GetFriendAttributeFlags"}, 34 {0x00170042, GetFriendAttributeFlags, "GetFriendAttributeFlags"},
35 {0x00180044, nullptr, "GetFriendPlayingGame"}, 35 {0x00180044, nullptr, "GetFriendPlayingGame"},
36 {0x00190042, nullptr, "GetFriendFavoriteGame"}, 36 {0x00190042, nullptr, "GetFriendFavoriteGame"},
37 {0x001A00C4, nullptr, "GetFriendInfo"}, 37 {0x001A00C4, nullptr, "GetFriendInfo"},
38 {0x001B0080, nullptr, "IsIncludedInFriendList"}, 38 {0x001B0080, nullptr, "IsIncludedInFriendList"},
39 {0x001C0042, nullptr, "UnscrambleLocalFriendCode"}, 39 {0x001C0042, nullptr, "UnscrambleLocalFriendCode"},
40 {0x001D0002, nullptr, "UpdateGameModeDescription"}, 40 {0x001D0002, nullptr, "UpdateGameModeDescription"},
41 {0x001E02C2, nullptr, "UpdateGameMode"}, 41 {0x001E02C2, nullptr, "UpdateGameMode"},
42 {0x001F0042, nullptr, "SendInvitation"}, 42 {0x001F0042, nullptr, "SendInvitation"},
43 {0x00200002, nullptr, "AttachToEventNotification"}, 43 {0x00200002, nullptr, "AttachToEventNotification"},
44 {0x00210040, nullptr, "SetNotificationMask"}, 44 {0x00210040, nullptr, "SetNotificationMask"},
45 {0x00220040, nullptr, "GetEventNotification"}, 45 {0x00220040, nullptr, "GetEventNotification"},
46 {0x00230000, nullptr, "GetLastResponseResult"}, 46 {0x00230000, nullptr, "GetLastResponseResult"},
47 {0x00240040, nullptr, "PrincipalIdToFriendCode"}, 47 {0x00240040, nullptr, "PrincipalIdToFriendCode"},
48 {0x00250080, nullptr, "FriendCodeToPrincipalId"}, 48 {0x00250080, nullptr, "FriendCodeToPrincipalId"},
49 {0x00260080, nullptr, "IsValidFriendCode"}, 49 {0x00260080, nullptr, "IsValidFriendCode"},
50 {0x00270040, nullptr, "ResultToErrorCode"}, 50 {0x00270040, nullptr, "ResultToErrorCode"},
51 {0x00280244, nullptr, "RequestGameAuthentication"}, 51 {0x00280244, nullptr, "RequestGameAuthentication"},
52 {0x00290000, nullptr, "GetGameAuthenticationData"}, 52 {0x00290000, nullptr, "GetGameAuthenticationData"},
53 {0x002A0204, nullptr, "RequestServiceLocator"}, 53 {0x002A0204, nullptr, "RequestServiceLocator"},
54 {0x002B0000, nullptr, "GetServiceLocatorData"}, 54 {0x002B0000, nullptr, "GetServiceLocatorData"},
55 {0x002C0002, nullptr, "DetectNatProperties"}, 55 {0x002C0002, nullptr, "DetectNatProperties"},
56 {0x002D0000, nullptr, "GetNatProperties"}, 56 {0x002D0000, nullptr, "GetNatProperties"},
57 {0x002E0000, nullptr, "GetServerTimeInterval"}, 57 {0x002E0000, nullptr, "GetServerTimeInterval"},
58 {0x002F0040, nullptr, "AllowHalfAwake"}, 58 {0x002F0040, nullptr, "AllowHalfAwake"},
59 {0x00300000, nullptr, "GetServerTypes"}, 59 {0x00300000, nullptr, "GetServerTypes"},
60 {0x00310082, nullptr, "GetFriendComment"}, 60 {0x00310082, nullptr, "GetFriendComment"},
61 {0x00320042, nullptr, "SetClientSdkVersion"}, 61 {0x00320042, nullptr, "SetClientSdkVersion"},
62 {0x00330000, nullptr, "GetMyApproachContext"}, 62 {0x00330000, nullptr, "GetMyApproachContext"},
63 {0x00340046, nullptr, "AddFriendWithApproach"}, 63 {0x00340046, nullptr, "AddFriendWithApproach"},
64 {0x00350082, nullptr, "DecryptApproachContext"}, 64 {0x00350082, nullptr, "DecryptApproachContext"},
65}; 65};
66 66
67FRD_U_Interface::FRD_U_Interface() { 67FRD_U_Interface::FRD_U_Interface() {
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index 4c7aaa7f2..1b851eade 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -3,9 +3,9 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstddef> 5#include <cstddef>
6#include <memory>
6#include <system_error> 7#include <system_error>
7#include <type_traits> 8#include <type_traits>
8#include <memory>
9#include <unordered_map> 9#include <unordered_map>
10#include <utility> 10#include <utility>
11 11
@@ -25,25 +25,25 @@
25#include "core/file_sys/directory_backend.h" 25#include "core/file_sys/directory_backend.h"
26#include "core/file_sys/file_backend.h" 26#include "core/file_sys/file_backend.h"
27#include "core/hle/hle.h" 27#include "core/hle/hle.h"
28#include "core/hle/service/service.h" 28#include "core/hle/result.h"
29#include "core/hle/service/fs/archive.h" 29#include "core/hle/service/fs/archive.h"
30#include "core/hle/service/fs/fs_user.h" 30#include "core/hle/service/fs/fs_user.h"
31#include "core/hle/result.h" 31#include "core/hle/service/service.h"
32#include "core/memory.h" 32#include "core/memory.h"
33 33
34// Specializes std::hash for ArchiveIdCode, so that we can use it in std::unordered_map. 34// Specializes std::hash for ArchiveIdCode, so that we can use it in std::unordered_map.
35// Workaroung for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970 35// Workaroung for libstdc++ bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60970
36namespace std { 36namespace std {
37 template <> 37template <>
38 struct hash<Service::FS::ArchiveIdCode> { 38struct hash<Service::FS::ArchiveIdCode> {
39 typedef Service::FS::ArchiveIdCode argument_type; 39 typedef Service::FS::ArchiveIdCode argument_type;
40 typedef std::size_t result_type; 40 typedef std::size_t result_type;
41 41
42 result_type operator()(const argument_type& id_code) const { 42 result_type operator()(const argument_type& id_code) const {
43 typedef std::underlying_type<argument_type>::type Type; 43 typedef std::underlying_type<argument_type>::type Type;
44 return std::hash<Type>()(static_cast<Type>(id_code)); 44 return std::hash<Type>()(static_cast<Type>(id_code));
45 } 45 }
46 }; 46};
47} 47}
48 48
49/// TODO(Subv): Confirm length of these strings 49/// TODO(Subv): Confirm length of these strings
@@ -56,197 +56,193 @@ namespace FS {
56// TODO: Verify code 56// TODO: Verify code
57/// Returned when a function is passed an invalid handle. 57/// Returned when a function is passed an invalid handle.
58const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::FS, 58const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::FS,
59 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 59 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
60 60
61/// Returned when a function is passed an invalid archive handle. 61/// Returned when a function is passed an invalid archive handle.
62const ResultCode ERR_INVALID_ARCHIVE_HANDLE(ErrorDescription::FS_ArchiveNotMounted, ErrorModule::FS, 62const ResultCode ERR_INVALID_ARCHIVE_HANDLE(ErrorDescription::FS_ArchiveNotMounted, ErrorModule::FS,
63 ErrorSummary::NotFound, ErrorLevel::Status); // 0xC8804465 63 ErrorSummary::NotFound,
64 ErrorLevel::Status); // 0xC8804465
64 65
65// Command to access archive file 66// Command to access archive file
66enum class FileCommand : u32 { 67enum class FileCommand : u32 {
67 Dummy1 = 0x000100C6, 68 Dummy1 = 0x000100C6,
68 Control = 0x040100C4, 69 Control = 0x040100C4,
69 OpenSubFile = 0x08010100, 70 OpenSubFile = 0x08010100,
70 Read = 0x080200C2, 71 Read = 0x080200C2,
71 Write = 0x08030102, 72 Write = 0x08030102,
72 GetSize = 0x08040000, 73 GetSize = 0x08040000,
73 SetSize = 0x08050080, 74 SetSize = 0x08050080,
74 GetAttributes = 0x08060000, 75 GetAttributes = 0x08060000,
75 SetAttributes = 0x08070040, 76 SetAttributes = 0x08070040,
76 Close = 0x08080000, 77 Close = 0x08080000,
77 Flush = 0x08090000, 78 Flush = 0x08090000,
78 SetPriority = 0x080A0040, 79 SetPriority = 0x080A0040,
79 GetPriority = 0x080B0000, 80 GetPriority = 0x080B0000,
80 OpenLinkFile = 0x080C0000, 81 OpenLinkFile = 0x080C0000,
81}; 82};
82 83
83// Command to access directory 84// Command to access directory
84enum class DirectoryCommand : u32 { 85enum class DirectoryCommand : u32 {
85 Dummy1 = 0x000100C6, 86 Dummy1 = 0x000100C6,
86 Control = 0x040100C4, 87 Control = 0x040100C4,
87 Read = 0x08010042, 88 Read = 0x08010042,
88 Close = 0x08020000, 89 Close = 0x08020000,
89}; 90};
90 91
91File::File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path & path) 92File::File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path)
92 : path(path), priority(0), backend(std::move(backend)) {} 93 : path(path), priority(0), backend(std::move(backend)) {
94}
93 95
94File::~File() {} 96File::~File() {
97}
95 98
96ResultVal<bool> File::SyncRequest() { 99ResultVal<bool> File::SyncRequest() {
97 u32* cmd_buff = Kernel::GetCommandBuffer(); 100 u32* cmd_buff = Kernel::GetCommandBuffer();
98 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]); 101 FileCommand cmd = static_cast<FileCommand>(cmd_buff[0]);
99 switch (cmd) { 102 switch (cmd) {
100 103
101 // Read from file... 104 // Read from file...
102 case FileCommand::Read: 105 case FileCommand::Read: {
103 { 106 u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32;
104 u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32; 107 u32 length = cmd_buff[3];
105 u32 length = cmd_buff[3]; 108 u32 address = cmd_buff[5];
106 u32 address = cmd_buff[5]; 109 LOG_TRACE(Service_FS, "Read %s %s: offset=0x%llx length=%d address=0x%x",
107 LOG_TRACE(Service_FS, "Read %s %s: offset=0x%llx length=%d address=0x%x", 110 GetTypeName().c_str(), GetName().c_str(), offset, length, address);
108 GetTypeName().c_str(), GetName().c_str(), offset, length, address); 111
109 112 if (offset + length > backend->GetSize()) {
110 if (offset + length > backend->GetSize()) { 113 LOG_ERROR(Service_FS,
111 LOG_ERROR(Service_FS, "Reading from out of bounds offset=0x%llX length=0x%08X file_size=0x%llX", 114 "Reading from out of bounds offset=0x%llX length=0x%08X file_size=0x%llX",
112 offset, length, backend->GetSize()); 115 offset, length, backend->GetSize());
113 }
114
115 std::vector<u8> data(length);
116 ResultVal<size_t> read = backend->Read(offset, data.size(), data.data());
117 if (read.Failed()) {
118 cmd_buff[1] = read.Code().raw;
119 return read.Code();
120 }
121 Memory::WriteBlock(address, data.data(), *read);
122 cmd_buff[2] = static_cast<u32>(*read);
123 break;
124 } 116 }
125 117
126 // Write to file... 118 std::vector<u8> data(length);
127 case FileCommand::Write: 119 ResultVal<size_t> read = backend->Read(offset, data.size(), data.data());
128 { 120 if (read.Failed()) {
129 u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32; 121 cmd_buff[1] = read.Code().raw;
130 u32 length = cmd_buff[3]; 122 return read.Code();
131 u32 flush = cmd_buff[4];
132 u32 address = cmd_buff[6];
133 LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x",
134 GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush);
135
136 std::vector<u8> data(length);
137 Memory::ReadBlock(address, data.data(), data.size());
138 ResultVal<size_t> written = backend->Write(offset, data.size(), flush != 0, data.data());
139 if (written.Failed()) {
140 cmd_buff[1] = written.Code().raw;
141 return written.Code();
142 }
143 cmd_buff[2] = static_cast<u32>(*written);
144 break;
145 } 123 }
124 Memory::WriteBlock(address, data.data(), *read);
125 cmd_buff[2] = static_cast<u32>(*read);
126 break;
127 }
146 128
147 case FileCommand::GetSize: 129 // Write to file...
148 { 130 case FileCommand::Write: {
149 LOG_TRACE(Service_FS, "GetSize %s %s", GetTypeName().c_str(), GetName().c_str()); 131 u64 offset = cmd_buff[1] | ((u64)cmd_buff[2]) << 32;
150 u64 size = backend->GetSize(); 132 u32 length = cmd_buff[3];
151 cmd_buff[2] = (u32)size; 133 u32 flush = cmd_buff[4];
152 cmd_buff[3] = size >> 32; 134 u32 address = cmd_buff[6];
153 break; 135 LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x",
136 GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush);
137
138 std::vector<u8> data(length);
139 Memory::ReadBlock(address, data.data(), data.size());
140 ResultVal<size_t> written = backend->Write(offset, data.size(), flush != 0, data.data());
141 if (written.Failed()) {
142 cmd_buff[1] = written.Code().raw;
143 return written.Code();
154 } 144 }
145 cmd_buff[2] = static_cast<u32>(*written);
146 break;
147 }
155 148
156 case FileCommand::SetSize: 149 case FileCommand::GetSize: {
157 { 150 LOG_TRACE(Service_FS, "GetSize %s %s", GetTypeName().c_str(), GetName().c_str());
158 u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32); 151 u64 size = backend->GetSize();
159 LOG_TRACE(Service_FS, "SetSize %s %s size=%llu", 152 cmd_buff[2] = (u32)size;
160 GetTypeName().c_str(), GetName().c_str(), size); 153 cmd_buff[3] = size >> 32;
161 backend->SetSize(size); 154 break;
162 break; 155 }
163 }
164 156
165 case FileCommand::Close: 157 case FileCommand::SetSize: {
166 { 158 u64 size = cmd_buff[1] | ((u64)cmd_buff[2] << 32);
167 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); 159 LOG_TRACE(Service_FS, "SetSize %s %s size=%llu", GetTypeName().c_str(), GetName().c_str(),
168 backend->Close(); 160 size);
169 break; 161 backend->SetSize(size);
170 } 162 break;
163 }
171 164
172 case FileCommand::Flush: 165 case FileCommand::Close: {
173 { 166 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str());
174 LOG_TRACE(Service_FS, "Flush"); 167 backend->Close();
175 backend->Flush(); 168 break;
176 break; 169 }
177 }
178 170
179 case FileCommand::OpenLinkFile: 171 case FileCommand::Flush: {
180 { 172 LOG_TRACE(Service_FS, "Flush");
181 LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str()); 173 backend->Flush();
182 cmd_buff[3] = Kernel::g_handle_table.Create(this).ValueOr(INVALID_HANDLE); 174 break;
183 break; 175 }
184 }
185 176
186 case FileCommand::SetPriority: 177 case FileCommand::OpenLinkFile: {
187 { 178 LOG_WARNING(Service_FS, "(STUBBED) File command OpenLinkFile %s", GetName().c_str());
188 priority = cmd_buff[1]; 179 cmd_buff[3] = Kernel::g_handle_table.Create(this).ValueOr(INVALID_HANDLE);
189 LOG_TRACE(Service_FS, "SetPriority %u", priority); 180 break;
190 break; 181 }
191 }
192 182
193 case FileCommand::GetPriority: 183 case FileCommand::SetPriority: {
194 { 184 priority = cmd_buff[1];
195 cmd_buff[2] = priority; 185 LOG_TRACE(Service_FS, "SetPriority %u", priority);
196 LOG_TRACE(Service_FS, "GetPriority"); 186 break;
197 break; 187 }
198 }
199 188
200 // Unknown command... 189 case FileCommand::GetPriority: {
201 default: 190 cmd_buff[2] = priority;
202 LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); 191 LOG_TRACE(Service_FS, "GetPriority");
203 ResultCode error = UnimplementedFunction(ErrorModule::FS); 192 break;
204 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. 193 }
205 return error; 194
195 // Unknown command...
196 default:
197 LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd);
198 ResultCode error = UnimplementedFunction(ErrorModule::FS);
199 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
200 return error;
206 } 201 }
207 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 202 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
208 return MakeResult<bool>(false); 203 return MakeResult<bool>(false);
209} 204}
210 205
211Directory::Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path & path) 206Directory::Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend,
212 : path(path), backend(std::move(backend)) {} 207 const FileSys::Path& path)
208 : path(path), backend(std::move(backend)) {
209}
213 210
214Directory::~Directory() {} 211Directory::~Directory() {
212}
215 213
216ResultVal<bool> Directory::SyncRequest() { 214ResultVal<bool> Directory::SyncRequest() {
217 u32* cmd_buff = Kernel::GetCommandBuffer(); 215 u32* cmd_buff = Kernel::GetCommandBuffer();
218 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]); 216 DirectoryCommand cmd = static_cast<DirectoryCommand>(cmd_buff[0]);
219 switch (cmd) { 217 switch (cmd) {
220 218
221 // Read from directory... 219 // Read from directory...
222 case DirectoryCommand::Read: 220 case DirectoryCommand::Read: {
223 { 221 u32 count = cmd_buff[1];
224 u32 count = cmd_buff[1]; 222 u32 address = cmd_buff[3];
225 u32 address = cmd_buff[3]; 223 std::vector<FileSys::Entry> entries(count);
226 std::vector<FileSys::Entry> entries(count); 224 LOG_TRACE(Service_FS, "Read %s %s: count=%d", GetTypeName().c_str(), GetName().c_str(),
227 LOG_TRACE(Service_FS, "Read %s %s: count=%d", 225 count);
228 GetTypeName().c_str(), GetName().c_str(), count); 226
229 227 // Number of entries actually read
230 // Number of entries actually read 228 u32 read = backend->Read(entries.size(), entries.data());
231 u32 read = backend->Read(entries.size(), entries.data()); 229 cmd_buff[2] = read;
232 cmd_buff[2] = read; 230 Memory::WriteBlock(address, entries.data(), read * sizeof(FileSys::Entry));
233 Memory::WriteBlock(address, entries.data(), read * sizeof(FileSys::Entry)); 231 break;
234 break; 232 }
235 }
236 233
237 case DirectoryCommand::Close: 234 case DirectoryCommand::Close: {
238 { 235 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str());
239 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); 236 backend->Close();
240 backend->Close(); 237 break;
241 break; 238 }
242 }
243 239
244 // Unknown command... 240 // Unknown command...
245 default: 241 default:
246 LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd); 242 LOG_ERROR(Service_FS, "Unknown command=0x%08X!", cmd);
247 ResultCode error = UnimplementedFunction(ErrorModule::FS); 243 ResultCode error = UnimplementedFunction(ErrorModule::FS);
248 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that. 244 cmd_buff[1] = error.raw; // TODO(Link Mauve): use the correct error code for that.
249 return MakeResult<bool>(false); 245 return MakeResult<bool>(false);
250 } 246 }
251 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 247 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
252 return MakeResult<bool>(false); 248 return MakeResult<bool>(false);
@@ -280,8 +276,8 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi
280 auto itr = id_code_map.find(id_code); 276 auto itr = id_code_map.find(id_code);
281 if (itr == id_code_map.end()) { 277 if (itr == id_code_map.end()) {
282 // TODO: Verify error against hardware 278 // TODO: Verify error against hardware
283 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, 279 return ResultCode(ErrorDescription::NotFound, ErrorModule::FS, ErrorSummary::NotFound,
284 ErrorSummary::NotFound, ErrorLevel::Permanent); 280 ErrorLevel::Permanent);
285 } 281 }
286 282
287 CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path)); 283 CASCADE_RESULT(std::unique_ptr<ArchiveBackend> res, itr->second->Open(archive_path));
@@ -303,19 +299,22 @@ ResultCode CloseArchive(ArchiveHandle handle) {
303 299
304// TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in 300// TODO(yuriks): This might be what the fs:REG service is for. See the Register/Unregister calls in
305// http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22 301// http://3dbrew.org/wiki/Filesystem_services#ProgramRegistry_service_.22fs:REG.22
306ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, ArchiveIdCode id_code) { 302ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory,
303 ArchiveIdCode id_code) {
307 auto result = id_code_map.emplace(id_code, std::move(factory)); 304 auto result = id_code_map.emplace(id_code, std::move(factory));
308 305
309 bool inserted = result.second; 306 bool inserted = result.second;
310 ASSERT_MSG(inserted, "Tried to register more than one archive with same id code"); 307 ASSERT_MSG(inserted, "Tried to register more than one archive with same id code");
311 308
312 auto& archive = result.first->second; 309 auto& archive = result.first->second;
313 LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(), id_code); 310 LOG_DEBUG(Service_FS, "Registered archive %s with id code 0x%08X", archive->GetName().c_str(),
311 id_code);
314 return RESULT_SUCCESS; 312 return RESULT_SUCCESS;
315} 313}
316 314
317ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle, 315ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle,
318 const FileSys::Path& path, const FileSys::Mode mode) { 316 const FileSys::Path& path,
317 const FileSys::Mode mode) {
319 ArchiveBackend* archive = GetArchive(archive_handle); 318 ArchiveBackend* archive = GetArchive(archive_handle);
320 if (archive == nullptr) 319 if (archive == nullptr)
321 return ERR_INVALID_ARCHIVE_HANDLE; 320 return ERR_INVALID_ARCHIVE_HANDLE;
@@ -336,8 +335,10 @@ ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Pa
336 return archive->DeleteFile(path); 335 return archive->DeleteFile(path);
337} 336}
338 337
339ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, 338ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle,
340 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { 339 const FileSys::Path& src_path,
340 ArchiveHandle dest_archive_handle,
341 const FileSys::Path& dest_path) {
341 ArchiveBackend* src_archive = GetArchive(src_archive_handle); 342 ArchiveBackend* src_archive = GetArchive(src_archive_handle);
342 ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); 343 ArchiveBackend* dest_archive = GetArchive(dest_archive_handle);
343 if (src_archive == nullptr || dest_archive == nullptr) 344 if (src_archive == nullptr || dest_archive == nullptr)
@@ -368,7 +369,8 @@ ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy
368 ErrorSummary::Canceled, ErrorLevel::Status); 369 ErrorSummary::Canceled, ErrorLevel::Status);
369} 370}
370 371
371ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u64 file_size) { 372ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path,
373 u64 file_size) {
372 ArchiveBackend* archive = GetArchive(archive_handle); 374 ArchiveBackend* archive = GetArchive(archive_handle);
373 if (archive == nullptr) 375 if (archive == nullptr)
374 return ERR_INVALID_ARCHIVE_HANDLE; 376 return ERR_INVALID_ARCHIVE_HANDLE;
@@ -387,8 +389,10 @@ ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy
387 ErrorSummary::Canceled, ErrorLevel::Status); 389 ErrorSummary::Canceled, ErrorLevel::Status);
388} 390}
389 391
390ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, 392ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle,
391 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path) { 393 const FileSys::Path& src_path,
394 ArchiveHandle dest_archive_handle,
395 const FileSys::Path& dest_path) {
392 ArchiveBackend* src_archive = GetArchive(src_archive_handle); 396 ArchiveBackend* src_archive = GetArchive(src_archive_handle);
393 ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); 397 ArchiveBackend* dest_archive = GetArchive(dest_archive_handle);
394 if (src_archive == nullptr || dest_archive == nullptr) 398 if (src_archive == nullptr || dest_archive == nullptr)
@@ -409,15 +413,15 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons
409} 413}
410 414
411ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, 415ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle,
412 const FileSys::Path& path) { 416 const FileSys::Path& path) {
413 ArchiveBackend* archive = GetArchive(archive_handle); 417 ArchiveBackend* archive = GetArchive(archive_handle);
414 if (archive == nullptr) 418 if (archive == nullptr)
415 return ERR_INVALID_ARCHIVE_HANDLE; 419 return ERR_INVALID_ARCHIVE_HANDLE;
416 420
417 std::unique_ptr<FileSys::DirectoryBackend> backend = archive->OpenDirectory(path); 421 std::unique_ptr<FileSys::DirectoryBackend> backend = archive->OpenDirectory(path);
418 if (backend == nullptr) { 422 if (backend == nullptr) {
419 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, 423 return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound,
420 ErrorSummary::NotFound, ErrorLevel::Permanent); 424 ErrorLevel::Permanent);
421 } 425 }
422 426
423 auto directory = Kernel::SharedPtr<Directory>(new Directory(std::move(backend), path)); 427 auto directory = Kernel::SharedPtr<Directory>(new Directory(std::move(backend), path));
@@ -431,7 +435,8 @@ ResultVal<u64> GetFreeBytesInArchive(ArchiveHandle archive_handle) {
431 return MakeResult<u64>(archive->GetFreeBytes()); 435 return MakeResult<u64>(archive->GetFreeBytes());
432} 436}
433 437
434ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info, const FileSys::Path& path) { 438ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info,
439 const FileSys::Path& path) {
435 auto archive_itr = id_code_map.find(id_code); 440 auto archive_itr = id_code_map.find(id_code);
436 if (archive_itr == id_code_map.end()) { 441 if (archive_itr == id_code_map.end()) {
437 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error 442 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error
@@ -440,7 +445,8 @@ ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo
440 return archive_itr->second->Format(path, format_info); 445 return archive_itr->second->Format(path, format_info);
441} 446}
442 447
443ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code, FileSys::Path& archive_path) { 448ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code,
449 FileSys::Path& archive_path) {
444 auto archive = id_code_map.find(id_code); 450 auto archive = id_code_map.find(id_code);
445 if (archive == id_code_map.end()) { 451 if (archive == id_code_map.end()) {
446 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error 452 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error
@@ -449,11 +455,14 @@ ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code
449 return archive->second->GetFormatInfo(archive_path); 455 return archive->second->GetFormatInfo(archive_path);
450} 456}
451 457
452ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, u32 icon_size, const FileSys::ArchiveFormatInfo& format_info) { 458ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer,
459 u32 icon_size, const FileSys::ArchiveFormatInfo& format_info) {
453 // Construct the binary path to the archive first 460 // Construct the binary path to the archive first
454 FileSys::Path path = FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low); 461 FileSys::Path path =
462 FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low);
455 463
456 auto archive = id_code_map.find(media_type == MediaType::NAND ? ArchiveIdCode::SharedExtSaveData : ArchiveIdCode::ExtSaveData); 464 auto archive = id_code_map.find(media_type == MediaType::NAND ? ArchiveIdCode::SharedExtSaveData
465 : ArchiveIdCode::ExtSaveData);
457 466
458 if (archive == id_code_map.end()) { 467 if (archive == id_code_map.end()) {
459 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error 468 return UnimplementedFunction(ErrorModule::FS); // TODO(Subv): Find the right error
@@ -476,7 +485,8 @@ ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon
476 485
477ResultCode DeleteExtSaveData(MediaType media_type, u32 high, u32 low) { 486ResultCode DeleteExtSaveData(MediaType media_type, u32 high, u32 low) {
478 // Construct the binary path to the archive first 487 // Construct the binary path to the archive first
479 FileSys::Path path = FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low); 488 FileSys::Path path =
489 FileSys::ConstructExtDataBinaryPath(static_cast<u32>(media_type), high, low);
480 490
481 std::string media_type_directory; 491 std::string media_type_directory;
482 if (media_type == MediaType::NAND) { 492 if (media_type == MediaType::NAND) {
@@ -489,7 +499,8 @@ ResultCode DeleteExtSaveData(MediaType media_type, u32 high, u32 low) {
489 } 499 }
490 500
491 // Delete all directories (/user, /boss) and the icon file. 501 // Delete all directories (/user, /boss) and the icon file.
492 std::string base_path = FileSys::GetExtDataContainerPath(media_type_directory, media_type == MediaType::NAND); 502 std::string base_path =
503 FileSys::GetExtDataContainerPath(media_type_directory, media_type == MediaType::NAND);
493 std::string extsavedata_path = FileSys::GetExtSaveDataPath(base_path, path); 504 std::string extsavedata_path = FileSys::GetExtSaveDataPath(base_path, path);
494 if (FileUtil::Exists(extsavedata_path) && !FileUtil::DeleteDirRecursively(extsavedata_path)) 505 if (FileUtil::Exists(extsavedata_path) && !FileUtil::DeleteDirRecursively(extsavedata_path))
495 return ResultCode(-1); // TODO(Subv): Find the right error code 506 return ResultCode(-1); // TODO(Subv): Find the right error code
@@ -530,30 +541,36 @@ void RegisterArchiveTypes() {
530 if (sdmc_factory->Initialize()) 541 if (sdmc_factory->Initialize())
531 RegisterArchiveType(std::move(sdmc_factory), ArchiveIdCode::SDMC); 542 RegisterArchiveType(std::move(sdmc_factory), ArchiveIdCode::SDMC);
532 else 543 else
533 LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str()); 544 LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s",
545 sdmc_directory.c_str());
534 546
535 // Create the SaveData archive 547 // Create the SaveData archive
536 auto savedata_factory = std::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory); 548 auto savedata_factory = std::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory);
537 RegisterArchiveType(std::move(savedata_factory), ArchiveIdCode::SaveData); 549 RegisterArchiveType(std::move(savedata_factory), ArchiveIdCode::SaveData);
538 550
539 auto extsavedata_factory = std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(sdmc_directory, false); 551 auto extsavedata_factory =
552 std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(sdmc_directory, false);
540 if (extsavedata_factory->Initialize()) 553 if (extsavedata_factory->Initialize())
541 RegisterArchiveType(std::move(extsavedata_factory), ArchiveIdCode::ExtSaveData); 554 RegisterArchiveType(std::move(extsavedata_factory), ArchiveIdCode::ExtSaveData);
542 else 555 else
543 LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s", extsavedata_factory->GetMountPoint().c_str()); 556 LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s",
557 extsavedata_factory->GetMountPoint().c_str());
544 558
545 auto sharedextsavedata_factory = std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(nand_directory, true); 559 auto sharedextsavedata_factory =
560 std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(nand_directory, true);
546 if (sharedextsavedata_factory->Initialize()) 561 if (sharedextsavedata_factory->Initialize())
547 RegisterArchiveType(std::move(sharedextsavedata_factory), ArchiveIdCode::SharedExtSaveData); 562 RegisterArchiveType(std::move(sharedextsavedata_factory), ArchiveIdCode::SharedExtSaveData);
548 else 563 else
549 LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s", 564 LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s",
550 sharedextsavedata_factory->GetMountPoint().c_str()); 565 sharedextsavedata_factory->GetMountPoint().c_str());
551 566
552 // Create the SaveDataCheck archive, basically a small variation of the RomFS archive 567 // Create the SaveDataCheck archive, basically a small variation of the RomFS archive
553 auto savedatacheck_factory = std::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory); 568 auto savedatacheck_factory =
569 std::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory);
554 RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck); 570 RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck);
555 571
556 auto systemsavedata_factory = std::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory); 572 auto systemsavedata_factory =
573 std::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory);
557 RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData); 574 RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData);
558} 575}
559 576
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h
index f7a50a3a7..aad540ff9 100644
--- a/src/core/hle/service/fs/archive.h
+++ b/src/core/hle/service/fs/archive.h
@@ -28,21 +28,18 @@ namespace FS {
28 28
29/// Supported archive types 29/// Supported archive types
30enum class ArchiveIdCode : u32 { 30enum class ArchiveIdCode : u32 {
31 RomFS = 0x00000003, 31 RomFS = 0x00000003,
32 SaveData = 0x00000004, 32 SaveData = 0x00000004,
33 ExtSaveData = 0x00000006, 33 ExtSaveData = 0x00000006,
34 SharedExtSaveData = 0x00000007, 34 SharedExtSaveData = 0x00000007,
35 SystemSaveData = 0x00000008, 35 SystemSaveData = 0x00000008,
36 SDMC = 0x00000009, 36 SDMC = 0x00000009,
37 SDMCWriteOnly = 0x0000000A, 37 SDMCWriteOnly = 0x0000000A,
38 SaveDataCheck = 0x2345678A, 38 SaveDataCheck = 0x2345678A,
39}; 39};
40 40
41/// Media types for the archives 41/// Media types for the archives
42enum class MediaType : u32 { 42enum class MediaType : u32 { NAND = 0, SDMC = 1 };
43 NAND = 0,
44 SDMC = 1
45};
46 43
47typedef u64 ArchiveHandle; 44typedef u64 ArchiveHandle;
48 45
@@ -51,11 +48,13 @@ public:
51 File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path); 48 File(std::unique_ptr<FileSys::FileBackend>&& backend, const FileSys::Path& path);
52 ~File(); 49 ~File();
53 50
54 std::string GetName() const override { return "Path: " + path.DebugStr(); } 51 std::string GetName() const override {
52 return "Path: " + path.DebugStr();
53 }
55 ResultVal<bool> SyncRequest() override; 54 ResultVal<bool> SyncRequest() override;
56 55
57 FileSys::Path path; ///< Path of the file 56 FileSys::Path path; ///< Path of the file
58 u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means 57 u32 priority; ///< Priority of the file. TODO(Subv): Find out what this means
59 std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface 58 std::unique_ptr<FileSys::FileBackend> backend; ///< File backend interface
60}; 59};
61 60
@@ -64,10 +63,12 @@ public:
64 Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path); 63 Directory(std::unique_ptr<FileSys::DirectoryBackend>&& backend, const FileSys::Path& path);
65 ~Directory(); 64 ~Directory();
66 65
67 std::string GetName() const override { return "Directory: " + path.DebugStr(); } 66 std::string GetName() const override {
67 return "Directory: " + path.DebugStr();
68 }
68 ResultVal<bool> SyncRequest() override; 69 ResultVal<bool> SyncRequest() override;
69 70
70 FileSys::Path path; ///< Path of the directory 71 FileSys::Path path; ///< Path of the directory
71 std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface 72 std::unique_ptr<FileSys::DirectoryBackend> backend; ///< File backend interface
72}; 73};
73 74
@@ -90,7 +91,8 @@ ResultCode CloseArchive(ArchiveHandle handle);
90 * @param factory File system backend interface to the archive 91 * @param factory File system backend interface to the archive
91 * @param id_code Id code used to access this type of archive 92 * @param id_code Id code used to access this type of archive
92 */ 93 */
93ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory, ArchiveIdCode id_code); 94ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factory,
95 ArchiveIdCode id_code);
94 96
95/** 97/**
96 * Open a File from an Archive 98 * Open a File from an Archive
@@ -100,7 +102,8 @@ ResultCode RegisterArchiveType(std::unique_ptr<FileSys::ArchiveFactory>&& factor
100 * @return The opened File object as a Session 102 * @return The opened File object as a Session
101 */ 103 */
102ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle, 104ResultVal<Kernel::SharedPtr<File>> OpenFileFromArchive(ArchiveHandle archive_handle,
103 const FileSys::Path& path, const FileSys::Mode mode); 105 const FileSys::Path& path,
106 const FileSys::Mode mode);
104 107
105/** 108/**
106 * Delete a File from an Archive 109 * Delete a File from an Archive
@@ -118,8 +121,10 @@ ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Pa
118 * @param dest_path Path to the File inside of the destination Archive 121 * @param dest_path Path to the File inside of the destination Archive
119 * @return Whether rename succeeded 122 * @return Whether rename succeeded
120 */ 123 */
121ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, 124ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle,
122 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path); 125 const FileSys::Path& src_path,
126 ArchiveHandle dest_archive_handle,
127 const FileSys::Path& dest_path);
123 128
124/** 129/**
125 * Delete a Directory from an Archive 130 * Delete a Directory from an Archive
@@ -136,7 +141,8 @@ ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy
136 * @param file_size The size of the new file, filled with zeroes 141 * @param file_size The size of the new file, filled with zeroes
137 * @return File creation result code 142 * @return File creation result code
138 */ 143 */
139ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u64 file_size); 144ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path,
145 u64 file_size);
140 146
141/** 147/**
142 * Create a Directory from an Archive 148 * Create a Directory from an Archive
@@ -154,8 +160,10 @@ ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy
154 * @param dest_path Path to the Directory inside of the destination Archive 160 * @param dest_path Path to the Directory inside of the destination Archive
155 * @return Whether rename succeeded 161 * @return Whether rename succeeded
156 */ 162 */
157ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, const FileSys::Path& src_path, 163ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle,
158 ArchiveHandle dest_archive_handle, const FileSys::Path& dest_path); 164 const FileSys::Path& src_path,
165 ArchiveHandle dest_archive_handle,
166 const FileSys::Path& dest_path);
159 167
160/** 168/**
161 * Open a Directory from an Archive 169 * Open a Directory from an Archive
@@ -164,7 +172,7 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons
164 * @return The opened Directory object as a Session 172 * @return The opened Directory object as a Session
165 */ 173 */
166ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle, 174ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle,
167 const FileSys::Path& path); 175 const FileSys::Path& path);
168 176
169/** 177/**
170 * Get the free space in an Archive 178 * Get the free space in an Archive
@@ -181,7 +189,8 @@ ResultVal<u64> GetFreeBytesInArchive(ArchiveHandle archive_handle);
181 * @param path The path to the archive, if relevant. 189 * @param path The path to the archive, if relevant.
182 * @return ResultCode 0 on success or the corresponding code on error 190 * @return ResultCode 0 on success or the corresponding code on error
183 */ 191 */
184ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info, const FileSys::Path& path = FileSys::Path()); 192ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo& format_info,
193 const FileSys::Path& path = FileSys::Path());
185 194
186/** 195/**
187 * Retrieves the format info about the archive of the specified type and path. 196 * Retrieves the format info about the archive of the specified type and path.
@@ -190,7 +199,8 @@ ResultCode FormatArchive(ArchiveIdCode id_code, const FileSys::ArchiveFormatInfo
190 * @param archive_path The path of the archive, if relevant 199 * @param archive_path The path of the archive, if relevant
191 * @return The format info of the archive, or the corresponding error code if failed. 200 * @return The format info of the archive, or the corresponding error code if failed.
192 */ 201 */
193ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code, FileSys::Path& archive_path); 202ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code,
203 FileSys::Path& archive_path);
194 204
195/** 205/**
196 * Creates a blank SharedExtSaveData archive for the specified extdata ID 206 * Creates a blank SharedExtSaveData archive for the specified extdata ID
@@ -202,7 +212,8 @@ ResultVal<FileSys::ArchiveFormatInfo> GetArchiveFormatInfo(ArchiveIdCode id_code
202 * @param format_info Format information about the new archive 212 * @param format_info Format information about the new archive
203 * @return ResultCode 0 on success or the corresponding code on error 213 * @return ResultCode 0 on success or the corresponding code on error
204 */ 214 */
205ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer, u32 icon_size, const FileSys::ArchiveFormatInfo& format_info); 215ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon_buffer,
216 u32 icon_size, const FileSys::ArchiveFormatInfo& format_info);
206 217
207/** 218/**
208 * Deletes the SharedExtSaveData archive for the specified extdata ID 219 * Deletes the SharedExtSaveData archive for the specified extdata ID
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index 937868747..a0adad634 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -57,14 +57,16 @@ static void OpenFile(Service::Interface* self) {
57 u32* cmd_buff = Kernel::GetCommandBuffer(); 57 u32* cmd_buff = Kernel::GetCommandBuffer();
58 58
59 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); 59 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
60 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 60 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
61 u32 filename_size = cmd_buff[5]; 61 u32 filename_size = cmd_buff[5];
62 FileSys::Mode mode; mode.hex = cmd_buff[6]; 62 FileSys::Mode mode;
63 u32 attributes = cmd_buff[7]; // TODO(Link Mauve): do something with those attributes. 63 mode.hex = cmd_buff[6];
64 u32 filename_ptr = cmd_buff[9]; 64 u32 attributes = cmd_buff[7]; // TODO(Link Mauve): do something with those attributes.
65 u32 filename_ptr = cmd_buff[9];
65 FileSys::Path file_path(filename_type, filename_size, filename_ptr); 66 FileSys::Path file_path(filename_type, filename_size, filename_ptr);
66 67
67 LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex, attributes); 68 LOG_DEBUG(Service_FS, "path=%s, mode=%d attrs=%u", file_path.DebugStr().c_str(), mode.hex,
69 attributes);
68 70
69 ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(archive_handle, file_path, mode); 71 ResultVal<SharedPtr<File>> file_res = OpenFileFromArchive(archive_handle, file_path, mode);
70 cmd_buff[1] = file_res.Code().raw; 72 cmd_buff[1] = file_res.Code().raw;
@@ -98,24 +100,27 @@ static void OpenFile(Service::Interface* self) {
98static void OpenFileDirectly(Service::Interface* self) { 100static void OpenFileDirectly(Service::Interface* self) {
99 u32* cmd_buff = Kernel::GetCommandBuffer(); 101 u32* cmd_buff = Kernel::GetCommandBuffer();
100 102
101 auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[2]); 103 auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[2]);
102 auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[3]); 104 auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[3]);
103 u32 archivename_size = cmd_buff[4]; 105 u32 archivename_size = cmd_buff[4];
104 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[5]); 106 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[5]);
105 u32 filename_size = cmd_buff[6]; 107 u32 filename_size = cmd_buff[6];
106 FileSys::Mode mode; mode.hex = cmd_buff[7]; 108 FileSys::Mode mode;
107 u32 attributes = cmd_buff[8]; // TODO(Link Mauve): do something with those attributes. 109 mode.hex = cmd_buff[7];
108 u32 archivename_ptr = cmd_buff[10]; 110 u32 attributes = cmd_buff[8]; // TODO(Link Mauve): do something with those attributes.
109 u32 filename_ptr = cmd_buff[12]; 111 u32 archivename_ptr = cmd_buff[10];
112 u32 filename_ptr = cmd_buff[12];
110 FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); 113 FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr);
111 FileSys::Path file_path(filename_type, filename_size, filename_ptr); 114 FileSys::Path file_path(filename_type, filename_size, filename_ptr);
112 115
113 LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s file_path=%s, mode=%u attributes=%d", 116 LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s file_path=%s, mode=%u attributes=%d",
114 archive_id, archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode.hex, attributes); 117 archive_id, archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode.hex,
118 attributes);
115 119
116 ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id, archive_path); 120 ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id, archive_path);
117 if (archive_handle.Failed()) { 121 if (archive_handle.Failed()) {
118 LOG_ERROR(Service_FS, "failed to get a handle for archive archive_id=0x%08X archive_path=%s", 122 LOG_ERROR(Service_FS,
123 "failed to get a handle for archive archive_id=0x%08X archive_path=%s",
119 archive_id, archive_path.DebugStr().c_str()); 124 archive_id, archive_path.DebugStr().c_str());
120 cmd_buff[1] = archive_handle.Code().raw; 125 cmd_buff[1] = archive_handle.Code().raw;
121 cmd_buff[3] = 0; 126 cmd_buff[3] = 0;
@@ -149,14 +154,14 @@ static void DeleteFile(Service::Interface* self) {
149 u32* cmd_buff = Kernel::GetCommandBuffer(); 154 u32* cmd_buff = Kernel::GetCommandBuffer();
150 155
151 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); 156 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
152 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 157 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
153 u32 filename_size = cmd_buff[5]; 158 u32 filename_size = cmd_buff[5];
154 u32 filename_ptr = cmd_buff[7]; 159 u32 filename_ptr = cmd_buff[7];
155 160
156 FileSys::Path file_path(filename_type, filename_size, filename_ptr); 161 FileSys::Path file_path(filename_type, filename_size, filename_ptr);
157 162
158 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", 163 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", filename_type, filename_size,
159 filename_type, filename_size, file_path.DebugStr().c_str()); 164 file_path.DebugStr().c_str());
160 165
161 cmd_buff[1] = DeleteFileFromArchive(archive_handle, file_path).raw; 166 cmd_buff[1] = DeleteFileFromArchive(archive_handle, file_path).raw;
162} 167}
@@ -181,22 +186,26 @@ static void RenameFile(Service::Interface* self) {
181 u32* cmd_buff = Kernel::GetCommandBuffer(); 186 u32* cmd_buff = Kernel::GetCommandBuffer();
182 187
183 ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); 188 ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
184 auto src_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 189 auto src_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
185 u32 src_filename_size = cmd_buff[5]; 190 u32 src_filename_size = cmd_buff[5];
186 ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]);; 191 ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]);
187 auto dest_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[8]); 192 ;
188 u32 dest_filename_size = cmd_buff[9]; 193 auto dest_filename_type = static_cast<FileSys::LowPathType>(cmd_buff[8]);
189 u32 src_filename_ptr = cmd_buff[11]; 194 u32 dest_filename_size = cmd_buff[9];
190 u32 dest_filename_ptr = cmd_buff[13]; 195 u32 src_filename_ptr = cmd_buff[11];
196 u32 dest_filename_ptr = cmd_buff[13];
191 197
192 FileSys::Path src_file_path(src_filename_type, src_filename_size, src_filename_ptr); 198 FileSys::Path src_file_path(src_filename_type, src_filename_size, src_filename_ptr);
193 FileSys::Path dest_file_path(dest_filename_type, dest_filename_size, dest_filename_ptr); 199 FileSys::Path dest_file_path(dest_filename_type, dest_filename_size, dest_filename_ptr);
194 200
195 LOG_DEBUG(Service_FS, "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s", 201 LOG_DEBUG(Service_FS,
202 "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s",
196 src_filename_type, src_filename_size, src_file_path.DebugStr().c_str(), 203 src_filename_type, src_filename_size, src_file_path.DebugStr().c_str(),
197 dest_filename_type, dest_filename_size, dest_file_path.DebugStr().c_str()); 204 dest_filename_type, dest_filename_size, dest_file_path.DebugStr().c_str());
198 205
199 cmd_buff[1] = RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle, dest_file_path).raw; 206 cmd_buff[1] = RenameFileBetweenArchives(src_archive_handle, src_file_path, dest_archive_handle,
207 dest_file_path)
208 .raw;
200} 209}
201 210
202/* 211/*
@@ -214,14 +223,14 @@ static void DeleteDirectory(Service::Interface* self) {
214 u32* cmd_buff = Kernel::GetCommandBuffer(); 223 u32* cmd_buff = Kernel::GetCommandBuffer();
215 224
216 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); 225 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
217 auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 226 auto dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
218 u32 dirname_size = cmd_buff[5]; 227 u32 dirname_size = cmd_buff[5];
219 u32 dirname_ptr = cmd_buff[7]; 228 u32 dirname_ptr = cmd_buff[7];
220 229
221 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); 230 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr);
222 231
223 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", 232 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size,
224 dirname_type, dirname_size, dir_path.DebugStr().c_str()); 233 dir_path.DebugStr().c_str());
225 234
226 cmd_buff[1] = DeleteDirectoryFromArchive(archive_handle, dir_path).raw; 235 cmd_buff[1] = DeleteDirectoryFromArchive(archive_handle, dir_path).raw;
227} 236}
@@ -243,14 +252,15 @@ static void CreateFile(Service::Interface* self) {
243 u32* cmd_buff = Kernel::GetCommandBuffer(); 252 u32* cmd_buff = Kernel::GetCommandBuffer();
244 253
245 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); 254 ArchiveHandle archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
246 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 255 auto filename_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
247 u32 filename_size = cmd_buff[5]; 256 u32 filename_size = cmd_buff[5];
248 u64 file_size = ((u64)cmd_buff[8] << 32) | cmd_buff[7]; 257 u64 file_size = ((u64)cmd_buff[8] << 32) | cmd_buff[7];
249 u32 filename_ptr = cmd_buff[10]; 258 u32 filename_ptr = cmd_buff[10];
250 259
251 FileSys::Path file_path(filename_type, filename_size, filename_ptr); 260 FileSys::Path file_path(filename_type, filename_size, filename_ptr);
252 261
253 LOG_DEBUG(Service_FS, "type=%d size=%llu data=%s", filename_type, file_size, file_path.DebugStr().c_str()); 262 LOG_DEBUG(Service_FS, "type=%d size=%llu data=%s", filename_type, file_size,
263 file_path.DebugStr().c_str());
254 264
255 cmd_buff[1] = CreateFileInArchive(archive_handle, file_path, file_size).raw; 265 cmd_buff[1] = CreateFileInArchive(archive_handle, file_path, file_size).raw;
256} 266}
@@ -276,7 +286,8 @@ static void CreateDirectory(Service::Interface* self) {
276 286
277 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); 287 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr);
278 288
279 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); 289 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size,
290 dir_path.DebugStr().c_str());
280 291
281 cmd_buff[1] = CreateDirectoryFromArchive(archive_handle, dir_path).raw; 292 cmd_buff[1] = CreateDirectoryFromArchive(archive_handle, dir_path).raw;
282} 293}
@@ -301,22 +312,25 @@ static void RenameDirectory(Service::Interface* self) {
301 u32* cmd_buff = Kernel::GetCommandBuffer(); 312 u32* cmd_buff = Kernel::GetCommandBuffer();
302 313
303 ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]); 314 ArchiveHandle src_archive_handle = MakeArchiveHandle(cmd_buff[2], cmd_buff[3]);
304 auto src_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]); 315 auto src_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[4]);
305 u32 src_dirname_size = cmd_buff[5]; 316 u32 src_dirname_size = cmd_buff[5];
306 ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]); 317 ArchiveHandle dest_archive_handle = MakeArchiveHandle(cmd_buff[6], cmd_buff[7]);
307 auto dest_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[8]); 318 auto dest_dirname_type = static_cast<FileSys::LowPathType>(cmd_buff[8]);
308 u32 dest_dirname_size = cmd_buff[9]; 319 u32 dest_dirname_size = cmd_buff[9];
309 u32 src_dirname_ptr = cmd_buff[11]; 320 u32 src_dirname_ptr = cmd_buff[11];
310 u32 dest_dirname_ptr = cmd_buff[13]; 321 u32 dest_dirname_ptr = cmd_buff[13];
311 322
312 FileSys::Path src_dir_path(src_dirname_type, src_dirname_size, src_dirname_ptr); 323 FileSys::Path src_dir_path(src_dirname_type, src_dirname_size, src_dirname_ptr);
313 FileSys::Path dest_dir_path(dest_dirname_type, dest_dirname_size, dest_dirname_ptr); 324 FileSys::Path dest_dir_path(dest_dirname_type, dest_dirname_size, dest_dirname_ptr);
314 325
315 LOG_DEBUG(Service_FS, "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s", 326 LOG_DEBUG(Service_FS,
327 "src_type=%d src_size=%d src_data=%s dest_type=%d dest_size=%d dest_data=%s",
316 src_dirname_type, src_dirname_size, src_dir_path.DebugStr().c_str(), 328 src_dirname_type, src_dirname_size, src_dir_path.DebugStr().c_str(),
317 dest_dirname_type, dest_dirname_size, dest_dir_path.DebugStr().c_str()); 329 dest_dirname_type, dest_dirname_size, dest_dir_path.DebugStr().c_str());
318 330
319 cmd_buff[1] = RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path, dest_archive_handle, dest_dir_path).raw; 331 cmd_buff[1] = RenameDirectoryBetweenArchives(src_archive_handle, src_dir_path,
332 dest_archive_handle, dest_dir_path)
333 .raw;
320} 334}
321 335
322/** 336/**
@@ -342,7 +356,8 @@ static void OpenDirectory(Service::Interface* self) {
342 356
343 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr); 357 FileSys::Path dir_path(dirname_type, dirname_size, dirname_ptr);
344 358
345 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size, dir_path.DebugStr().c_str()); 359 LOG_DEBUG(Service_FS, "type=%d size=%d data=%s", dirname_type, dirname_size,
360 dir_path.DebugStr().c_str());
346 361
347 ResultVal<SharedPtr<Directory>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path); 362 ResultVal<SharedPtr<Directory>> dir_res = OpenDirectoryFromArchive(archive_handle, dir_path);
348 cmd_buff[1] = dir_res.Code().raw; 363 cmd_buff[1] = dir_res.Code().raw;
@@ -370,13 +385,14 @@ static void OpenDirectory(Service::Interface* self) {
370static void OpenArchive(Service::Interface* self) { 385static void OpenArchive(Service::Interface* self) {
371 u32* cmd_buff = Kernel::GetCommandBuffer(); 386 u32* cmd_buff = Kernel::GetCommandBuffer();
372 387
373 auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[1]); 388 auto archive_id = static_cast<FS::ArchiveIdCode>(cmd_buff[1]);
374 auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]); 389 auto archivename_type = static_cast<FileSys::LowPathType>(cmd_buff[2]);
375 u32 archivename_size = cmd_buff[3]; 390 u32 archivename_size = cmd_buff[3];
376 u32 archivename_ptr = cmd_buff[5]; 391 u32 archivename_ptr = cmd_buff[5];
377 FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); 392 FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr);
378 393
379 LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s", archive_id, archive_path.DebugStr().c_str()); 394 LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s", archive_id,
395 archive_path.DebugStr().c_str());
380 396
381 ResultVal<ArchiveHandle> handle = OpenArchive(archive_id, archive_path); 397 ResultVal<ArchiveHandle> handle = OpenArchive(archive_id, archive_path);
382 cmd_buff[1] = handle.Code().raw; 398 cmd_buff[1] = handle.Code().raw;
@@ -385,7 +401,8 @@ static void OpenArchive(Service::Interface* self) {
385 cmd_buff[3] = (*handle >> 32) & 0xFFFFFFFF; 401 cmd_buff[3] = (*handle >> 32) & 0xFFFFFFFF;
386 } else { 402 } else {
387 cmd_buff[2] = cmd_buff[3] = 0; 403 cmd_buff[2] = cmd_buff[3] = 0;
388 LOG_ERROR(Service_FS, "failed to get a handle for archive archive_id=0x%08X archive_path=%s", 404 LOG_ERROR(Service_FS,
405 "failed to get a handle for archive archive_id=0x%08X archive_path=%s",
389 archive_id, archive_path.DebugStr().c_str()); 406 archive_id, archive_path.DebugStr().c_str());
390 } 407 }
391} 408}
@@ -471,7 +488,8 @@ static void FormatSaveData(Service::Interface* self) {
471 if (archive_id != FS::ArchiveIdCode::SaveData) { 488 if (archive_id != FS::ArchiveIdCode::SaveData) {
472 LOG_ERROR(Service_FS, "tried to format an archive different than SaveData, %u", archive_id); 489 LOG_ERROR(Service_FS, "tried to format an archive different than SaveData, %u", archive_id);
473 cmd_buff[1] = ResultCode(ErrorDescription::FS_InvalidPath, ErrorModule::FS, 490 cmd_buff[1] = ResultCode(ErrorDescription::FS_InvalidPath, ErrorModule::FS,
474 ErrorSummary::InvalidArgument, ErrorLevel::Usage).raw; 491 ErrorSummary::InvalidArgument, ErrorLevel::Usage)
492 .raw;
475 return; 493 return;
476 } 494 }
477 495
@@ -571,18 +589,21 @@ static void CreateExtSaveData(Service::Interface* self) {
571 u32 icon_size = cmd_buff[9]; 589 u32 icon_size = cmd_buff[9];
572 VAddr icon_buffer = cmd_buff[11]; 590 VAddr icon_buffer = cmd_buff[11];
573 591
574 LOG_WARNING(Service_FS, "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X " 592 LOG_WARNING(
575 "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X " 593 Service_FS,
576 "icon_size=%08X icon_descriptor=%08X icon_buffer=%08X", save_high, save_low, 594 "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X "
577 cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7], cmd_buff[8], icon_size, 595 "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X "
578 cmd_buff[10], icon_buffer); 596 "icon_size=%08X icon_descriptor=%08X icon_buffer=%08X",
597 save_high, save_low, cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7],
598 cmd_buff[8], icon_size, cmd_buff[10], icon_buffer);
579 599
580 FileSys::ArchiveFormatInfo format_info; 600 FileSys::ArchiveFormatInfo format_info;
581 format_info.number_directories = cmd_buff[5]; 601 format_info.number_directories = cmd_buff[5];
582 format_info.number_files = cmd_buff[6]; 602 format_info.number_files = cmd_buff[6];
583 format_info.duplicate_data = false; 603 format_info.duplicate_data = false;
584 format_info.total_size = 0; 604 format_info.total_size = 0;
585 cmd_buff[1] = CreateExtSaveData(media_type, save_high, save_low, icon_buffer, icon_size, format_info).raw; 605 cmd_buff[1] =
606 CreateExtSaveData(media_type, save_high, save_low, icon_buffer, icon_size, format_info).raw;
586} 607}
587 608
588/** 609/**
@@ -604,7 +625,7 @@ static void DeleteExtSaveData(Service::Interface* self) {
604 u32 unknown = cmd_buff[4]; // TODO(Subv): Figure out what this is 625 u32 unknown = cmd_buff[4]; // TODO(Subv): Figure out what this is
605 626
606 LOG_WARNING(Service_FS, "(STUBBED) save_low=%08X save_high=%08X media_type=%08X unknown=%08X", 627 LOG_WARNING(Service_FS, "(STUBBED) save_low=%08X save_high=%08X media_type=%08X unknown=%08X",
607 save_low, save_high, cmd_buff[1] & 0xFF, unknown); 628 save_low, save_high, cmd_buff[1] & 0xFF, unknown);
608 629
609 cmd_buff[1] = DeleteExtSaveData(media_type, save_high, save_low).raw; 630 cmd_buff[1] = DeleteExtSaveData(media_type, save_high, save_low).raw;
610} 631}
@@ -662,10 +683,13 @@ static void CreateSystemSaveData(Service::Interface* self) {
662 u32 savedata_high = cmd_buff[1]; 683 u32 savedata_high = cmd_buff[1];
663 u32 savedata_low = cmd_buff[2]; 684 u32 savedata_low = cmd_buff[2];
664 685
665 LOG_WARNING(Service_FS, "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X " 686 LOG_WARNING(
666 "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X " 687 Service_FS,
667 "cmd_buff[9]=%08X", savedata_high, savedata_low, cmd_buff[3], cmd_buff[4], cmd_buff[5], 688 "(STUBBED) savedata_high=%08X savedata_low=%08X cmd_buff[3]=%08X "
668 cmd_buff[6], cmd_buff[7], cmd_buff[8], cmd_buff[9]); 689 "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X "
690 "cmd_buff[9]=%08X",
691 savedata_high, savedata_low, cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6],
692 cmd_buff[7], cmd_buff[8], cmd_buff[9]);
669 693
670 cmd_buff[1] = CreateSystemSaveData(savedata_high, savedata_low).raw; 694 cmd_buff[1] = CreateSystemSaveData(savedata_high, savedata_low).raw;
671} 695}
@@ -692,10 +716,13 @@ static void CreateLegacySystemSaveData(Service::Interface* self) {
692 u32* cmd_buff = Kernel::GetCommandBuffer(); 716 u32* cmd_buff = Kernel::GetCommandBuffer();
693 u32 savedata_id = cmd_buff[1]; 717 u32 savedata_id = cmd_buff[1];
694 718
695 LOG_WARNING(Service_FS, "(STUBBED) savedata_id=%08X cmd_buff[3]=%08X " 719 LOG_WARNING(
696 "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X " 720 Service_FS,
697 "cmd_buff[9]=%08X", savedata_id, cmd_buff[3], cmd_buff[4], cmd_buff[5], 721 "(STUBBED) savedata_id=%08X cmd_buff[3]=%08X "
698 cmd_buff[6], cmd_buff[7], cmd_buff[8], cmd_buff[9]); 722 "cmd_buff[4]=%08X cmd_buff[5]=%08X cmd_buff[6]=%08X cmd_buff[7]=%08X cmd_buff[8]=%08X "
723 "cmd_buff[9]=%08X",
724 savedata_id, cmd_buff[3], cmd_buff[4], cmd_buff[5], cmd_buff[6], cmd_buff[7], cmd_buff[8],
725 cmd_buff[9]);
699 726
700 cmd_buff[0] = IPC::MakeHeader(0x810, 0x1, 0); 727 cmd_buff[0] = IPC::MakeHeader(0x810, 0x1, 0);
701 // With this command, the SystemSaveData always has save_high = 0 (Always created in the NAND) 728 // With this command, the SystemSaveData always has save_high = 0 (Always created in the NAND)
@@ -721,8 +748,8 @@ static void InitializeWithSdkVersion(Service::Interface* self) {
721 748
722 cmd_buff[1] = RESULT_SUCCESS.raw; 749 cmd_buff[1] = RESULT_SUCCESS.raw;
723 750
724 LOG_WARNING(Service_FS, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, unk3=0x%08X", 751 LOG_WARNING(Service_FS, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, unk3=0x%08X", unk1, unk2,
725 unk1, unk2, unk3); 752 unk3);
726} 753}
727 754
728/** 755/**
@@ -834,115 +861,114 @@ static void GetFormatInfo(Service::Interface* self) {
834} 861}
835 862
836const Interface::FunctionInfo FunctionTable[] = { 863const Interface::FunctionInfo FunctionTable[] = {
837 {0x000100C6, nullptr, "Dummy1"}, 864 {0x000100C6, nullptr, "Dummy1"},
838 {0x040100C4, nullptr, "Control"}, 865 {0x040100C4, nullptr, "Control"},
839 {0x08010002, Initialize, "Initialize"}, 866 {0x08010002, Initialize, "Initialize"},
840 {0x080201C2, OpenFile, "OpenFile"}, 867 {0x080201C2, OpenFile, "OpenFile"},
841 {0x08030204, OpenFileDirectly, "OpenFileDirectly"}, 868 {0x08030204, OpenFileDirectly, "OpenFileDirectly"},
842 {0x08040142, DeleteFile, "DeleteFile"}, 869 {0x08040142, DeleteFile, "DeleteFile"},
843 {0x08050244, RenameFile, "RenameFile"}, 870 {0x08050244, RenameFile, "RenameFile"},
844 {0x08060142, DeleteDirectory, "DeleteDirectory"}, 871 {0x08060142, DeleteDirectory, "DeleteDirectory"},
845 {0x08070142, nullptr, "DeleteDirectoryRecursively"}, 872 {0x08070142, nullptr, "DeleteDirectoryRecursively"},
846 {0x08080202, CreateFile, "CreateFile"}, 873 {0x08080202, CreateFile, "CreateFile"},
847 {0x08090182, CreateDirectory, "CreateDirectory"}, 874 {0x08090182, CreateDirectory, "CreateDirectory"},
848 {0x080A0244, RenameDirectory, "RenameDirectory"}, 875 {0x080A0244, RenameDirectory, "RenameDirectory"},
849 {0x080B0102, OpenDirectory, "OpenDirectory"}, 876 {0x080B0102, OpenDirectory, "OpenDirectory"},
850 {0x080C00C2, OpenArchive, "OpenArchive"}, 877 {0x080C00C2, OpenArchive, "OpenArchive"},
851 {0x080D0144, nullptr, "ControlArchive"}, 878 {0x080D0144, nullptr, "ControlArchive"},
852 {0x080E0080, CloseArchive, "CloseArchive"}, 879 {0x080E0080, CloseArchive, "CloseArchive"},
853 {0x080F0180, FormatThisUserSaveData, "FormatThisUserSaveData"}, 880 {0x080F0180, FormatThisUserSaveData, "FormatThisUserSaveData"},
854 {0x08100200, CreateLegacySystemSaveData, "CreateLegacySystemSaveData"}, 881 {0x08100200, CreateLegacySystemSaveData, "CreateLegacySystemSaveData"},
855 {0x08110040, nullptr, "DeleteSystemSaveData"}, 882 {0x08110040, nullptr, "DeleteSystemSaveData"},
856 {0x08120080, GetFreeBytes, "GetFreeBytes"}, 883 {0x08120080, GetFreeBytes, "GetFreeBytes"},
857 {0x08130000, nullptr, "GetCardType"}, 884 {0x08130000, nullptr, "GetCardType"},
858 {0x08140000, nullptr, "GetSdmcArchiveResource"}, 885 {0x08140000, nullptr, "GetSdmcArchiveResource"},
859 {0x08150000, nullptr, "GetNandArchiveResource"}, 886 {0x08150000, nullptr, "GetNandArchiveResource"},
860 {0x08160000, nullptr, "GetSdmcFatfsError"}, 887 {0x08160000, nullptr, "GetSdmcFatfsError"},
861 {0x08170000, IsSdmcDetected, "IsSdmcDetected"}, 888 {0x08170000, IsSdmcDetected, "IsSdmcDetected"},
862 {0x08180000, IsSdmcWriteable, "IsSdmcWritable"}, 889 {0x08180000, IsSdmcWriteable, "IsSdmcWritable"},
863 {0x08190042, nullptr, "GetSdmcCid"}, 890 {0x08190042, nullptr, "GetSdmcCid"},
864 {0x081A0042, nullptr, "GetNandCid"}, 891 {0x081A0042, nullptr, "GetNandCid"},
865 {0x081B0000, nullptr, "GetSdmcSpeedInfo"}, 892 {0x081B0000, nullptr, "GetSdmcSpeedInfo"},
866 {0x081C0000, nullptr, "GetNandSpeedInfo"}, 893 {0x081C0000, nullptr, "GetNandSpeedInfo"},
867 {0x081D0042, nullptr, "GetSdmcLog"}, 894 {0x081D0042, nullptr, "GetSdmcLog"},
868 {0x081E0042, nullptr, "GetNandLog"}, 895 {0x081E0042, nullptr, "GetNandLog"},
869 {0x081F0000, nullptr, "ClearSdmcLog"}, 896 {0x081F0000, nullptr, "ClearSdmcLog"},
870 {0x08200000, nullptr, "ClearNandLog"}, 897 {0x08200000, nullptr, "ClearNandLog"},
871 {0x08210000, CardSlotIsInserted, "CardSlotIsInserted"}, 898 {0x08210000, CardSlotIsInserted, "CardSlotIsInserted"},
872 {0x08220000, nullptr, "CardSlotPowerOn"}, 899 {0x08220000, nullptr, "CardSlotPowerOn"},
873 {0x08230000, nullptr, "CardSlotPowerOff"}, 900 {0x08230000, nullptr, "CardSlotPowerOff"},
874 {0x08240000, nullptr, "CardSlotGetCardIFPowerStatus"}, 901 {0x08240000, nullptr, "CardSlotGetCardIFPowerStatus"},
875 {0x08250040, nullptr, "CardNorDirectCommand"}, 902 {0x08250040, nullptr, "CardNorDirectCommand"},
876 {0x08260080, nullptr, "CardNorDirectCommandWithAddress"}, 903 {0x08260080, nullptr, "CardNorDirectCommandWithAddress"},
877 {0x08270082, nullptr, "CardNorDirectRead"}, 904 {0x08270082, nullptr, "CardNorDirectRead"},
878 {0x082800C2, nullptr, "CardNorDirectReadWithAddress"}, 905 {0x082800C2, nullptr, "CardNorDirectReadWithAddress"},
879 {0x08290082, nullptr, "CardNorDirectWrite"}, 906 {0x08290082, nullptr, "CardNorDirectWrite"},
880 {0x082A00C2, nullptr, "CardNorDirectWriteWithAddress"}, 907 {0x082A00C2, nullptr, "CardNorDirectWriteWithAddress"},
881 {0x082B00C2, nullptr, "CardNorDirectRead_4xIO"}, 908 {0x082B00C2, nullptr, "CardNorDirectRead_4xIO"},
882 {0x082C0082, nullptr, "CardNorDirectCpuWriteWithoutVerify"}, 909 {0x082C0082, nullptr, "CardNorDirectCpuWriteWithoutVerify"},
883 {0x082D0040, nullptr, "CardNorDirectSectorEraseWithoutVerify"}, 910 {0x082D0040, nullptr, "CardNorDirectSectorEraseWithoutVerify"},
884 {0x082E0040, nullptr, "GetProductInfo"}, 911 {0x082E0040, nullptr, "GetProductInfo"},
885 {0x082F0040, nullptr, "GetProgramLaunchInfo"}, 912 {0x082F0040, nullptr, "GetProgramLaunchInfo"},
886 {0x08300182, nullptr, "CreateExtSaveData"}, 913 {0x08300182, nullptr, "CreateExtSaveData"},
887 {0x08310180, nullptr, "CreateSharedExtSaveData"}, 914 {0x08310180, nullptr, "CreateSharedExtSaveData"},
888 {0x08320102, nullptr, "ReadExtSaveDataIcon"}, 915 {0x08320102, nullptr, "ReadExtSaveDataIcon"},
889 {0x08330082, nullptr, "EnumerateExtSaveData"}, 916 {0x08330082, nullptr, "EnumerateExtSaveData"},
890 {0x08340082, nullptr, "EnumerateSharedExtSaveData"}, 917 {0x08340082, nullptr, "EnumerateSharedExtSaveData"},
891 {0x08350080, nullptr, "DeleteExtSaveData"}, 918 {0x08350080, nullptr, "DeleteExtSaveData"},
892 {0x08360080, nullptr, "DeleteSharedExtSaveData"}, 919 {0x08360080, nullptr, "DeleteSharedExtSaveData"},
893 {0x08370040, nullptr, "SetCardSpiBaudRate"}, 920 {0x08370040, nullptr, "SetCardSpiBaudRate"},
894 {0x08380040, nullptr, "SetCardSpiBusMode"}, 921 {0x08380040, nullptr, "SetCardSpiBusMode"},
895 {0x08390000, nullptr, "SendInitializeInfoTo9"}, 922 {0x08390000, nullptr, "SendInitializeInfoTo9"},
896 {0x083A0100, nullptr, "GetSpecialContentIndex"}, 923 {0x083A0100, nullptr, "GetSpecialContentIndex"},
897 {0x083B00C2, nullptr, "GetLegacyRomHeader"}, 924 {0x083B00C2, nullptr, "GetLegacyRomHeader"},
898 {0x083C00C2, nullptr, "GetLegacyBannerData"}, 925 {0x083C00C2, nullptr, "GetLegacyBannerData"},
899 {0x083D0100, nullptr, "CheckAuthorityToAccessExtSaveData"}, 926 {0x083D0100, nullptr, "CheckAuthorityToAccessExtSaveData"},
900 {0x083E00C2, nullptr, "QueryTotalQuotaSize"}, 927 {0x083E00C2, nullptr, "QueryTotalQuotaSize"},
901 {0x083F00C0, nullptr, "GetExtDataBlockSize"}, 928 {0x083F00C0, nullptr, "GetExtDataBlockSize"},
902 {0x08400040, nullptr, "AbnegateAccessRight"}, 929 {0x08400040, nullptr, "AbnegateAccessRight"},
903 {0x08410000, nullptr, "DeleteSdmcRoot"}, 930 {0x08410000, nullptr, "DeleteSdmcRoot"},
904 {0x08420040, nullptr, "DeleteAllExtSaveDataOnNand"}, 931 {0x08420040, nullptr, "DeleteAllExtSaveDataOnNand"},
905 {0x08430000, nullptr, "InitializeCtrFileSystem"}, 932 {0x08430000, nullptr, "InitializeCtrFileSystem"},
906 {0x08440000, nullptr, "CreateSeed"}, 933 {0x08440000, nullptr, "CreateSeed"},
907 {0x084500C2, GetFormatInfo, "GetFormatInfo"}, 934 {0x084500C2, GetFormatInfo, "GetFormatInfo"},
908 {0x08460102, nullptr, "GetLegacyRomHeader2"}, 935 {0x08460102, nullptr, "GetLegacyRomHeader2"},
909 {0x08470180, nullptr, "FormatCtrCardUserSaveData"}, 936 {0x08470180, nullptr, "FormatCtrCardUserSaveData"},
910 {0x08480042, nullptr, "GetSdmcCtrRootPath"}, 937 {0x08480042, nullptr, "GetSdmcCtrRootPath"},
911 {0x08490040, GetArchiveResource, "GetArchiveResource"}, 938 {0x08490040, GetArchiveResource, "GetArchiveResource"},
912 {0x084A0002, nullptr, "ExportIntegrityVerificationSeed"}, 939 {0x084A0002, nullptr, "ExportIntegrityVerificationSeed"},
913 {0x084B0002, nullptr, "ImportIntegrityVerificationSeed"}, 940 {0x084B0002, nullptr, "ImportIntegrityVerificationSeed"},
914 {0x084C0242, FormatSaveData, "FormatSaveData"}, 941 {0x084C0242, FormatSaveData, "FormatSaveData"},
915 {0x084D0102, nullptr, "GetLegacySubBannerData"}, 942 {0x084D0102, nullptr, "GetLegacySubBannerData"},
916 {0x084E0342, nullptr, "UpdateSha256Context"}, 943 {0x084E0342, nullptr, "UpdateSha256Context"},
917 {0x084F0102, nullptr, "ReadSpecialFile"}, 944 {0x084F0102, nullptr, "ReadSpecialFile"},
918 {0x08500040, nullptr, "GetSpecialFileSize"}, 945 {0x08500040, nullptr, "GetSpecialFileSize"},
919 {0x08510242, CreateExtSaveData, "CreateExtSaveData"}, 946 {0x08510242, CreateExtSaveData, "CreateExtSaveData"},
920 {0x08520100, DeleteExtSaveData, "DeleteExtSaveData"}, 947 {0x08520100, DeleteExtSaveData, "DeleteExtSaveData"},
921 {0x08530142, nullptr, "ReadExtSaveDataIcon"}, 948 {0x08530142, nullptr, "ReadExtSaveDataIcon"},
922 {0x085400C0, nullptr, "GetExtDataBlockSize"}, 949 {0x085400C0, nullptr, "GetExtDataBlockSize"},
923 {0x08550102, nullptr, "EnumerateExtSaveData"}, 950 {0x08550102, nullptr, "EnumerateExtSaveData"},
924 {0x08560240, CreateSystemSaveData, "CreateSystemSaveData"}, 951 {0x08560240, CreateSystemSaveData, "CreateSystemSaveData"},
925 {0x08570080, DeleteSystemSaveData, "DeleteSystemSaveData"}, 952 {0x08570080, DeleteSystemSaveData, "DeleteSystemSaveData"},
926 {0x08580000, nullptr, "StartDeviceMoveAsSource"}, 953 {0x08580000, nullptr, "StartDeviceMoveAsSource"},
927 {0x08590200, nullptr, "StartDeviceMoveAsDestination"}, 954 {0x08590200, nullptr, "StartDeviceMoveAsDestination"},
928 {0x085A00C0, nullptr, "SetArchivePriority"}, 955 {0x085A00C0, nullptr, "SetArchivePriority"},
929 {0x085B0080, nullptr, "GetArchivePriority"}, 956 {0x085B0080, nullptr, "GetArchivePriority"},
930 {0x085C00C0, nullptr, "SetCtrCardLatencyParameter"}, 957 {0x085C00C0, nullptr, "SetCtrCardLatencyParameter"},
931 {0x085D01C0, nullptr, "SetFsCompatibilityInfo"}, 958 {0x085D01C0, nullptr, "SetFsCompatibilityInfo"},
932 {0x085E0040, nullptr, "ResetCardCompatibilityParameter"}, 959 {0x085E0040, nullptr, "ResetCardCompatibilityParameter"},
933 {0x085F0040, nullptr, "SwitchCleanupInvalidSaveData"}, 960 {0x085F0040, nullptr, "SwitchCleanupInvalidSaveData"},
934 {0x08600042, nullptr, "EnumerateSystemSaveData"}, 961 {0x08600042, nullptr, "EnumerateSystemSaveData"},
935 {0x08610042, InitializeWithSdkVersion, "InitializeWithSdkVersion"}, 962 {0x08610042, InitializeWithSdkVersion, "InitializeWithSdkVersion"},
936 {0x08620040, SetPriority, "SetPriority"}, 963 {0x08620040, SetPriority, "SetPriority"},
937 {0x08630000, GetPriority, "GetPriority"}, 964 {0x08630000, GetPriority, "GetPriority"},
938 {0x08640000, nullptr, "GetNandInfo"}, 965 {0x08640000, nullptr, "GetNandInfo"},
939 {0x08650140, nullptr, "SetSaveDataSecureValue"}, 966 {0x08650140, nullptr, "SetSaveDataSecureValue"},
940 {0x086600C0, nullptr, "GetSaveDataSecureValue"}, 967 {0x086600C0, nullptr, "GetSaveDataSecureValue"},
941 {0x086700C4, nullptr, "ControlSecureSave"}, 968 {0x086700C4, nullptr, "ControlSecureSave"},
942 {0x08680000, nullptr, "GetMediaType"}, 969 {0x08680000, nullptr, "GetMediaType"},
943 {0x08690000, nullptr, "GetNandEraseCount"}, 970 {0x08690000, nullptr, "GetNandEraseCount"},
944 {0x086A0082, nullptr, "ReadNandReport"} 971 {0x086A0082, nullptr, "ReadNandReport"}};
945};
946 972
947//////////////////////////////////////////////////////////////////////////////////////////////////// 973////////////////////////////////////////////////////////////////////////////////////////////////////
948// Interface class 974// Interface class
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index ec565f46d..b273aac47 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -5,16 +5,16 @@
5#include "common/bit_field.h" 5#include "common/bit_field.h"
6#include "common/microprofile.h" 6#include "common/microprofile.h"
7 7
8#include "core/memory.h"
9#include "core/hle/kernel/event.h" 8#include "core/hle/kernel/event.h"
10#include "core/hle/kernel/shared_memory.h" 9#include "core/hle/kernel/shared_memory.h"
11#include "core/hle/result.h" 10#include "core/hle/result.h"
12#include "core/hw/hw.h"
13#include "core/hw/gpu.h" 11#include "core/hw/gpu.h"
12#include "core/hw/hw.h"
14#include "core/hw/lcd.h" 13#include "core/hw/lcd.h"
14#include "core/memory.h"
15 15
16#include "video_core/gpu_debugger.h"
17#include "video_core/debug_utils/debug_utils.h" 16#include "video_core/debug_utils/debug_utils.h"
17#include "video_core/gpu_debugger.h"
18 18
19#include "gsp_gpu.h" 19#include "gsp_gpu.h"
20 20
@@ -29,12 +29,16 @@ const static u32 REGS_BEGIN = 0x1EB00000;
29 29
30namespace GSP_GPU { 30namespace GSP_GPU {
31 31
32const ResultCode ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED(ErrorDescription::OutofRangeOrMisalignedAddress, ErrorModule::GX, 32const ResultCode
33 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02A01 33 ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED(ErrorDescription::OutofRangeOrMisalignedAddress,
34 ErrorModule::GX, ErrorSummary::InvalidArgument,
35 ErrorLevel::Usage); // 0xE0E02A01
34const ResultCode ERR_GSP_REGS_MISALIGNED(ErrorDescription::MisalignedSize, ErrorModule::GX, 36const ResultCode ERR_GSP_REGS_MISALIGNED(ErrorDescription::MisalignedSize, ErrorModule::GX,
35 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02BF2 37 ErrorSummary::InvalidArgument,
38 ErrorLevel::Usage); // 0xE0E02BF2
36const ResultCode ERR_GSP_REGS_INVALID_SIZE(ErrorDescription::InvalidSize, ErrorModule::GX, 39const ResultCode ERR_GSP_REGS_INVALID_SIZE(ErrorDescription::InvalidSize, ErrorModule::GX,
37 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02BEC 40 ErrorSummary::InvalidArgument,
41 ErrorLevel::Usage); // 0xE0E02BEC
38 42
39/// Event triggered when GSP interrupt has been signalled 43/// Event triggered when GSP interrupt has been signalled
40Kernel::SharedPtr<Kernel::Event> g_interrupt_event; 44Kernel::SharedPtr<Kernel::Event> g_interrupt_event;
@@ -73,7 +77,8 @@ static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) {
73 * @param data Data to be written 77 * @param data Data to be written
74 */ 78 */
75static void WriteSingleHWReg(u32 base_address, u32 data) { 79static void WriteSingleHWReg(u32 base_address, u32 data) {
76 DEBUG_ASSERT_MSG((base_address & 3) == 0 && base_address < 0x420000, "Write address out of range or misaligned"); 80 DEBUG_ASSERT_MSG((base_address & 3) == 0 && base_address < 0x420000,
81 "Write address out of range or misaligned");
77 HW::Write<u32>(base_address + REGS_BEGIN, data); 82 HW::Write<u32>(base_address + REGS_BEGIN, data);
78} 83}
79 84
@@ -90,7 +95,8 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, VAddr data_va
90 const u32 max_size_in_bytes = 0x80; 95 const u32 max_size_in_bytes = 0x80;
91 96
92 if (base_address & 3 || base_address >= 0x420000) { 97 if (base_address & 3 || base_address >= 0x420000) {
93 LOG_ERROR(Service_GSP, "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)", 98 LOG_ERROR(Service_GSP,
99 "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)",
94 base_address, size_in_bytes); 100 base_address, size_in_bytes);
95 return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED; 101 return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED;
96 } else if (size_in_bytes <= max_size_in_bytes) { 102 } else if (size_in_bytes <= max_size_in_bytes) {
@@ -124,12 +130,14 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, VAddr data_va
124 * @param masks A pointer to the masks 130 * @param masks A pointer to the masks
125 * @return RESULT_SUCCESS if the parameters are valid, error code otherwise 131 * @return RESULT_SUCCESS if the parameters are valid, error code otherwise
126 */ 132 */
127static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, VAddr data_vaddr, VAddr masks_vaddr) { 133static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, VAddr data_vaddr,
134 VAddr masks_vaddr) {
128 // This magic number is verified to be done by the gsp module 135 // This magic number is verified to be done by the gsp module
129 const u32 max_size_in_bytes = 0x80; 136 const u32 max_size_in_bytes = 0x80;
130 137
131 if (base_address & 3 || base_address >= 0x420000) { 138 if (base_address & 3 || base_address >= 0x420000) {
132 LOG_ERROR(Service_GSP, "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)", 139 LOG_ERROR(Service_GSP,
140 "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)",
133 base_address, size_in_bytes); 141 base_address, size_in_bytes);
134 return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED; 142 return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED;
135 } else if (size_in_bytes <= max_size_in_bytes) { 143 } else if (size_in_bytes <= max_size_in_bytes) {
@@ -214,7 +222,8 @@ static void ReadHWRegs(Service::Interface* self) {
214 222
215 // TODO: Return proper error codes 223 // TODO: Return proper error codes
216 if (reg_addr + size >= 0x420000) { 224 if (reg_addr + size >= 0x420000) {
217 LOG_ERROR(Service_GSP, "Read address out of range! (address=0x%08x, size=0x%08x)", reg_addr, size); 225 LOG_ERROR(Service_GSP, "Read address out of range! (address=0x%08x, size=0x%08x)", reg_addr,
226 size);
218 return; 227 return;
219 } 228 }
220 229
@@ -243,22 +252,34 @@ ResultCode SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) {
243 PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left); 252 PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left);
244 PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right); 253 PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right);
245 if (info.active_fb == 0) { 254 if (info.active_fb == 0) {
246 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), 255 WriteSingleHWReg(
247 phys_address_left); 256 base_address +
248 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), 257 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)),
249 phys_address_right); 258 phys_address_left);
259 WriteSingleHWReg(
260 base_address +
261 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)),
262 phys_address_right);
250 } else { 263 } else {
251 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), 264 WriteSingleHWReg(
252 phys_address_left); 265 base_address +
253 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), 266 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)),
254 phys_address_right); 267 phys_address_left);
268 WriteSingleHWReg(
269 base_address +
270 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)),
271 phys_address_right);
255 } 272 }
256 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), 273 WriteSingleHWReg(base_address +
274 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)),
257 info.stride); 275 info.stride);
258 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), 276 WriteSingleHWReg(
259 info.format); 277 base_address +
260 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), 278 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)),
261 info.shown_fb); 279 info.format);
280 WriteSingleHWReg(
281 base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)),
282 info.shown_fb);
262 283
263 if (Pica::g_debug_context) 284 if (Pica::g_debug_context)
264 Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr); 285 Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr);
@@ -305,15 +326,15 @@ static void SetBufferSwap(Service::Interface* self) {
305static void FlushDataCache(Service::Interface* self) { 326static void FlushDataCache(Service::Interface* self) {
306 u32* cmd_buff = Kernel::GetCommandBuffer(); 327 u32* cmd_buff = Kernel::GetCommandBuffer();
307 u32 address = cmd_buff[1]; 328 u32 address = cmd_buff[1];
308 u32 size = cmd_buff[2]; 329 u32 size = cmd_buff[2];
309 u32 process = cmd_buff[4]; 330 u32 process = cmd_buff[4];
310 331
311 // TODO(purpasmart96): Verify return header on HW 332 // TODO(purpasmart96): Verify return header on HW
312 333
313 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 334 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
314 335
315 LOG_DEBUG(Service_GSP, "(STUBBED) called address=0x%08X, size=0x%08X, process=0x%08X", 336 LOG_DEBUG(Service_GSP, "(STUBBED) called address=0x%08X, size=0x%08X, process=0x%08X", address,
316 address, size, process); 337 size, process);
317} 338}
318 339
319/** 340/**
@@ -356,11 +377,12 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) {
356 // This specific code is required for a successful initialization, rather than 0 377 // This specific code is required for a successful initialization, rather than 0
357 first_initialization = false; 378 first_initialization = false;
358 cmd_buff[1] = ResultCode(ErrorDescription::GPU_FirstInitialization, ErrorModule::GX, 379 cmd_buff[1] = ResultCode(ErrorDescription::GPU_FirstInitialization, ErrorModule::GX,
359 ErrorSummary::Success, ErrorLevel::Success).raw; 380 ErrorSummary::Success, ErrorLevel::Success)
381 .raw;
360 } else { 382 } else {
361 cmd_buff[1] = RESULT_SUCCESS.raw; 383 cmd_buff[1] = RESULT_SUCCESS.raw;
362 } 384 }
363 cmd_buff[2] = g_thread_id++; // Thread ID 385 cmd_buff[2] = g_thread_id++; // Thread ID
364 cmd_buff[4] = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); // GSP shared memory 386 cmd_buff[4] = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); // GSP shared memory
365 387
366 g_interrupt_event->Signal(); // TODO(bunnei): Is this correct? 388 g_interrupt_event->Signal(); // TODO(bunnei): Is this correct?
@@ -416,7 +438,8 @@ void SignalInterrupt(InterruptId interrupt_id) {
416 // Update framebuffer information if requested 438 // Update framebuffer information if requested
417 // TODO(yuriks): Confirm where this code should be called. It is definitely updated without 439 // TODO(yuriks): Confirm where this code should be called. It is definitely updated without
418 // executing any GSP commands, only waiting on the event. 440 // executing any GSP commands, only waiting on the event.
419 int screen_id = (interrupt_id == InterruptId::PDC0) ? 0 : (interrupt_id == InterruptId::PDC1) ? 1 : -1; 441 int screen_id =
442 (interrupt_id == InterruptId::PDC0) ? 0 : (interrupt_id == InterruptId::PDC1) ? 1 : -1;
420 if (screen_id != -1) { 443 if (screen_id != -1) {
421 FrameBufferUpdate* info = GetFrameBufferInfo(thread_id, screen_id); 444 FrameBufferUpdate* info = GetFrameBufferInfo(thread_id, screen_id);
422 if (info->is_dirty) { 445 if (info->is_dirty) {
@@ -440,25 +463,27 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
440 switch (command.id) { 463 switch (command.id) {
441 464
442 // GX request DMA - typically used for copying memory from GSP heap to VRAM 465 // GX request DMA - typically used for copying memory from GSP heap to VRAM
443 case CommandId::REQUEST_DMA: 466 case CommandId::REQUEST_DMA: {
444 {
445 MICROPROFILE_SCOPE(GPU_GSP_DMA); 467 MICROPROFILE_SCOPE(GPU_GSP_DMA);
446 468
447 // TODO: Consider attempting rasterizer-accelerated surface blit if that usage is ever possible/likely 469 // TODO: Consider attempting rasterizer-accelerated surface blit if that usage is ever
448 Memory::RasterizerFlushRegion(Memory::VirtualToPhysicalAddress(command.dma_request.source_address), 470 // possible/likely
449 command.dma_request.size); 471 Memory::RasterizerFlushRegion(
450 Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(command.dma_request.dest_address), 472 Memory::VirtualToPhysicalAddress(command.dma_request.source_address),
451 command.dma_request.size); 473 command.dma_request.size);
474 Memory::RasterizerFlushAndInvalidateRegion(
475 Memory::VirtualToPhysicalAddress(command.dma_request.dest_address),
476 command.dma_request.size);
452 477
453 // TODO(Subv): These memory accesses should not go through the application's memory mapping. 478 // TODO(Subv): These memory accesses should not go through the application's memory mapping.
454 // They should go through the GSP module's memory mapping. 479 // They should go through the GSP module's memory mapping.
455 Memory::CopyBlock(command.dma_request.dest_address, command.dma_request.source_address, command.dma_request.size); 480 Memory::CopyBlock(command.dma_request.dest_address, command.dma_request.source_address,
481 command.dma_request.size);
456 SignalInterrupt(InterruptId::DMA); 482 SignalInterrupt(InterruptId::DMA);
457 break; 483 break;
458 } 484 }
459 // TODO: This will need some rework in the future. (why?) 485 // TODO: This will need some rework in the future. (why?)
460 case CommandId::SUBMIT_GPU_CMDLIST: 486 case CommandId::SUBMIT_GPU_CMDLIST: {
461 {
462 auto& params = command.submit_gpu_cmdlist; 487 auto& params = command.submit_gpu_cmdlist;
463 488
464 if (params.do_flush) { 489 if (params.do_flush) {
@@ -468,10 +493,12 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
468 } 493 }
469 494
470 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.address)), 495 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.address)),
471 Memory::VirtualToPhysicalAddress(params.address) >> 3); 496 Memory::VirtualToPhysicalAddress(params.address) >> 3);
472 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.size)), params.size); 497 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.size)),
498 params.size);
473 499
474 // TODO: Not sure if we are supposed to always write this .. seems to trigger processing though 500 // TODO: Not sure if we are supposed to always write this .. seems to trigger processing
501 // though
475 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.trigger)), 1); 502 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(command_processor_config.trigger)), 1);
476 503
477 // TODO(yuriks): Figure out the meaning of the `flags` field. 504 // TODO(yuriks): Figure out the meaning of the `flags` field.
@@ -481,67 +508,70 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
481 508
482 // It's assumed that the two "blocks" behave equivalently. 509 // It's assumed that the two "blocks" behave equivalently.
483 // Presumably this is done simply to allow two memory fills to run in parallel. 510 // Presumably this is done simply to allow two memory fills to run in parallel.
484 case CommandId::SET_MEMORY_FILL: 511 case CommandId::SET_MEMORY_FILL: {
485 {
486 auto& params = command.memory_fill; 512 auto& params = command.memory_fill;
487 513
488 if (params.start1 != 0) { 514 if (params.start1 != 0) {
489 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_start)), 515 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_start)),
490 Memory::VirtualToPhysicalAddress(params.start1) >> 3); 516 Memory::VirtualToPhysicalAddress(params.start1) >> 3);
491 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_end)), 517 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].address_end)),
492 Memory::VirtualToPhysicalAddress(params.end1) >> 3); 518 Memory::VirtualToPhysicalAddress(params.end1) >> 3);
493 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].value_32bit)), params.value1); 519 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].value_32bit)),
494 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].control)), params.control1); 520 params.value1);
521 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[0].control)),
522 params.control1);
495 } 523 }
496 524
497 if (params.start2 != 0) { 525 if (params.start2 != 0) {
498 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_start)), 526 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_start)),
499 Memory::VirtualToPhysicalAddress(params.start2) >> 3); 527 Memory::VirtualToPhysicalAddress(params.start2) >> 3);
500 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_end)), 528 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].address_end)),
501 Memory::VirtualToPhysicalAddress(params.end2) >> 3); 529 Memory::VirtualToPhysicalAddress(params.end2) >> 3);
502 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].value_32bit)), params.value2); 530 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].value_32bit)),
503 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].control)), params.control2); 531 params.value2);
532 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(memory_fill_config[1].control)),
533 params.control2);
504 } 534 }
505 break; 535 break;
506 } 536 }
507 537
508 case CommandId::SET_DISPLAY_TRANSFER: 538 case CommandId::SET_DISPLAY_TRANSFER: {
509 {
510 auto& params = command.display_transfer; 539 auto& params = command.display_transfer;
511 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_address)), 540 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_address)),
512 Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3); 541 Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3);
513 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_address)), 542 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_address)),
514 Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3); 543 Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3);
515 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_size)), params.in_buffer_size); 544 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.input_size)),
516 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_size)), params.out_buffer_size); 545 params.in_buffer_size);
517 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.flags)), params.flags); 546 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.output_size)),
547 params.out_buffer_size);
548 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.flags)),
549 params.flags);
518 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.trigger)), 1); 550 WriteGPURegister(static_cast<u32>(GPU_REG_INDEX(display_transfer_config.trigger)), 1);
519 break; 551 break;
520 } 552 }
521 553
522 case CommandId::SET_TEXTURE_COPY: 554 case CommandId::SET_TEXTURE_COPY: {
523 {
524 auto& params = command.texture_copy; 555 auto& params = command.texture_copy;
525 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.input_address), 556 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.input_address),
526 Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3); 557 Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3);
527 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.output_address), 558 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.output_address),
528 Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3); 559 Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3);
529 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.size), 560 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.size),
530 params.size); 561 params.size);
531 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.input_size), 562 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.input_size),
532 params.in_width_gap); 563 params.in_width_gap);
533 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.output_size), 564 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.texture_copy.output_size),
534 params.out_width_gap); 565 params.out_width_gap);
535 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.flags), 566 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.flags), params.flags);
536 params.flags);
537 567
538 // NOTE: Actual GSP ORs 1 with current register instead of overwriting. Doesn't seem to matter. 568 // NOTE: Actual GSP ORs 1 with current register instead of overwriting. Doesn't seem to
569 // matter.
539 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.trigger), 1); 570 WriteGPURegister((u32)GPU_REG_INDEX(display_transfer_config.trigger), 1);
540 break; 571 break;
541 } 572 }
542 573
543 case CommandId::CACHE_FLUSH: 574 case CommandId::CACHE_FLUSH: {
544 {
545 // NOTE: Rasterizer flushing handled elsewhere in CPU read/write and other GPU handlers 575 // NOTE: Rasterizer flushing handled elsewhere in CPU read/write and other GPU handlers
546 // Use command.cache_flush.regions to implement this handler 576 // Use command.cache_flush.regions to implement this handler
547 break; 577 break;
@@ -552,7 +582,8 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
552 } 582 }
553 583
554 if (Pica::g_debug_context) 584 if (Pica::g_debug_context)
555 Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::GSPCommandProcessed, (void*)&command); 585 Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::GSPCommandProcessed,
586 (void*)&command);
556} 587}
557 588
558/** 589/**
@@ -575,7 +606,7 @@ static void SetLcdForceBlack(Service::Interface* self) {
575 // the color to black (all zero). 606 // the color to black (all zero).
576 data.is_enabled.Assign(enable_black); 607 data.is_enabled.Assign(enable_black);
577 608
578 LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_top), data.raw); // Top LCD 609 LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_top), data.raw); // Top LCD
579 LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_bottom), data.raw); // Bottom LCD 610 LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_bottom), data.raw); // Bottom LCD
580 611
581 cmd_buff[1] = RESULT_SUCCESS.raw; 612 cmd_buff[1] = RESULT_SUCCESS.raw;
@@ -679,37 +710,37 @@ static void ReleaseRight(Service::Interface* self) {
679} 710}
680 711
681const Interface::FunctionInfo FunctionTable[] = { 712const Interface::FunctionInfo FunctionTable[] = {
682 {0x00010082, WriteHWRegs, "WriteHWRegs"}, 713 {0x00010082, WriteHWRegs, "WriteHWRegs"},
683 {0x00020084, WriteHWRegsWithMask, "WriteHWRegsWithMask"}, 714 {0x00020084, WriteHWRegsWithMask, "WriteHWRegsWithMask"},
684 {0x00030082, nullptr, "WriteHWRegRepeat"}, 715 {0x00030082, nullptr, "WriteHWRegRepeat"},
685 {0x00040080, ReadHWRegs, "ReadHWRegs"}, 716 {0x00040080, ReadHWRegs, "ReadHWRegs"},
686 {0x00050200, SetBufferSwap, "SetBufferSwap"}, 717 {0x00050200, SetBufferSwap, "SetBufferSwap"},
687 {0x00060082, nullptr, "SetCommandList"}, 718 {0x00060082, nullptr, "SetCommandList"},
688 {0x000700C2, nullptr, "RequestDma"}, 719 {0x000700C2, nullptr, "RequestDma"},
689 {0x00080082, FlushDataCache, "FlushDataCache"}, 720 {0x00080082, FlushDataCache, "FlushDataCache"},
690 {0x00090082, nullptr, "InvalidateDataCache"}, 721 {0x00090082, nullptr, "InvalidateDataCache"},
691 {0x000A0044, nullptr, "RegisterInterruptEvents"}, 722 {0x000A0044, nullptr, "RegisterInterruptEvents"},
692 {0x000B0040, SetLcdForceBlack, "SetLcdForceBlack"}, 723 {0x000B0040, SetLcdForceBlack, "SetLcdForceBlack"},
693 {0x000C0000, TriggerCmdReqQueue, "TriggerCmdReqQueue"}, 724 {0x000C0000, TriggerCmdReqQueue, "TriggerCmdReqQueue"},
694 {0x000D0140, nullptr, "SetDisplayTransfer"}, 725 {0x000D0140, nullptr, "SetDisplayTransfer"},
695 {0x000E0180, nullptr, "SetTextureCopy"}, 726 {0x000E0180, nullptr, "SetTextureCopy"},
696 {0x000F0200, nullptr, "SetMemoryFill"}, 727 {0x000F0200, nullptr, "SetMemoryFill"},
697 {0x00100040, SetAxiConfigQoSMode, "SetAxiConfigQoSMode"}, 728 {0x00100040, SetAxiConfigQoSMode, "SetAxiConfigQoSMode"},
698 {0x00110040, nullptr, "SetPerfLogMode"}, 729 {0x00110040, nullptr, "SetPerfLogMode"},
699 {0x00120000, nullptr, "GetPerfLog"}, 730 {0x00120000, nullptr, "GetPerfLog"},
700 {0x00130042, RegisterInterruptRelayQueue, "RegisterInterruptRelayQueue"}, 731 {0x00130042, RegisterInterruptRelayQueue, "RegisterInterruptRelayQueue"},
701 {0x00140000, UnregisterInterruptRelayQueue, "UnregisterInterruptRelayQueue"}, 732 {0x00140000, UnregisterInterruptRelayQueue, "UnregisterInterruptRelayQueue"},
702 {0x00150002, nullptr, "TryAcquireRight"}, 733 {0x00150002, nullptr, "TryAcquireRight"},
703 {0x00160042, AcquireRight, "AcquireRight"}, 734 {0x00160042, AcquireRight, "AcquireRight"},
704 {0x00170000, ReleaseRight, "ReleaseRight"}, 735 {0x00170000, ReleaseRight, "ReleaseRight"},
705 {0x00180000, ImportDisplayCaptureInfo, "ImportDisplayCaptureInfo"}, 736 {0x00180000, ImportDisplayCaptureInfo, "ImportDisplayCaptureInfo"},
706 {0x00190000, nullptr, "SaveVramSysArea"}, 737 {0x00190000, nullptr, "SaveVramSysArea"},
707 {0x001A0000, nullptr, "RestoreVramSysArea"}, 738 {0x001A0000, nullptr, "RestoreVramSysArea"},
708 {0x001B0000, nullptr, "ResetGpuCore"}, 739 {0x001B0000, nullptr, "ResetGpuCore"},
709 {0x001C0040, nullptr, "SetLedForceOff"}, 740 {0x001C0040, nullptr, "SetLedForceOff"},
710 {0x001D0040, nullptr, "SetTestCommand"}, 741 {0x001D0040, nullptr, "SetTestCommand"},
711 {0x001E0080, nullptr, "SetInternalPriorities"}, 742 {0x001E0080, nullptr, "SetInternalPriorities"},
712 {0x001F0082, nullptr, "StoreDataCache"}, 743 {0x001F0082, nullptr, "StoreDataCache"},
713}; 744};
714 745
715//////////////////////////////////////////////////////////////////////////////////////////////////// 746////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -721,9 +752,9 @@ Interface::Interface() {
721 g_interrupt_event = nullptr; 752 g_interrupt_event = nullptr;
722 753
723 using Kernel::MemoryPermission; 754 using Kernel::MemoryPermission;
724 g_shared_memory = Kernel::SharedMemory::Create(nullptr, 0x1000, 755 g_shared_memory = Kernel::SharedMemory::Create(nullptr, 0x1000, MemoryPermission::ReadWrite,
725 MemoryPermission::ReadWrite, MemoryPermission::ReadWrite, 756 MemoryPermission::ReadWrite, 0,
726 0, Kernel::MemoryRegion::BASE, "GSP:SharedMemory"); 757 Kernel::MemoryRegion::BASE, "GSP:SharedMemory");
727 758
728 g_thread_id = 0; 759 g_thread_id = 0;
729 gpu_right_acquired = false; 760 gpu_right_acquired = false;
diff --git a/src/core/hle/service/gsp_gpu.h b/src/core/hle/service/gsp_gpu.h
index 3b4b678a3..e028123f3 100644
--- a/src/core/hle/service/gsp_gpu.h
+++ b/src/core/hle/service/gsp_gpu.h
@@ -20,30 +20,30 @@ namespace GSP_GPU {
20 20
21/// GSP interrupt ID 21/// GSP interrupt ID
22enum class InterruptId : u8 { 22enum class InterruptId : u8 {
23 PSC0 = 0x00, 23 PSC0 = 0x00,
24 PSC1 = 0x01, 24 PSC1 = 0x01,
25 PDC0 = 0x02, // Seems called every vertical screen line 25 PDC0 = 0x02, // Seems called every vertical screen line
26 PDC1 = 0x03, // Seems called every frame 26 PDC1 = 0x03, // Seems called every frame
27 PPF = 0x04, 27 PPF = 0x04,
28 P3D = 0x05, 28 P3D = 0x05,
29 DMA = 0x06, 29 DMA = 0x06,
30}; 30};
31 31
32/// GSP command ID 32/// GSP command ID
33enum class CommandId : u32 { 33enum class CommandId : u32 {
34 REQUEST_DMA = 0x00, 34 REQUEST_DMA = 0x00,
35 /// Submits a commandlist for execution by the GPU. 35 /// Submits a commandlist for execution by the GPU.
36 SUBMIT_GPU_CMDLIST = 0x01, 36 SUBMIT_GPU_CMDLIST = 0x01,
37 37
38 // Fills a given memory range with a particular value 38 // Fills a given memory range with a particular value
39 SET_MEMORY_FILL = 0x02, 39 SET_MEMORY_FILL = 0x02,
40 40
41 // Copies an image and optionally performs color-conversion or scaling. 41 // Copies an image and optionally performs color-conversion or scaling.
42 // This is highly similar to the GameCube's EFB copy feature 42 // This is highly similar to the GameCube's EFB copy feature
43 SET_DISPLAY_TRANSFER = 0x03, 43 SET_DISPLAY_TRANSFER = 0x03,
44 44
45 // Conceptionally similar to SET_DISPLAY_TRANSFER and presumable uses the same hardware path 45 // Conceptionally similar to SET_DISPLAY_TRANSFER and presumable uses the same hardware path
46 SET_TEXTURE_COPY = 0x04, 46 SET_TEXTURE_COPY = 0x04,
47 /// Flushes up to 3 cache regions in a single command. 47 /// Flushes up to 3 cache regions in a single command.
48 CACHE_FLUSH = 0x05, 48 CACHE_FLUSH = 0x05,
49}; 49};
@@ -61,19 +61,18 @@ struct InterruptRelayQueue {
61 u32 missed_PDC0; 61 u32 missed_PDC0;
62 u32 missed_PDC1; 62 u32 missed_PDC1;
63 63
64 InterruptId slot[0x34]; ///< Interrupt ID slots 64 InterruptId slot[0x34]; ///< Interrupt ID slots
65}; 65};
66static_assert(sizeof(InterruptRelayQueue) == 0x40, 66static_assert(sizeof(InterruptRelayQueue) == 0x40, "InterruptRelayQueue struct has incorrect size");
67 "InterruptRelayQueue struct has incorrect size");
68 67
69struct FrameBufferInfo { 68struct FrameBufferInfo {
70 BitField<0, 1, u32> active_fb; // 0 = first, 1 = second 69 BitField<0, 1, u32> active_fb; // 0 = first, 1 = second
71 70
72 u32 address_left; 71 u32 address_left;
73 u32 address_right; 72 u32 address_right;
74 u32 stride; // maps to 0x1EF00X90 ? 73 u32 stride; // maps to 0x1EF00X90 ?
75 u32 format; // maps to 0x1EF00X70 ? 74 u32 format; // maps to 0x1EF00X70 ?
76 u32 shown_fb; // maps to 0x1EF00X78 ? 75 u32 shown_fb; // maps to 0x1EF00X78 ?
77 u32 unknown; 76 u32 unknown;
78}; 77};
79static_assert(sizeof(FrameBufferInfo) == 0x1c, "Struct has incorrect size"); 78static_assert(sizeof(FrameBufferInfo) == 0x1c, "Struct has incorrect size");
@@ -91,7 +90,8 @@ static_assert(sizeof(FrameBufferUpdate) == 0x40, "Struct has incorrect size");
91// TODO: Not sure if this padding is correct. 90// TODO: Not sure if this padding is correct.
92// Chances are the second block is stored at offset 0x24 rather than 0x20. 91// Chances are the second block is stored at offset 0x24 rather than 0x20.
93#ifndef _MSC_VER 92#ifndef _MSC_VER
94static_assert(offsetof(FrameBufferUpdate, framebuffer_info[1]) == 0x20, "FrameBufferInfo element has incorrect alignment"); 93static_assert(offsetof(FrameBufferUpdate, framebuffer_info[1]) == 0x20,
94 "FrameBufferInfo element has incorrect alignment");
95#endif 95#endif
96 96
97/// GSP command 97/// GSP command
@@ -163,13 +163,13 @@ struct CommandBuffer {
163 // Current command index. This index is updated by GSP module after loading the command 163 // Current command index. This index is updated by GSP module after loading the command
164 // data, right before the command is processed. When this index is updated by GSP module, 164 // data, right before the command is processed. When this index is updated by GSP module,
165 // the total commands field is decreased by one as well. 165 // the total commands field is decreased by one as well.
166 BitField<0,8,u32> index; 166 BitField<0, 8, u32> index;
167 167
168 // Total commands to process, must not be value 0 when GSP module handles commands. This 168 // Total commands to process, must not be value 0 when GSP module handles commands. This
169 // must be <=15 when writing a command to shared memory. This is incremented by the 169 // must be <=15 when writing a command to shared memory. This is incremented by the
170 // application when writing a command to shared memory, after increasing this value 170 // application when writing a command to shared memory, after increasing this value
171 // TriggerCmdReqQueue is only used if this field is value 1. 171 // TriggerCmdReqQueue is only used if this field is value 1.
172 BitField<8,8,u32> number_commands; 172 BitField<8, 8, u32> number_commands;
173 }; 173 };
174 174
175 u32 unk[7]; 175 u32 unk[7];
diff --git a/src/core/hle/service/gsp_lcd.cpp b/src/core/hle/service/gsp_lcd.cpp
index c700c21c5..3922cd197 100644
--- a/src/core/hle/service/gsp_lcd.cpp
+++ b/src/core/hle/service/gsp_lcd.cpp
@@ -9,13 +9,11 @@
9 9
10namespace GSP_LCD { 10namespace GSP_LCD {
11 11
12const Interface::FunctionInfo FunctionTable[] = { 12const Interface::FunctionInfo FunctionTable[] = {{0x000F0000, nullptr, "PowerOnAllBacklights"},
13 {0x000F0000, nullptr, "PowerOnAllBacklights"}, 13 {0x00100000, nullptr, "PowerOffAllBacklights"},
14 {0x00100000, nullptr, "PowerOffAllBacklights"}, 14 {0x00110040, nullptr, "PowerOnBacklight"},
15 {0x00110040, nullptr, "PowerOnBacklight"}, 15 {0x00120040, nullptr, "PowerOffBacklight"},
16 {0x00120040, nullptr, "PowerOffBacklight"}, 16 {0x00130040, nullptr, "SetLedForceOff"}};
17 {0x00130040, nullptr, "SetLedForceOff"}
18};
19 17
20//////////////////////////////////////////////////////////////////////////////////////////////////// 18////////////////////////////////////////////////////////////////////////////////////////////////////
21// Interface class 19// Interface class
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index cdec11388..d915a3105 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -4,13 +4,13 @@
4 4
5#include <cmath> 5#include <cmath>
6 6
7#include "common/logging/log.h"
8#include "common/emu_window.h" 7#include "common/emu_window.h"
8#include "common/logging/log.h"
9 9
10#include "core/hle/service/service.h"
11#include "core/hle/service/hid/hid.h" 10#include "core/hle/service/hid/hid.h"
12#include "core/hle/service/hid/hid_spvr.h" 11#include "core/hle/service/hid/hid_spvr.h"
13#include "core/hle/service/hid/hid_user.h" 12#include "core/hle/service/hid/hid_user.h"
13#include "core/hle/service/service.h"
14 14
15#include "core/core_timing.h" 15#include "core/core_timing.h"
16#include "core/hle/kernel/event.h" 16#include "core/hle/kernel/event.h"
@@ -37,11 +37,14 @@ static u32 next_accelerometer_index;
37static u32 next_gyroscope_index; 37static u32 next_gyroscope_index;
38 38
39static int enable_accelerometer_count = 0; // positive means enabled 39static int enable_accelerometer_count = 0; // positive means enabled
40static int enable_gyroscope_count = 0; // positive means enabled 40static int enable_gyroscope_count = 0; // positive means enabled
41 41
42static PadState GetCirclePadDirectionState(s16 circle_pad_x, s16 circle_pad_y) { 42static PadState GetCirclePadDirectionState(s16 circle_pad_x, s16 circle_pad_y) {
43 constexpr float TAN30 = 0.577350269, TAN60 = 1 / TAN30; // 30 degree and 60 degree are angular thresholds for directions 43 constexpr float TAN30 = 0.577350269,
44 constexpr int CIRCLE_PAD_THRESHOLD_SQUARE = 40 * 40; // a circle pad radius greater than 40 will trigger circle pad direction 44 TAN60 =
45 1 / TAN30; // 30 degree and 60 degree are angular thresholds for directions
46 constexpr int CIRCLE_PAD_THRESHOLD_SQUARE =
47 40 * 40; // a circle pad radius greater than 40 will trigger circle pad direction
45 PadState state; 48 PadState state;
46 state.hex = 0; 49 state.hex = 0;
47 50
@@ -90,7 +93,7 @@ void Update() {
90 PadState old_state = mem->pad.entries[last_entry_index].current_state; 93 PadState old_state = mem->pad.entries[last_entry_index].current_state;
91 94
92 // Compute bitmask with 1s for bits different from the old state 95 // Compute bitmask with 1s for bits different from the old state
93 PadState changed = { { (state.hex ^ old_state.hex) } }; 96 PadState changed = {{(state.hex ^ old_state.hex)}};
94 97
95 // Get the current Pad entry 98 // Get the current Pad entry
96 PadDataEntry& pad_entry = mem->pad.entries[mem->pad.index]; 99 PadDataEntry& pad_entry = mem->pad.entries[mem->pad.index];
@@ -135,11 +138,13 @@ void Update() {
135 // Update accelerometer 138 // Update accelerometer
136 if (enable_accelerometer_count > 0) { 139 if (enable_accelerometer_count > 0) {
137 mem->accelerometer.index = next_accelerometer_index; 140 mem->accelerometer.index = next_accelerometer_index;
138 next_accelerometer_index = (next_accelerometer_index + 1) % mem->accelerometer.entries.size(); 141 next_accelerometer_index =
142 (next_accelerometer_index + 1) % mem->accelerometer.entries.size();
139 143
140 AccelerometerDataEntry& accelerometer_entry = mem->accelerometer.entries[mem->accelerometer.index]; 144 AccelerometerDataEntry& accelerometer_entry =
141 std::tie(accelerometer_entry.x, accelerometer_entry.y, accelerometer_entry.z) 145 mem->accelerometer.entries[mem->accelerometer.index];
142 = VideoCore::g_emu_window->GetAccelerometerState(); 146 std::tie(accelerometer_entry.x, accelerometer_entry.y, accelerometer_entry.z) =
147 VideoCore::g_emu_window->GetAccelerometerState();
143 148
144 // Make up "raw" entry 149 // Make up "raw" entry
145 // TODO(wwylele): 150 // TODO(wwylele):
@@ -167,8 +172,8 @@ void Update() {
167 next_gyroscope_index = (next_gyroscope_index + 1) % mem->gyroscope.entries.size(); 172 next_gyroscope_index = (next_gyroscope_index + 1) % mem->gyroscope.entries.size();
168 173
169 GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index]; 174 GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index];
170 std::tie(gyroscope_entry.x, gyroscope_entry.y, gyroscope_entry.z) 175 std::tie(gyroscope_entry.x, gyroscope_entry.y, gyroscope_entry.z) =
171 = VideoCore::g_emu_window->GetGyroscopeState(); 176 VideoCore::g_emu_window->GetGyroscopeState();
172 177
173 // Make up "raw" entry 178 // Make up "raw" entry
174 mem->gyroscope.raw_entry.x = gyroscope_entry.x; 179 mem->gyroscope.raw_entry.x = gyroscope_entry.x;
@@ -188,7 +193,7 @@ void Update() {
188void GetIPCHandles(Service::Interface* self) { 193void GetIPCHandles(Service::Interface* self) {
189 u32* cmd_buff = Kernel::GetCommandBuffer(); 194 u32* cmd_buff = Kernel::GetCommandBuffer();
190 195
191 cmd_buff[1] = 0; // No error 196 cmd_buff[1] = 0; // No error
192 cmd_buff[2] = 0x14000000; // IPC Command Structure translate-header 197 cmd_buff[2] = 0x14000000; // IPC Command Structure translate-header
193 // TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling) 198 // TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling)
194 cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::shared_mem).MoveFrom(); 199 cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::shared_mem).MoveFrom();
@@ -259,9 +264,7 @@ void GetGyroscopeLowCalibrateParam(Service::Interface* self) {
259 264
260 const s16 param_unit = 6700; // an approximate value taken from hw 265 const s16 param_unit = 6700; // an approximate value taken from hw
261 GyroscopeCalibrateParam param = { 266 GyroscopeCalibrateParam param = {
262 { 0, param_unit, -param_unit }, 267 {0, param_unit, -param_unit}, {0, param_unit, -param_unit}, {0, param_unit, -param_unit},
263 { 0, param_unit, -param_unit },
264 { 0, param_unit, -param_unit },
265 }; 268 };
266 memcpy(&cmd_buff[2], &param, sizeof(param)); 269 memcpy(&cmd_buff[2], &param, sizeof(param));
267 270
@@ -286,9 +289,9 @@ void Init() {
286 AddService(new HID_SPVR_Interface); 289 AddService(new HID_SPVR_Interface);
287 290
288 using Kernel::MemoryPermission; 291 using Kernel::MemoryPermission;
289 shared_mem = SharedMemory::Create(nullptr, 0x1000, 292 shared_mem =
290 MemoryPermission::ReadWrite, MemoryPermission::Read, 293 SharedMemory::Create(nullptr, 0x1000, MemoryPermission::ReadWrite, MemoryPermission::Read,
291 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory"); 294 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory");
292 295
293 next_pad_index = 0; 296 next_pad_index = 0;
294 next_touch_index = 0; 297 next_touch_index = 0;
@@ -296,9 +299,9 @@ void Init() {
296 // Create event handles 299 // Create event handles
297 event_pad_or_touch_1 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch1"); 300 event_pad_or_touch_1 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch1");
298 event_pad_or_touch_2 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch2"); 301 event_pad_or_touch_2 = Event::Create(ResetType::OneShot, "HID:EventPadOrTouch2");
299 event_accelerometer = Event::Create(ResetType::OneShot, "HID:EventAccelerometer"); 302 event_accelerometer = Event::Create(ResetType::OneShot, "HID:EventAccelerometer");
300 event_gyroscope = Event::Create(ResetType::OneShot, "HID:EventGyroscope"); 303 event_gyroscope = Event::Create(ResetType::OneShot, "HID:EventGyroscope");
301 event_debug_pad = Event::Create(ResetType::OneShot, "HID:EventDebugPad"); 304 event_debug_pad = Event::Create(ResetType::OneShot, "HID:EventDebugPad");
302} 305}
303 306
304void Shutdown() { 307void Shutdown() {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 669b1f723..f54ffd8be 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -9,10 +9,10 @@
9#ifndef _MSC_VER 9#ifndef _MSC_VER
10#include <cstddef> 10#include <cstddef>
11#endif 11#endif
12#include "core/settings.h"
13#include "common/bit_field.h" 12#include "common/bit_field.h"
14#include "common/common_funcs.h" 13#include "common/common_funcs.h"
15#include "common/common_types.h" 14#include "common/common_types.h"
15#include "core/settings.h"
16 16
17namespace Service { 17namespace Service {
18 18
@@ -103,7 +103,7 @@ struct SharedMem {
103 struct { 103 struct {
104 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 104 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0
105 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks` 105 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks`
106 u32 index; ///< Index of the last updated pad state entry 106 u32 index; ///< Index of the last updated pad state entry
107 107
108 INSERT_PADDING_WORDS(0x2); 108 INSERT_PADDING_WORDS(0x2);
109 109
@@ -121,7 +121,7 @@ struct SharedMem {
121 struct { 121 struct {
122 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 122 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0
123 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks` 123 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks`
124 u32 index; ///< Index of the last updated touch entry 124 u32 index; ///< Index of the last updated touch entry
125 125
126 INSERT_PADDING_WORDS(0x1); 126 INSERT_PADDING_WORDS(0x1);
127 127
@@ -135,7 +135,7 @@ struct SharedMem {
135 struct { 135 struct {
136 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 136 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0
137 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks` 137 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks`
138 u32 index; ///< Index of the last updated accelerometer entry 138 u32 index; ///< Index of the last updated accelerometer entry
139 139
140 INSERT_PADDING_WORDS(0x1); 140 INSERT_PADDING_WORDS(0x1);
141 141
@@ -149,7 +149,7 @@ struct SharedMem {
149 struct { 149 struct {
150 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0 150 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0
151 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks` 151 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks`
152 u32 index; ///< Index of the last updated accelerometer entry 152 u32 index; ///< Index of the last updated accelerometer entry
153 153
154 INSERT_PADDING_WORDS(0x1); 154 INSERT_PADDING_WORDS(0x1);
155 155
@@ -176,9 +176,9 @@ struct GyroscopeCalibrateParam {
176// is technically allowed since C++11. This macro should be enabled once MSVC adds 176// is technically allowed since C++11. This macro should be enabled once MSVC adds
177// support for that. 177// support for that.
178#ifndef _MSC_VER 178#ifndef _MSC_VER
179#define ASSERT_REG_POSITION(field_name, position) \ 179#define ASSERT_REG_POSITION(field_name, position) \
180 static_assert(offsetof(SharedMem, field_name) == position * 4, \ 180 static_assert(offsetof(SharedMem, field_name) == position * 4, \
181 "Field "#field_name" has invalid position") 181 "Field " #field_name " has invalid position")
182 182
183ASSERT_REG_POSITION(pad.index_reset_ticks, 0x0); 183ASSERT_REG_POSITION(pad.index_reset_ticks, 0x0);
184ASSERT_REG_POSITION(touch.index_reset_ticks, 0x2A); 184ASSERT_REG_POSITION(touch.index_reset_ticks, 0x2A);
@@ -187,33 +187,33 @@ ASSERT_REG_POSITION(touch.index_reset_ticks, 0x2A);
187#endif // !defined(_MSC_VER) 187#endif // !defined(_MSC_VER)
188 188
189// Pre-defined PadStates for single button presses 189// Pre-defined PadStates for single button presses
190const PadState PAD_NONE = {{0}}; 190const PadState PAD_NONE = {{0}};
191const PadState PAD_A = {{1u << 0}}; 191const PadState PAD_A = {{1u << 0}};
192const PadState PAD_B = {{1u << 1}}; 192const PadState PAD_B = {{1u << 1}};
193const PadState PAD_SELECT = {{1u << 2}}; 193const PadState PAD_SELECT = {{1u << 2}};
194const PadState PAD_START = {{1u << 3}}; 194const PadState PAD_START = {{1u << 3}};
195const PadState PAD_RIGHT = {{1u << 4}}; 195const PadState PAD_RIGHT = {{1u << 4}};
196const PadState PAD_LEFT = {{1u << 5}}; 196const PadState PAD_LEFT = {{1u << 5}};
197const PadState PAD_UP = {{1u << 6}}; 197const PadState PAD_UP = {{1u << 6}};
198const PadState PAD_DOWN = {{1u << 7}}; 198const PadState PAD_DOWN = {{1u << 7}};
199const PadState PAD_R = {{1u << 8}}; 199const PadState PAD_R = {{1u << 8}};
200const PadState PAD_L = {{1u << 9}}; 200const PadState PAD_L = {{1u << 9}};
201const PadState PAD_X = {{1u << 10}}; 201const PadState PAD_X = {{1u << 10}};
202const PadState PAD_Y = {{1u << 11}}; 202const PadState PAD_Y = {{1u << 11}};
203 203
204const PadState PAD_ZL = {{1u << 14}}; 204const PadState PAD_ZL = {{1u << 14}};
205const PadState PAD_ZR = {{1u << 15}}; 205const PadState PAD_ZR = {{1u << 15}};
206 206
207const PadState PAD_TOUCH = {{1u << 20}}; 207const PadState PAD_TOUCH = {{1u << 20}};
208 208
209const PadState PAD_C_RIGHT = {{1u << 24}}; 209const PadState PAD_C_RIGHT = {{1u << 24}};
210const PadState PAD_C_LEFT = {{1u << 25}}; 210const PadState PAD_C_LEFT = {{1u << 25}};
211const PadState PAD_C_UP = {{1u << 26}}; 211const PadState PAD_C_UP = {{1u << 26}};
212const PadState PAD_C_DOWN = {{1u << 27}}; 212const PadState PAD_C_DOWN = {{1u << 27}};
213const PadState PAD_CIRCLE_RIGHT = {{1u << 28}}; 213const PadState PAD_CIRCLE_RIGHT = {{1u << 28}};
214const PadState PAD_CIRCLE_LEFT = {{1u << 29}}; 214const PadState PAD_CIRCLE_LEFT = {{1u << 29}};
215const PadState PAD_CIRCLE_UP = {{1u << 30}}; 215const PadState PAD_CIRCLE_UP = {{1u << 30}};
216const PadState PAD_CIRCLE_DOWN = {{1u << 31}}; 216const PadState PAD_CIRCLE_DOWN = {{1u << 31}};
217 217
218/** 218/**
219 * HID::GetIPCHandles service function 219 * HID::GetIPCHandles service function
@@ -305,6 +305,5 @@ void Init();
305 305
306/// Shutdown HID service 306/// Shutdown HID service
307void Shutdown(); 307void Shutdown();
308
309} 308}
310} 309}
diff --git a/src/core/hle/service/hid/hid_spvr.cpp b/src/core/hle/service/hid/hid_spvr.cpp
index 046e65b11..09007e304 100644
--- a/src/core/hle/service/hid/hid_spvr.cpp
+++ b/src/core/hle/service/hid/hid_spvr.cpp
@@ -9,16 +9,16 @@ namespace Service {
9namespace HID { 9namespace HID {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x000A0000, GetIPCHandles, "GetIPCHandles"}, 12 {0x000A0000, GetIPCHandles, "GetIPCHandles"},
13 {0x000B0000, nullptr, "StartAnalogStickCalibration"}, 13 {0x000B0000, nullptr, "StartAnalogStickCalibration"},
14 {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"}, 14 {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"},
15 {0x00110000, EnableAccelerometer, "EnableAccelerometer"}, 15 {0x00110000, EnableAccelerometer, "EnableAccelerometer"},
16 {0x00120000, DisableAccelerometer, "DisableAccelerometer"}, 16 {0x00120000, DisableAccelerometer, "DisableAccelerometer"},
17 {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"}, 17 {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"},
18 {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"}, 18 {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"},
19 {0x00150000, GetGyroscopeLowRawToDpsCoefficient, "GetGyroscopeLowRawToDpsCoefficient"}, 19 {0x00150000, GetGyroscopeLowRawToDpsCoefficient, "GetGyroscopeLowRawToDpsCoefficient"},
20 {0x00160000, GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"}, 20 {0x00160000, GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"},
21 {0x00170000, GetSoundVolume, "GetSoundVolume"}, 21 {0x00170000, GetSoundVolume, "GetSoundVolume"},
22}; 22};
23 23
24HID_SPVR_Interface::HID_SPVR_Interface() { 24HID_SPVR_Interface::HID_SPVR_Interface() {
diff --git a/src/core/hle/service/hid/hid_user.cpp b/src/core/hle/service/hid/hid_user.cpp
index bb157b83d..42591543c 100644
--- a/src/core/hle/service/hid/hid_user.cpp
+++ b/src/core/hle/service/hid/hid_user.cpp
@@ -9,16 +9,16 @@ namespace Service {
9namespace HID { 9namespace HID {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x000A0000, GetIPCHandles, "GetIPCHandles"}, 12 {0x000A0000, GetIPCHandles, "GetIPCHandles"},
13 {0x000B0000, nullptr, "StartAnalogStickCalibration"}, 13 {0x000B0000, nullptr, "StartAnalogStickCalibration"},
14 {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"}, 14 {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"},
15 {0x00110000, EnableAccelerometer, "EnableAccelerometer"}, 15 {0x00110000, EnableAccelerometer, "EnableAccelerometer"},
16 {0x00120000, DisableAccelerometer, "DisableAccelerometer"}, 16 {0x00120000, DisableAccelerometer, "DisableAccelerometer"},
17 {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"}, 17 {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"},
18 {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"}, 18 {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"},
19 {0x00150000, GetGyroscopeLowRawToDpsCoefficient, "GetGyroscopeLowRawToDpsCoefficient"}, 19 {0x00150000, GetGyroscopeLowRawToDpsCoefficient, "GetGyroscopeLowRawToDpsCoefficient"},
20 {0x00160000, GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"}, 20 {0x00160000, GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"},
21 {0x00170000, GetSoundVolume, "GetSoundVolume"}, 21 {0x00170000, GetSoundVolume, "GetSoundVolume"},
22}; 22};
23 23
24HID_U_Interface::HID_U_Interface() { 24HID_U_Interface::HID_U_Interface() {
diff --git a/src/core/hle/service/http_c.cpp b/src/core/hle/service/http_c.cpp
index 0855ab227..3cf62a4b8 100644
--- a/src/core/hle/service/http_c.cpp
+++ b/src/core/hle/service/http_c.cpp
@@ -10,56 +10,56 @@
10namespace HTTP_C { 10namespace HTTP_C {
11 11
12const Interface::FunctionInfo FunctionTable[] = { 12const Interface::FunctionInfo FunctionTable[] = {
13 {0x00010044, nullptr, "Initialize"}, 13 {0x00010044, nullptr, "Initialize"},
14 {0x00020082, nullptr, "CreateContext"}, 14 {0x00020082, nullptr, "CreateContext"},
15 {0x00030040, nullptr, "CloseContext"}, 15 {0x00030040, nullptr, "CloseContext"},
16 {0x00040040, nullptr, "CancelConnection"}, 16 {0x00040040, nullptr, "CancelConnection"},
17 {0x00050040, nullptr, "GetRequestState"}, 17 {0x00050040, nullptr, "GetRequestState"},
18 {0x00060040, nullptr, "GetDownloadSizeState"}, 18 {0x00060040, nullptr, "GetDownloadSizeState"},
19 {0x00070040, nullptr, "GetRequestError"}, 19 {0x00070040, nullptr, "GetRequestError"},
20 {0x00080042, nullptr, "InitializeConnectionSession"}, 20 {0x00080042, nullptr, "InitializeConnectionSession"},
21 {0x00090040, nullptr, "BeginRequest"}, 21 {0x00090040, nullptr, "BeginRequest"},
22 {0x000A0040, nullptr, "BeginRequestAsync"}, 22 {0x000A0040, nullptr, "BeginRequestAsync"},
23 {0x000B0082, nullptr, "ReceiveData"}, 23 {0x000B0082, nullptr, "ReceiveData"},
24 {0x000C0102, nullptr, "ReceiveDataTimeout"}, 24 {0x000C0102, nullptr, "ReceiveDataTimeout"},
25 {0x000D0146, nullptr, "SetProxy"}, 25 {0x000D0146, nullptr, "SetProxy"},
26 {0x000E0040, nullptr, "SetProxyDefault"}, 26 {0x000E0040, nullptr, "SetProxyDefault"},
27 {0x000F00C4, nullptr, "SetBasicAuthorization"}, 27 {0x000F00C4, nullptr, "SetBasicAuthorization"},
28 {0x00100080, nullptr, "SetSocketBufferSize"}, 28 {0x00100080, nullptr, "SetSocketBufferSize"},
29 {0x001100C4, nullptr, "AddRequestHeader"}, 29 {0x001100C4, nullptr, "AddRequestHeader"},
30 {0x001200C4, nullptr, "AddPostDataAscii"}, 30 {0x001200C4, nullptr, "AddPostDataAscii"},
31 {0x001300C4, nullptr, "AddPostDataBinary"}, 31 {0x001300C4, nullptr, "AddPostDataBinary"},
32 {0x00140082, nullptr, "AddPostDataRaw"}, 32 {0x00140082, nullptr, "AddPostDataRaw"},
33 {0x00150080, nullptr, "SetPostDataType"}, 33 {0x00150080, nullptr, "SetPostDataType"},
34 {0x001600C4, nullptr, "SendPostDataAscii"}, 34 {0x001600C4, nullptr, "SendPostDataAscii"},
35 {0x00170144, nullptr, "SendPostDataAsciiTimeout"}, 35 {0x00170144, nullptr, "SendPostDataAsciiTimeout"},
36 {0x001800C4, nullptr, "SendPostDataBinary"}, 36 {0x001800C4, nullptr, "SendPostDataBinary"},
37 {0x00190144, nullptr, "SendPostDataBinaryTimeout"}, 37 {0x00190144, nullptr, "SendPostDataBinaryTimeout"},
38 {0x001A0082, nullptr, "SendPostDataRaw"}, 38 {0x001A0082, nullptr, "SendPostDataRaw"},
39 {0x001B0102, nullptr, "SendPOSTDataRawTimeout"}, 39 {0x001B0102, nullptr, "SendPOSTDataRawTimeout"},
40 {0x001C0080, nullptr, "SetPostDataEncoding"}, 40 {0x001C0080, nullptr, "SetPostDataEncoding"},
41 {0x001D0040, nullptr, "NotifyFinishSendPostData"}, 41 {0x001D0040, nullptr, "NotifyFinishSendPostData"},
42 {0x001E00C4, nullptr, "GetResponseHeader"}, 42 {0x001E00C4, nullptr, "GetResponseHeader"},
43 {0x001F0144, nullptr, "GetResponseHeaderTimeout"}, 43 {0x001F0144, nullptr, "GetResponseHeaderTimeout"},
44 {0x00200082, nullptr, "GetResponseData"}, 44 {0x00200082, nullptr, "GetResponseData"},
45 {0x00210102, nullptr, "GetResponseDataTimeout"}, 45 {0x00210102, nullptr, "GetResponseDataTimeout"},
46 {0x00220040, nullptr, "GetResponseStatusCode"}, 46 {0x00220040, nullptr, "GetResponseStatusCode"},
47 {0x002300C0, nullptr, "GetResponseStatusCodeTimeout"}, 47 {0x002300C0, nullptr, "GetResponseStatusCodeTimeout"},
48 {0x00240082, nullptr, "AddTrustedRootCA"}, 48 {0x00240082, nullptr, "AddTrustedRootCA"},
49 {0x00250080, nullptr, "AddDefaultCert"}, 49 {0x00250080, nullptr, "AddDefaultCert"},
50 {0x00260080, nullptr, "SelectRootCertChain"}, 50 {0x00260080, nullptr, "SelectRootCertChain"},
51 {0x002700C4, nullptr, "SetClientCert"}, 51 {0x002700C4, nullptr, "SetClientCert"},
52 {0x002B0080, nullptr, "SetSSLOpt"}, 52 {0x002B0080, nullptr, "SetSSLOpt"},
53 {0x002C0080, nullptr, "SetSSLClearOpt"}, 53 {0x002C0080, nullptr, "SetSSLClearOpt"},
54 {0x002D0000, nullptr, "CreateRootCertChain"}, 54 {0x002D0000, nullptr, "CreateRootCertChain"},
55 {0x002E0040, nullptr, "DestroyRootCertChain"}, 55 {0x002E0040, nullptr, "DestroyRootCertChain"},
56 {0x002F0082, nullptr, "RootCertChainAddCert"}, 56 {0x002F0082, nullptr, "RootCertChainAddCert"},
57 {0x00300080, nullptr, "RootCertChainAddDefaultCert"}, 57 {0x00300080, nullptr, "RootCertChainAddDefaultCert"},
58 {0x00350186, nullptr, "SetDefaultProxy"}, 58 {0x00350186, nullptr, "SetDefaultProxy"},
59 {0x00360000, nullptr, "ClearDNSCache"}, 59 {0x00360000, nullptr, "ClearDNSCache"},
60 {0x00370080, nullptr, "SetKeepAlive"}, 60 {0x00370080, nullptr, "SetKeepAlive"},
61 {0x003800C0, nullptr, "SetPostDataTypeSize"}, 61 {0x003800C0, nullptr, "SetPostDataTypeSize"},
62 {0x00390000, nullptr, "Finalize"}, 62 {0x00390000, nullptr, "Finalize"},
63}; 63};
64 64
65//////////////////////////////////////////////////////////////////////////////////////////////////// 65////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/ir/ir.cpp b/src/core/hle/service/ir/ir.cpp
index 079a87e48..fc048ae88 100644
--- a/src/core/hle/service/ir/ir.cpp
+++ b/src/core/hle/service/ir/ir.cpp
@@ -5,11 +5,11 @@
5#include "core/hle/kernel/event.h" 5#include "core/hle/kernel/event.h"
6#include "core/hle/kernel/shared_memory.h" 6#include "core/hle/kernel/shared_memory.h"
7 7
8#include "core/hle/service/service.h"
9#include "core/hle/service/ir/ir.h" 8#include "core/hle/service/ir/ir.h"
10#include "core/hle/service/ir/ir_rst.h" 9#include "core/hle/service/ir/ir_rst.h"
11#include "core/hle/service/ir/ir_u.h" 10#include "core/hle/service/ir/ir_u.h"
12#include "core/hle/service/ir/ir_user.h" 11#include "core/hle/service/ir/ir_user.h"
12#include "core/hle/service/service.h"
13 13
14namespace Service { 14namespace Service {
15namespace IR { 15namespace IR {
@@ -32,14 +32,14 @@ void InitializeIrNopShared(Interface* self) {
32 u32* cmd_buff = Kernel::GetCommandBuffer(); 32 u32* cmd_buff = Kernel::GetCommandBuffer();
33 33
34 u32 transfer_buff_size = cmd_buff[1]; 34 u32 transfer_buff_size = cmd_buff[1];
35 u32 recv_buff_size = cmd_buff[2]; 35 u32 recv_buff_size = cmd_buff[2];
36 u32 unk1 = cmd_buff[3]; 36 u32 unk1 = cmd_buff[3];
37 u32 send_buff_size = cmd_buff[4]; 37 u32 send_buff_size = cmd_buff[4];
38 u32 unk2 = cmd_buff[5]; 38 u32 unk2 = cmd_buff[5];
39 u8 baud_rate = cmd_buff[6] & 0xFF; 39 u8 baud_rate = cmd_buff[6] & 0xFF;
40 Handle handle = cmd_buff[8]; 40 Handle handle = cmd_buff[8];
41 41
42 if(Kernel::g_handle_table.IsValid(handle)) { 42 if (Kernel::g_handle_table.IsValid(handle)) {
43 transfer_shared_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(handle); 43 transfer_shared_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(handle);
44 transfer_shared_memory->name = "IR:TransferSharedMemory"; 44 transfer_shared_memory->name = "IR:TransferSharedMemory";
45 } 45 }
@@ -47,7 +47,7 @@ void InitializeIrNopShared(Interface* self) {
47 cmd_buff[1] = RESULT_SUCCESS.raw; 47 cmd_buff[1] = RESULT_SUCCESS.raw;
48 48
49 LOG_WARNING(Service_IR, "(STUBBED) called, transfer_buff_size=%d, recv_buff_size=%d, " 49 LOG_WARNING(Service_IR, "(STUBBED) called, transfer_buff_size=%d, recv_buff_size=%d, "
50 "unk1=%d, send_buff_size=%d, unk2=%d, baud_rate=%u, handle=0x%08X", 50 "unk1=%d, send_buff_size=%d, unk2=%d, baud_rate=%u, handle=0x%08X",
51 transfer_buff_size, recv_buff_size, unk1, send_buff_size, unk2, baud_rate, handle); 51 transfer_buff_size, recv_buff_size, unk1, send_buff_size, unk2, baud_rate, handle);
52} 52}
53 53
@@ -94,13 +94,13 @@ void Init() {
94 AddService(new IR_User_Interface); 94 AddService(new IR_User_Interface);
95 95
96 using Kernel::MemoryPermission; 96 using Kernel::MemoryPermission;
97 shared_memory = SharedMemory::Create(nullptr, 0x1000, 97 shared_memory = SharedMemory::Create(nullptr, 0x1000, Kernel::MemoryPermission::ReadWrite,
98 Kernel::MemoryPermission::ReadWrite, Kernel::MemoryPermission::ReadWrite, 98 Kernel::MemoryPermission::ReadWrite, 0,
99 0, Kernel::MemoryRegion::BASE, "IR:SharedMemory"); 99 Kernel::MemoryRegion::BASE, "IR:SharedMemory");
100 transfer_shared_memory = nullptr; 100 transfer_shared_memory = nullptr;
101 101
102 // Create event handle(s) 102 // Create event handle(s)
103 handle_event = Event::Create(ResetType::OneShot, "IR:HandleEvent"); 103 handle_event = Event::Create(ResetType::OneShot, "IR:HandleEvent");
104 conn_status_event = Event::Create(ResetType::OneShot, "IR:ConnectionStatusEvent"); 104 conn_status_event = Event::Create(ResetType::OneShot, "IR:ConnectionStatusEvent");
105} 105}
106 106
diff --git a/src/core/hle/service/ir/ir_rst.cpp b/src/core/hle/service/ir/ir_rst.cpp
index c0300f109..1f10ebd3d 100644
--- a/src/core/hle/service/ir/ir_rst.cpp
+++ b/src/core/hle/service/ir/ir_rst.cpp
@@ -9,10 +9,10 @@ namespace Service {
9namespace IR { 9namespace IR {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010000, GetHandles, "GetHandles"}, 12 {0x00010000, GetHandles, "GetHandles"},
13 {0x00020080, nullptr, "Initialize"}, 13 {0x00020080, nullptr, "Initialize"},
14 {0x00030000, nullptr, "Shutdown"}, 14 {0x00030000, nullptr, "Shutdown"},
15 {0x00090000, nullptr, "WriteToTwoFields"}, 15 {0x00090000, nullptr, "WriteToTwoFields"},
16}; 16};
17 17
18IR_RST_Interface::IR_RST_Interface() { 18IR_RST_Interface::IR_RST_Interface() {
diff --git a/src/core/hle/service/ir/ir_u.cpp b/src/core/hle/service/ir/ir_u.cpp
index 96f76cb83..be4049da9 100644
--- a/src/core/hle/service/ir/ir_u.cpp
+++ b/src/core/hle/service/ir/ir_u.cpp
@@ -8,24 +8,15 @@ namespace Service {
8namespace IR { 8namespace IR {
9 9
10const Interface::FunctionInfo FunctionTable[] = { 10const Interface::FunctionInfo FunctionTable[] = {
11 {0x00010000, nullptr, "Initialize"}, 11 {0x00010000, nullptr, "Initialize"}, {0x00020000, nullptr, "Shutdown"},
12 {0x00020000, nullptr, "Shutdown"}, 12 {0x00030042, nullptr, "StartSendTransfer"}, {0x00040000, nullptr, "WaitSendTransfer"},
13 {0x00030042, nullptr, "StartSendTransfer"}, 13 {0x000500C2, nullptr, "StartRecvTransfer"}, {0x00060000, nullptr, "WaitRecvTransfer"},
14 {0x00040000, nullptr, "WaitSendTransfer"}, 14 {0x00070080, nullptr, "GetRecvTransferCount"}, {0x00080000, nullptr, "GetSendState"},
15 {0x000500C2, nullptr, "StartRecvTransfer"}, 15 {0x00090040, nullptr, "SetBitRate"}, {0x000A0000, nullptr, "GetBitRate"},
16 {0x00060000, nullptr, "WaitRecvTransfer"}, 16 {0x000B0040, nullptr, "SetIRLEDState"}, {0x000C0000, nullptr, "GetIRLEDRecvState"},
17 {0x00070080, nullptr, "GetRecvTransferCount"}, 17 {0x000D0000, nullptr, "GetSendFinishedEvent"}, {0x000E0000, nullptr, "GetRecvFinishedEvent"},
18 {0x00080000, nullptr, "GetSendState"}, 18 {0x000F0000, nullptr, "GetTransferState"}, {0x00100000, nullptr, "GetErrorStatus"},
19 {0x00090040, nullptr, "SetBitRate"}, 19 {0x00110040, nullptr, "SetSleepModeActive"}, {0x00120040, nullptr, "SetSleepModeState"},
20 {0x000A0000, nullptr, "GetBitRate"},
21 {0x000B0040, nullptr, "SetIRLEDState"},
22 {0x000C0000, nullptr, "GetIRLEDRecvState"},
23 {0x000D0000, nullptr, "GetSendFinishedEvent"},
24 {0x000E0000, nullptr, "GetRecvFinishedEvent"},
25 {0x000F0000, nullptr, "GetTransferState"},
26 {0x00100000, nullptr, "GetErrorStatus"},
27 {0x00110040, nullptr, "SetSleepModeActive"},
28 {0x00120040, nullptr, "SetSleepModeState"},
29}; 20};
30 21
31IR_U_Interface::IR_U_Interface() { 22IR_U_Interface::IR_U_Interface() {
diff --git a/src/core/hle/service/ir/ir_user.cpp b/src/core/hle/service/ir/ir_user.cpp
index 06a601029..6cff1d544 100644
--- a/src/core/hle/service/ir/ir_user.cpp
+++ b/src/core/hle/service/ir/ir_user.cpp
@@ -9,32 +9,32 @@ namespace Service {
9namespace IR { 9namespace IR {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010182, nullptr, "InitializeIrNop"}, 12 {0x00010182, nullptr, "InitializeIrNop"},
13 {0x00020000, FinalizeIrNop, "FinalizeIrNop"}, 13 {0x00020000, FinalizeIrNop, "FinalizeIrNop"},
14 {0x00030000, nullptr, "ClearReceiveBuffer"}, 14 {0x00030000, nullptr, "ClearReceiveBuffer"},
15 {0x00040000, nullptr, "ClearSendBuffer"}, 15 {0x00040000, nullptr, "ClearSendBuffer"},
16 {0x000500C0, nullptr, "WaitConnection"}, 16 {0x000500C0, nullptr, "WaitConnection"},
17 {0x00060040, RequireConnection, "RequireConnection"}, 17 {0x00060040, RequireConnection, "RequireConnection"},
18 {0x000702C0, nullptr, "AutoConnection"}, 18 {0x000702C0, nullptr, "AutoConnection"},
19 {0x00080000, nullptr, "AnyConnection"}, 19 {0x00080000, nullptr, "AnyConnection"},
20 {0x00090000, Disconnect, "Disconnect"}, 20 {0x00090000, Disconnect, "Disconnect"},
21 {0x000A0000, nullptr, "GetReceiveEvent"}, 21 {0x000A0000, nullptr, "GetReceiveEvent"},
22 {0x000B0000, nullptr, "GetSendEvent"}, 22 {0x000B0000, nullptr, "GetSendEvent"},
23 {0x000C0000, GetConnectionStatusEvent, "GetConnectionStatusEvent"}, 23 {0x000C0000, GetConnectionStatusEvent, "GetConnectionStatusEvent"},
24 {0x000D0042, nullptr, "SendIrNop"}, 24 {0x000D0042, nullptr, "SendIrNop"},
25 {0x000E0042, nullptr, "SendIrNopLarge"}, 25 {0x000E0042, nullptr, "SendIrNopLarge"},
26 {0x000F0040, nullptr, "ReceiveIrnop"}, 26 {0x000F0040, nullptr, "ReceiveIrnop"},
27 {0x00100042, nullptr, "ReceiveIrnopLarge"}, 27 {0x00100042, nullptr, "ReceiveIrnopLarge"},
28 {0x00110040, nullptr, "GetLatestReceiveErrorResult"}, 28 {0x00110040, nullptr, "GetLatestReceiveErrorResult"},
29 {0x00120040, nullptr, "GetLatestSendErrorResult"}, 29 {0x00120040, nullptr, "GetLatestSendErrorResult"},
30 {0x00130000, nullptr, "GetConnectionStatus"}, 30 {0x00130000, nullptr, "GetConnectionStatus"},
31 {0x00140000, nullptr, "GetTryingToConnectStatus"}, 31 {0x00140000, nullptr, "GetTryingToConnectStatus"},
32 {0x00150000, nullptr, "GetReceiveSizeFreeAndUsed"}, 32 {0x00150000, nullptr, "GetReceiveSizeFreeAndUsed"},
33 {0x00160000, nullptr, "GetSendSizeFreeAndUsed"}, 33 {0x00160000, nullptr, "GetSendSizeFreeAndUsed"},
34 {0x00170000, nullptr, "GetConnectionRole"}, 34 {0x00170000, nullptr, "GetConnectionRole"},
35 {0x00180182, InitializeIrNopShared, "InitializeIrNopShared"}, 35 {0x00180182, InitializeIrNopShared, "InitializeIrNopShared"},
36 {0x00190040, nullptr, "ReleaseReceivedData"}, 36 {0x00190040, nullptr, "ReleaseReceivedData"},
37 {0x001A0040, nullptr, "SetOwnMachineId"}, 37 {0x001A0040, nullptr, "SetOwnMachineId"},
38}; 38};
39 39
40IR_User_Interface::IR_User_Interface() { 40IR_User_Interface::IR_User_Interface() {
diff --git a/src/core/hle/service/ldr_ro/cro_helper.cpp b/src/core/hle/service/ldr_ro/cro_helper.cpp
index 3d2a613ee..5757a4e64 100644
--- a/src/core/hle/service/ldr_ro/cro_helper.cpp
+++ b/src/core/hle/service/ldr_ro/cro_helper.cpp
@@ -14,38 +14,29 @@
14namespace LDR_RO { 14namespace LDR_RO {
15 15
16static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F 16static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F
17 ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 17 ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument,
18 ErrorLevel::Usage);
18 19
19static ResultCode CROFormatError(u32 description) { 20static ResultCode CROFormatError(u32 description) {
20 return ResultCode(static_cast<ErrorDescription>(description), ErrorModule::RO, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 21 return ResultCode(static_cast<ErrorDescription>(description), ErrorModule::RO,
22 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
21} 23}
22 24
23const std::array<int, 17> CROHelper::ENTRY_SIZE {{ 25const std::array<int, 17> CROHelper::ENTRY_SIZE{
24 1, // code 26 {1, // code
25 1, // data 27 1, // data
26 1, // module name 28 1, // module name
27 sizeof(SegmentEntry), 29 sizeof(SegmentEntry), sizeof(ExportNamedSymbolEntry), sizeof(ExportIndexedSymbolEntry),
28 sizeof(ExportNamedSymbolEntry), 30 1, // export strings
29 sizeof(ExportIndexedSymbolEntry), 31 sizeof(ExportTreeEntry), sizeof(ImportModuleEntry), sizeof(ExternalRelocationEntry),
30 1, // export strings 32 sizeof(ImportNamedSymbolEntry), sizeof(ImportIndexedSymbolEntry),
31 sizeof(ExportTreeEntry), 33 sizeof(ImportAnonymousSymbolEntry),
32 sizeof(ImportModuleEntry), 34 1, // import strings
33 sizeof(ExternalRelocationEntry), 35 sizeof(StaticAnonymousSymbolEntry), sizeof(InternalRelocationEntry),
34 sizeof(ImportNamedSymbolEntry), 36 sizeof(StaticRelocationEntry)}};
35 sizeof(ImportIndexedSymbolEntry), 37
36 sizeof(ImportAnonymousSymbolEntry), 38const std::array<CROHelper::HeaderField, 4> CROHelper::FIX_BARRIERS{
37 1, // import strings 39 {Fix0Barrier, Fix1Barrier, Fix2Barrier, Fix3Barrier}};
38 sizeof(StaticAnonymousSymbolEntry),
39 sizeof(InternalRelocationEntry),
40 sizeof(StaticRelocationEntry)
41}};
42
43const std::array<CROHelper::HeaderField, 4> CROHelper::FIX_BARRIERS {{
44 Fix0Barrier,
45 Fix1Barrier,
46 Fix2Barrier,
47 Fix3Barrier
48}};
49 40
50VAddr CROHelper::SegmentTagToAddress(SegmentTag segment_tag) const { 41VAddr CROHelper::SegmentTagToAddress(SegmentTag segment_tag) const {
51 u32 segment_num = GetField(SegmentNum); 42 u32 segment_num = GetField(SegmentNum);
@@ -63,7 +54,7 @@ VAddr CROHelper::SegmentTagToAddress(SegmentTag segment_tag) const {
63} 54}
64 55
65ResultCode CROHelper::ApplyRelocation(VAddr target_address, RelocationType relocation_type, 56ResultCode CROHelper::ApplyRelocation(VAddr target_address, RelocationType relocation_type,
66 u32 addend, u32 symbol_address, u32 target_future_address) { 57 u32 addend, u32 symbol_address, u32 target_future_address) {
67 58
68 switch (relocation_type) { 59 switch (relocation_type) {
69 case RelocationType::Nothing: 60 case RelocationType::Nothing:
@@ -124,7 +115,8 @@ ResultCode CROHelper::ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool
124 return CROFormatError(0x12); 115 return CROFormatError(0x12);
125 } 116 }
126 117
127 ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend, symbol_address, relocation_target); 118 ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend,
119 symbol_address, relocation_target);
128 if (result.IsError()) { 120 if (result.IsError()) {
129 LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); 121 LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw);
130 return result; 122 return result;
@@ -167,7 +159,7 @@ VAddr CROHelper::FindExportNamedSymbol(const std::string& name) const {
167 159
168 if (test_byte >= len) { 160 if (test_byte >= len) {
169 next.raw = entry.left.raw; 161 next.raw = entry.left.raw;
170 } else if((name[test_byte] >> test_bit_in_byte) & 1) { 162 } else if ((name[test_byte] >> test_bit_in_byte) & 1) {
171 next.raw = entry.right.raw; 163 next.raw = entry.right.raw;
172 } else { 164 } else {
173 next.raw = entry.left.raw; 165 next.raw = entry.left.raw;
@@ -212,26 +204,13 @@ ResultCode CROHelper::RebaseHeader(u32 cro_size) {
212 return error; 204 return error;
213 205
214 // verifies that all offsets are in the correct order 206 // verifies that all offsets are in the correct order
215 constexpr std::array<HeaderField, 18> OFFSET_ORDER = {{ 207 constexpr std::array<HeaderField, 18> OFFSET_ORDER = {
216 CodeOffset, 208 {CodeOffset, ModuleNameOffset, SegmentTableOffset, ExportNamedSymbolTableOffset,
217 ModuleNameOffset, 209 ExportTreeTableOffset, ExportIndexedSymbolTableOffset, ExportStringsOffset,
218 SegmentTableOffset, 210 ImportModuleTableOffset, ExternalRelocationTableOffset, ImportNamedSymbolTableOffset,
219 ExportNamedSymbolTableOffset, 211 ImportIndexedSymbolTableOffset, ImportAnonymousSymbolTableOffset, ImportStringsOffset,
220 ExportTreeTableOffset, 212 StaticAnonymousSymbolTableOffset, InternalRelocationTableOffset,
221 ExportIndexedSymbolTableOffset, 213 StaticRelocationTableOffset, DataOffset, FileSize}};
222 ExportStringsOffset,
223 ImportModuleTableOffset,
224 ExternalRelocationTableOffset,
225 ImportNamedSymbolTableOffset,
226 ImportIndexedSymbolTableOffset,
227 ImportAnonymousSymbolTableOffset,
228 ImportStringsOffset,
229 StaticAnonymousSymbolTableOffset,
230 InternalRelocationTableOffset,
231 StaticRelocationTableOffset,
232 DataOffset,
233 FileSize
234 }};
235 214
236 u32 prev_offset = GetField(OFFSET_ORDER[0]); 215 u32 prev_offset = GetField(OFFSET_ORDER[0]);
237 u32 cur_offset; 216 u32 cur_offset;
@@ -266,9 +245,9 @@ ResultCode CROHelper::RebaseHeader(u32 cro_size) {
266 return RESULT_SUCCESS; 245 return RESULT_SUCCESS;
267} 246}
268 247
269ResultVal<VAddr> CROHelper::RebaseSegmentTable(u32 cro_size, 248ResultVal<VAddr> CROHelper::RebaseSegmentTable(u32 cro_size, VAddr data_segment_address,
270 VAddr data_segment_address, u32 data_segment_size, 249 u32 data_segment_size, VAddr bss_segment_address,
271 VAddr bss_segment_address, u32 bss_segment_size) { 250 u32 bss_segment_size) {
272 251
273 u32 prev_data_segment = 0; 252 u32 prev_data_segment = 0;
274 u32 segment_num = GetField(SegmentNum); 253 u32 segment_num = GetField(SegmentNum);
@@ -309,8 +288,8 @@ ResultCode CROHelper::RebaseExportNamedSymbolTable() {
309 288
310 if (entry.name_offset != 0) { 289 if (entry.name_offset != 0) {
311 entry.name_offset += module_address; 290 entry.name_offset += module_address;
312 if (entry.name_offset < export_strings_offset 291 if (entry.name_offset < export_strings_offset ||
313 || entry.name_offset >= export_strings_end) { 292 entry.name_offset >= export_strings_end) {
314 return CROFormatError(0x11); 293 return CROFormatError(0x11);
315 } 294 }
316 } 295 }
@@ -337,9 +316,13 @@ ResultCode CROHelper::RebaseImportModuleTable() {
337 VAddr import_strings_offset = GetField(ImportStringsOffset); 316 VAddr import_strings_offset = GetField(ImportStringsOffset);
338 VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize); 317 VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize);
339 VAddr import_indexed_symbol_table_offset = GetField(ImportIndexedSymbolTableOffset); 318 VAddr import_indexed_symbol_table_offset = GetField(ImportIndexedSymbolTableOffset);
340 VAddr index_import_table_end = import_indexed_symbol_table_offset + GetField(ImportIndexedSymbolNum) * sizeof(ImportIndexedSymbolEntry); 319 VAddr index_import_table_end =
320 import_indexed_symbol_table_offset +
321 GetField(ImportIndexedSymbolNum) * sizeof(ImportIndexedSymbolEntry);
341 VAddr import_anonymous_symbol_table_offset = GetField(ImportAnonymousSymbolTableOffset); 322 VAddr import_anonymous_symbol_table_offset = GetField(ImportAnonymousSymbolTableOffset);
342 VAddr offset_import_table_end = import_anonymous_symbol_table_offset + GetField(ImportAnonymousSymbolNum) * sizeof(ImportAnonymousSymbolEntry); 323 VAddr offset_import_table_end =
324 import_anonymous_symbol_table_offset +
325 GetField(ImportAnonymousSymbolNum) * sizeof(ImportAnonymousSymbolEntry);
343 326
344 u32 module_num = GetField(ImportModuleNum); 327 u32 module_num = GetField(ImportModuleNum);
345 for (u32 i = 0; i < module_num; ++i) { 328 for (u32 i = 0; i < module_num; ++i) {
@@ -348,24 +331,24 @@ ResultCode CROHelper::RebaseImportModuleTable() {
348 331
349 if (entry.name_offset != 0) { 332 if (entry.name_offset != 0) {
350 entry.name_offset += module_address; 333 entry.name_offset += module_address;
351 if (entry.name_offset < import_strings_offset 334 if (entry.name_offset < import_strings_offset ||
352 || entry.name_offset >= import_strings_end) { 335 entry.name_offset >= import_strings_end) {
353 return CROFormatError(0x18); 336 return CROFormatError(0x18);
354 } 337 }
355 } 338 }
356 339
357 if (entry.import_indexed_symbol_table_offset != 0) { 340 if (entry.import_indexed_symbol_table_offset != 0) {
358 entry.import_indexed_symbol_table_offset += module_address; 341 entry.import_indexed_symbol_table_offset += module_address;
359 if (entry.import_indexed_symbol_table_offset < import_indexed_symbol_table_offset 342 if (entry.import_indexed_symbol_table_offset < import_indexed_symbol_table_offset ||
360 || entry.import_indexed_symbol_table_offset > index_import_table_end) { 343 entry.import_indexed_symbol_table_offset > index_import_table_end) {
361 return CROFormatError(0x18); 344 return CROFormatError(0x18);
362 } 345 }
363 } 346 }
364 347
365 if (entry.import_anonymous_symbol_table_offset != 0) { 348 if (entry.import_anonymous_symbol_table_offset != 0) {
366 entry.import_anonymous_symbol_table_offset += module_address; 349 entry.import_anonymous_symbol_table_offset += module_address;
367 if (entry.import_anonymous_symbol_table_offset < import_anonymous_symbol_table_offset 350 if (entry.import_anonymous_symbol_table_offset < import_anonymous_symbol_table_offset ||
368 || entry.import_anonymous_symbol_table_offset > offset_import_table_end) { 351 entry.import_anonymous_symbol_table_offset > offset_import_table_end) {
369 return CROFormatError(0x18); 352 return CROFormatError(0x18);
370 } 353 }
371 } 354 }
@@ -379,25 +362,27 @@ ResultCode CROHelper::RebaseImportNamedSymbolTable() {
379 VAddr import_strings_offset = GetField(ImportStringsOffset); 362 VAddr import_strings_offset = GetField(ImportStringsOffset);
380 VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize); 363 VAddr import_strings_end = import_strings_offset + GetField(ImportStringsSize);
381 VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); 364 VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset);
382 VAddr external_relocation_table_end = external_relocation_table_offset + GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); 365 VAddr external_relocation_table_end =
366 external_relocation_table_offset +
367 GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry);
383 368
384 u32 num = GetField(ImportNamedSymbolNum); 369 u32 num = GetField(ImportNamedSymbolNum);
385 for (u32 i = 0; i < num ; ++i) { 370 for (u32 i = 0; i < num; ++i) {
386 ImportNamedSymbolEntry entry; 371 ImportNamedSymbolEntry entry;
387 GetEntry(i, entry); 372 GetEntry(i, entry);
388 373
389 if (entry.name_offset != 0) { 374 if (entry.name_offset != 0) {
390 entry.name_offset += module_address; 375 entry.name_offset += module_address;
391 if (entry.name_offset < import_strings_offset 376 if (entry.name_offset < import_strings_offset ||
392 || entry.name_offset >= import_strings_end) { 377 entry.name_offset >= import_strings_end) {
393 return CROFormatError(0x1B); 378 return CROFormatError(0x1B);
394 } 379 }
395 } 380 }
396 381
397 if (entry.relocation_batch_offset != 0) { 382 if (entry.relocation_batch_offset != 0) {
398 entry.relocation_batch_offset += module_address; 383 entry.relocation_batch_offset += module_address;
399 if (entry.relocation_batch_offset < external_relocation_table_offset 384 if (entry.relocation_batch_offset < external_relocation_table_offset ||
400 || entry.relocation_batch_offset > external_relocation_table_end) { 385 entry.relocation_batch_offset > external_relocation_table_end) {
401 return CROFormatError(0x1B); 386 return CROFormatError(0x1B);
402 } 387 }
403 } 388 }
@@ -409,17 +394,19 @@ ResultCode CROHelper::RebaseImportNamedSymbolTable() {
409 394
410ResultCode CROHelper::RebaseImportIndexedSymbolTable() { 395ResultCode CROHelper::RebaseImportIndexedSymbolTable() {
411 VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); 396 VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset);
412 VAddr external_relocation_table_end = external_relocation_table_offset + GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); 397 VAddr external_relocation_table_end =
398 external_relocation_table_offset +
399 GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry);
413 400
414 u32 num = GetField(ImportIndexedSymbolNum); 401 u32 num = GetField(ImportIndexedSymbolNum);
415 for (u32 i = 0; i < num ; ++i) { 402 for (u32 i = 0; i < num; ++i) {
416 ImportIndexedSymbolEntry entry; 403 ImportIndexedSymbolEntry entry;
417 GetEntry(i, entry); 404 GetEntry(i, entry);
418 405
419 if (entry.relocation_batch_offset != 0) { 406 if (entry.relocation_batch_offset != 0) {
420 entry.relocation_batch_offset += module_address; 407 entry.relocation_batch_offset += module_address;
421 if (entry.relocation_batch_offset < external_relocation_table_offset 408 if (entry.relocation_batch_offset < external_relocation_table_offset ||
422 || entry.relocation_batch_offset > external_relocation_table_end) { 409 entry.relocation_batch_offset > external_relocation_table_end) {
423 return CROFormatError(0x14); 410 return CROFormatError(0x14);
424 } 411 }
425 } 412 }
@@ -431,17 +418,19 @@ ResultCode CROHelper::RebaseImportIndexedSymbolTable() {
431 418
432ResultCode CROHelper::RebaseImportAnonymousSymbolTable() { 419ResultCode CROHelper::RebaseImportAnonymousSymbolTable() {
433 VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset); 420 VAddr external_relocation_table_offset = GetField(ExternalRelocationTableOffset);
434 VAddr external_relocation_table_end = external_relocation_table_offset + GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry); 421 VAddr external_relocation_table_end =
422 external_relocation_table_offset +
423 GetField(ExternalRelocationNum) * sizeof(ExternalRelocationEntry);
435 424
436 u32 num = GetField(ImportAnonymousSymbolNum); 425 u32 num = GetField(ImportAnonymousSymbolNum);
437 for (u32 i = 0; i < num ; ++i) { 426 for (u32 i = 0; i < num; ++i) {
438 ImportAnonymousSymbolEntry entry; 427 ImportAnonymousSymbolEntry entry;
439 GetEntry(i, entry); 428 GetEntry(i, entry);
440 429
441 if (entry.relocation_batch_offset != 0) { 430 if (entry.relocation_batch_offset != 0) {
442 entry.relocation_batch_offset += module_address; 431 entry.relocation_batch_offset += module_address;
443 if (entry.relocation_batch_offset < external_relocation_table_offset 432 if (entry.relocation_batch_offset < external_relocation_table_offset ||
444 || entry.relocation_batch_offset > external_relocation_table_end) { 433 entry.relocation_batch_offset > external_relocation_table_end) {
445 return CROFormatError(0x17); 434 return CROFormatError(0x17);
446 } 435 }
447 } 436 }
@@ -475,7 +464,8 @@ ResultCode CROHelper::ResetExternalRelocations() {
475 return CROFormatError(0x12); 464 return CROFormatError(0x12);
476 } 465 }
477 466
478 ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend, unresolved_symbol, relocation_target); 467 ResultCode result = ApplyRelocation(relocation_target, relocation.type, relocation.addend,
468 unresolved_symbol, relocation_target);
479 if (result.IsError()) { 469 if (result.IsError()) {
480 LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); 470 LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw);
481 return result; 471 return result;
@@ -528,23 +518,27 @@ ResultCode CROHelper::ClearExternalRelocations() {
528 518
529ResultCode CROHelper::ApplyStaticAnonymousSymbolToCRS(VAddr crs_address) { 519ResultCode CROHelper::ApplyStaticAnonymousSymbolToCRS(VAddr crs_address) {
530 VAddr static_relocation_table_offset = GetField(StaticRelocationTableOffset); 520 VAddr static_relocation_table_offset = GetField(StaticRelocationTableOffset);
531 VAddr static_relocation_table_end = static_relocation_table_offset + GetField(StaticRelocationNum) * sizeof(StaticRelocationEntry); 521 VAddr static_relocation_table_end =
522 static_relocation_table_offset +
523 GetField(StaticRelocationNum) * sizeof(StaticRelocationEntry);
532 524
533 CROHelper crs(crs_address); 525 CROHelper crs(crs_address);
534 u32 offset_export_num = GetField(StaticAnonymousSymbolNum); 526 u32 offset_export_num = GetField(StaticAnonymousSymbolNum);
535 LOG_INFO(Service_LDR, "CRO \"%s\" exports %d static anonymous symbols", ModuleName().data(), offset_export_num); 527 LOG_INFO(Service_LDR, "CRO \"%s\" exports %d static anonymous symbols", ModuleName().data(),
528 offset_export_num);
536 for (u32 i = 0; i < offset_export_num; ++i) { 529 for (u32 i = 0; i < offset_export_num; ++i) {
537 StaticAnonymousSymbolEntry entry; 530 StaticAnonymousSymbolEntry entry;
538 GetEntry(i, entry); 531 GetEntry(i, entry);
539 u32 batch_address = entry.relocation_batch_offset + module_address; 532 u32 batch_address = entry.relocation_batch_offset + module_address;
540 533
541 if (batch_address < static_relocation_table_offset 534 if (batch_address < static_relocation_table_offset ||
542 || batch_address > static_relocation_table_end) { 535 batch_address > static_relocation_table_end) {
543 return CROFormatError(0x16); 536 return CROFormatError(0x16);
544 } 537 }
545 538
546 u32 symbol_address = SegmentTagToAddress(entry.symbol_position); 539 u32 symbol_address = SegmentTagToAddress(entry.symbol_position);
547 LOG_TRACE(Service_LDR, "CRO \"%s\" exports 0x%08X to the static module", ModuleName().data(), symbol_address); 540 LOG_TRACE(Service_LDR, "CRO \"%s\" exports 0x%08X to the static module",
541 ModuleName().data(), symbol_address);
548 ResultCode result = crs.ApplyRelocationBatch(batch_address, symbol_address); 542 ResultCode result = crs.ApplyRelocationBatch(batch_address, symbol_address);
549 if (result.IsError()) { 543 if (result.IsError()) {
550 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 544 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
@@ -571,7 +565,8 @@ ResultCode CROHelper::ApplyInternalRelocations(u32 old_data_segment_address) {
571 565
572 if (target_segment.type == SegmentType::Data) { 566 if (target_segment.type == SegmentType::Data) {
573 // If the relocation is to the .data segment, we need to relocate it in the old buffer 567 // If the relocation is to the .data segment, we need to relocate it in the old buffer
574 target_address = old_data_segment_address + relocation.target_position.offset_into_segment; 568 target_address =
569 old_data_segment_address + relocation.target_position.offset_into_segment;
575 } else { 570 } else {
576 target_address = target_addressB; 571 target_address = target_addressB;
577 } 572 }
@@ -582,8 +577,10 @@ ResultCode CROHelper::ApplyInternalRelocations(u32 old_data_segment_address) {
582 577
583 SegmentEntry symbol_segment; 578 SegmentEntry symbol_segment;
584 GetEntry(relocation.symbol_segment, symbol_segment); 579 GetEntry(relocation.symbol_segment, symbol_segment);
585 LOG_TRACE(Service_LDR, "Internally relocates 0x%08X with 0x%08X", target_address, symbol_segment.offset); 580 LOG_TRACE(Service_LDR, "Internally relocates 0x%08X with 0x%08X", target_address,
586 ResultCode result = ApplyRelocation(target_address, relocation.type, relocation.addend, symbol_segment.offset, target_addressB); 581 symbol_segment.offset);
582 ResultCode result = ApplyRelocation(target_address, relocation.type, relocation.addend,
583 symbol_segment.offset, target_addressB);
587 if (result.IsError()) { 584 if (result.IsError()) {
588 LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw); 585 LOG_ERROR(Service_LDR, "Error applying relocation %08X", result.raw);
589 return result; 586 return result;
@@ -734,25 +731,29 @@ ResultCode CROHelper::ApplyImportNamedSymbol(VAddr crs_address) {
734 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); 731 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry));
735 732
736 if (!relocation_entry.is_batch_resolved) { 733 if (!relocation_entry.is_batch_resolved) {
737 ResultCode result = ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { 734 ResultCode result =
738 std::string symbol_name = Memory::ReadCString(entry.name_offset, import_strings_size); 735 ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> {
739 u32 symbol_address = source.FindExportNamedSymbol(symbol_name); 736 std::string symbol_name =
740 737 Memory::ReadCString(entry.name_offset, import_strings_size);
741 if (symbol_address != 0) { 738 u32 symbol_address = source.FindExportNamedSymbol(symbol_name);
742 LOG_TRACE(Service_LDR, "CRO \"%s\" imports \"%s\" from \"%s\"", 739
743 ModuleName().data(), symbol_name.data(), source.ModuleName().data()); 740 if (symbol_address != 0) {
744 741 LOG_TRACE(Service_LDR, "CRO \"%s\" imports \"%s\" from \"%s\"",
745 ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address); 742 ModuleName().data(), symbol_name.data(),
746 if (result.IsError()) { 743 source.ModuleName().data());
747 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 744
748 return result; 745 ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address);
746 if (result.IsError()) {
747 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X",
748 result.raw);
749 return result;
750 }
751
752 return MakeResult<bool>(false);
749 } 753 }
750 754
751 return MakeResult<bool>(false); 755 return MakeResult<bool>(true);
752 } 756 });
753
754 return MakeResult<bool>(true);
755 });
756 if (result.IsError()) { 757 if (result.IsError()) {
757 return result; 758 return result;
758 } 759 }
@@ -777,7 +778,6 @@ ResultCode CROHelper::ResetImportNamedSymbol() {
777 LOG_ERROR(Service_LDR, "Error reseting relocation batch %08X", result.raw); 778 LOG_ERROR(Service_LDR, "Error reseting relocation batch %08X", result.raw);
778 return result; 779 return result;
779 } 780 }
780
781 } 781 }
782 return RESULT_SUCCESS; 782 return RESULT_SUCCESS;
783} 783}
@@ -831,40 +831,47 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) {
831 GetEntry(i, entry); 831 GetEntry(i, entry);
832 std::string want_cro_name = Memory::ReadCString(entry.name_offset, import_strings_size); 832 std::string want_cro_name = Memory::ReadCString(entry.name_offset, import_strings_size);
833 833
834 ResultCode result = ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { 834 ResultCode result =
835 if (want_cro_name == source.ModuleName()) { 835 ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> {
836 LOG_INFO(Service_LDR, "CRO \"%s\" imports %d indexed symbols from \"%s\"", 836 if (want_cro_name == source.ModuleName()) {
837 ModuleName().data(), entry.import_indexed_symbol_num, source.ModuleName().data()); 837 LOG_INFO(Service_LDR, "CRO \"%s\" imports %d indexed symbols from \"%s\"",
838 for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { 838 ModuleName().data(), entry.import_indexed_symbol_num,
839 ImportIndexedSymbolEntry im; 839 source.ModuleName().data());
840 entry.GetImportIndexedSymbolEntry(j, im); 840 for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) {
841 ExportIndexedSymbolEntry ex; 841 ImportIndexedSymbolEntry im;
842 source.GetEntry(im.index, ex); 842 entry.GetImportIndexedSymbolEntry(j, im);
843 u32 symbol_address = source.SegmentTagToAddress(ex.symbol_position); 843 ExportIndexedSymbolEntry ex;
844 LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address); 844 source.GetEntry(im.index, ex);
845 ResultCode result = ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); 845 u32 symbol_address = source.SegmentTagToAddress(ex.symbol_position);
846 if (result.IsError()) { 846 LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address);
847 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 847 ResultCode result =
848 return result; 848 ApplyRelocationBatch(im.relocation_batch_offset, symbol_address);
849 if (result.IsError()) {
850 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X",
851 result.raw);
852 return result;
853 }
849 } 854 }
850 } 855 LOG_INFO(Service_LDR, "CRO \"%s\" imports %d anonymous symbols from \"%s\"",
851 LOG_INFO(Service_LDR, "CRO \"%s\" imports %d anonymous symbols from \"%s\"", 856 ModuleName().data(), entry.import_anonymous_symbol_num,
852 ModuleName().data(), entry.import_anonymous_symbol_num, source.ModuleName().data()); 857 source.ModuleName().data());
853 for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { 858 for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) {
854 ImportAnonymousSymbolEntry im; 859 ImportAnonymousSymbolEntry im;
855 entry.GetImportAnonymousSymbolEntry(j, im); 860 entry.GetImportAnonymousSymbolEntry(j, im);
856 u32 symbol_address = source.SegmentTagToAddress(im.symbol_position); 861 u32 symbol_address = source.SegmentTagToAddress(im.symbol_position);
857 LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address); 862 LOG_TRACE(Service_LDR, " Imports 0x%08X", symbol_address);
858 ResultCode result = ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); 863 ResultCode result =
859 if (result.IsError()) { 864 ApplyRelocationBatch(im.relocation_batch_offset, symbol_address);
860 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 865 if (result.IsError()) {
861 return result; 866 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X",
867 result.raw);
868 return result;
869 }
862 } 870 }
871 return MakeResult<bool>(false);
863 } 872 }
864 return MakeResult<bool>(false); 873 return MakeResult<bool>(true);
865 } 874 });
866 return MakeResult<bool>(true);
867 });
868 if (result.IsError()) { 875 if (result.IsError()) {
869 return result; 876 return result;
870 } 877 }
@@ -873,8 +880,8 @@ ResultCode CROHelper::ApplyModuleImport(VAddr crs_address) {
873} 880}
874 881
875ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) { 882ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) {
876 LOG_DEBUG(Service_LDR, "CRO \"%s\" exports named symbols to \"%s\"", 883 LOG_DEBUG(Service_LDR, "CRO \"%s\" exports named symbols to \"%s\"", ModuleName().data(),
877 ModuleName().data(), target.ModuleName().data()); 884 target.ModuleName().data());
878 u32 target_import_strings_size = target.GetField(ImportStringsSize); 885 u32 target_import_strings_size = target.GetField(ImportStringsSize);
879 u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum); 886 u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum);
880 for (u32 i = 0; i < target_symbol_import_num; ++i) { 887 for (u32 i = 0; i < target_symbol_import_num; ++i) {
@@ -885,7 +892,8 @@ ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) {
885 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); 892 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry));
886 893
887 if (!relocation_entry.is_batch_resolved) { 894 if (!relocation_entry.is_batch_resolved) {
888 std::string symbol_name = Memory::ReadCString(entry.name_offset, target_import_strings_size); 895 std::string symbol_name =
896 Memory::ReadCString(entry.name_offset, target_import_strings_size);
889 u32 symbol_address = FindExportNamedSymbol(symbol_name); 897 u32 symbol_address = FindExportNamedSymbol(symbol_name);
890 if (symbol_address != 0) { 898 if (symbol_address != 0) {
891 LOG_TRACE(Service_LDR, " exports symbol \"%s\"", symbol_name.data()); 899 LOG_TRACE(Service_LDR, " exports symbol \"%s\"", symbol_name.data());
@@ -901,8 +909,8 @@ ResultCode CROHelper::ApplyExportNamedSymbol(CROHelper target) {
901} 909}
902 910
903ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) { 911ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) {
904 LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports named symbols to \"%s\"", 912 LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports named symbols to \"%s\"", ModuleName().data(),
905 ModuleName().data(), target.ModuleName().data()); 913 target.ModuleName().data());
906 u32 unresolved_symbol = target.GetOnUnresolvedAddress(); 914 u32 unresolved_symbol = target.GetOnUnresolvedAddress();
907 u32 target_import_strings_size = target.GetField(ImportStringsSize); 915 u32 target_import_strings_size = target.GetField(ImportStringsSize);
908 u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum); 916 u32 target_symbol_import_num = target.GetField(ImportNamedSymbolNum);
@@ -914,11 +922,13 @@ ResultCode CROHelper::ResetExportNamedSymbol(CROHelper target) {
914 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); 922 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry));
915 923
916 if (relocation_entry.is_batch_resolved) { 924 if (relocation_entry.is_batch_resolved) {
917 std::string symbol_name = Memory::ReadCString(entry.name_offset, target_import_strings_size); 925 std::string symbol_name =
926 Memory::ReadCString(entry.name_offset, target_import_strings_size);
918 u32 symbol_address = FindExportNamedSymbol(symbol_name); 927 u32 symbol_address = FindExportNamedSymbol(symbol_name);
919 if (symbol_address != 0) { 928 if (symbol_address != 0) {
920 LOG_TRACE(Service_LDR, " unexports symbol \"%s\"", symbol_name.data()); 929 LOG_TRACE(Service_LDR, " unexports symbol \"%s\"", symbol_name.data());
921 ResultCode result = target.ApplyRelocationBatch(relocation_addr, unresolved_symbol, true); 930 ResultCode result =
931 target.ApplyRelocationBatch(relocation_addr, unresolved_symbol, true);
922 if (result.IsError()) { 932 if (result.IsError()) {
923 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 933 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
924 return result; 934 return result;
@@ -940,8 +950,8 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) {
940 if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name) 950 if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name)
941 continue; 951 continue;
942 952
943 LOG_INFO(Service_LDR, "CRO \"%s\" exports %d indexed symbols to \"%s\"", 953 LOG_INFO(Service_LDR, "CRO \"%s\" exports %d indexed symbols to \"%s\"", module_name.data(),
944 module_name.data(), entry.import_indexed_symbol_num, target.ModuleName().data()); 954 entry.import_indexed_symbol_num, target.ModuleName().data());
945 for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { 955 for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) {
946 ImportIndexedSymbolEntry im; 956 ImportIndexedSymbolEntry im;
947 entry.GetImportIndexedSymbolEntry(j, im); 957 entry.GetImportIndexedSymbolEntry(j, im);
@@ -949,7 +959,8 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) {
949 GetEntry(im.index, ex); 959 GetEntry(im.index, ex);
950 u32 symbol_address = SegmentTagToAddress(ex.symbol_position); 960 u32 symbol_address = SegmentTagToAddress(ex.symbol_position);
951 LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address); 961 LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address);
952 ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); 962 ResultCode result =
963 target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address);
953 if (result.IsError()) { 964 if (result.IsError()) {
954 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 965 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
955 return result; 966 return result;
@@ -957,13 +968,14 @@ ResultCode CROHelper::ApplyModuleExport(CROHelper target) {
957 } 968 }
958 969
959 LOG_INFO(Service_LDR, "CRO \"%s\" exports %d anonymous symbols to \"%s\"", 970 LOG_INFO(Service_LDR, "CRO \"%s\" exports %d anonymous symbols to \"%s\"",
960 module_name.data(), entry.import_anonymous_symbol_num, target.ModuleName().data()); 971 module_name.data(), entry.import_anonymous_symbol_num, target.ModuleName().data());
961 for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { 972 for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) {
962 ImportAnonymousSymbolEntry im; 973 ImportAnonymousSymbolEntry im;
963 entry.GetImportAnonymousSymbolEntry(j, im); 974 entry.GetImportAnonymousSymbolEntry(j, im);
964 u32 symbol_address = SegmentTagToAddress(im.symbol_position); 975 u32 symbol_address = SegmentTagToAddress(im.symbol_position);
965 LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address); 976 LOG_TRACE(Service_LDR, " exports symbol 0x%08X", symbol_address);
966 ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address); 977 ResultCode result =
978 target.ApplyRelocationBatch(im.relocation_batch_offset, symbol_address);
967 if (result.IsError()) { 979 if (result.IsError()) {
968 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 980 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
969 return result; 981 return result;
@@ -987,12 +999,13 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) {
987 if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name) 999 if (Memory::ReadCString(entry.name_offset, target_import_string_size) != module_name)
988 continue; 1000 continue;
989 1001
990 LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports indexed symbols to \"%s\"", 1002 LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports indexed symbols to \"%s\"", module_name.data(),
991 module_name.data(), target.ModuleName().data()); 1003 target.ModuleName().data());
992 for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) { 1004 for (u32 j = 0; j < entry.import_indexed_symbol_num; ++j) {
993 ImportIndexedSymbolEntry im; 1005 ImportIndexedSymbolEntry im;
994 entry.GetImportIndexedSymbolEntry(j, im); 1006 entry.GetImportIndexedSymbolEntry(j, im);
995 ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); 1007 ResultCode result =
1008 target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true);
996 if (result.IsError()) { 1009 if (result.IsError()) {
997 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 1010 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
998 return result; 1011 return result;
@@ -1000,11 +1013,12 @@ ResultCode CROHelper::ResetModuleExport(CROHelper target) {
1000 } 1013 }
1001 1014
1002 LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports anonymous symbols to \"%s\"", 1015 LOG_DEBUG(Service_LDR, "CRO \"%s\" unexports anonymous symbols to \"%s\"",
1003 module_name.data(), target.ModuleName().data()); 1016 module_name.data(), target.ModuleName().data());
1004 for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) { 1017 for (u32 j = 0; j < entry.import_anonymous_symbol_num; ++j) {
1005 ImportAnonymousSymbolEntry im; 1018 ImportAnonymousSymbolEntry im;
1006 entry.GetImportAnonymousSymbolEntry(j, im); 1019 entry.GetImportAnonymousSymbolEntry(j, im);
1007 ResultCode result = target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true); 1020 ResultCode result =
1021 target.ApplyRelocationBatch(im.relocation_batch_offset, unresolved_symbol, true);
1008 if (result.IsError()) { 1022 if (result.IsError()) {
1009 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 1023 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw);
1010 return result; 1024 return result;
@@ -1025,25 +1039,27 @@ ResultCode CROHelper::ApplyExitRelocations(VAddr crs_address) {
1025 ExternalRelocationEntry relocation_entry; 1039 ExternalRelocationEntry relocation_entry;
1026 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry)); 1040 Memory::ReadBlock(relocation_addr, &relocation_entry, sizeof(ExternalRelocationEntry));
1027 1041
1028 if (Memory::ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit"){ 1042 if (Memory::ReadCString(entry.name_offset, import_strings_size) == "__aeabi_atexit") {
1029 ResultCode result = ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> { 1043 ResultCode result =
1030 u32 symbol_address = source.FindExportNamedSymbol("nnroAeabiAtexit_"); 1044 ForEachAutoLinkCRO(crs_address, [&](CROHelper source) -> ResultVal<bool> {
1045 u32 symbol_address = source.FindExportNamedSymbol("nnroAeabiAtexit_");
1031 1046
1032 if (symbol_address != 0) { 1047 if (symbol_address != 0) {
1033 LOG_DEBUG(Service_LDR, "CRO \"%s\" import exit function from \"%s\"", 1048 LOG_DEBUG(Service_LDR, "CRO \"%s\" import exit function from \"%s\"",
1034 ModuleName().data(), source.ModuleName().data()); 1049 ModuleName().data(), source.ModuleName().data());
1035 1050
1036 ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address); 1051 ResultCode result = ApplyRelocationBatch(relocation_addr, symbol_address);
1037 if (result.IsError()) { 1052 if (result.IsError()) {
1038 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X", result.raw); 1053 LOG_ERROR(Service_LDR, "Error applying relocation batch %08X",
1039 return result; 1054 result.raw);
1040 } 1055 return result;
1056 }
1041 1057
1042 return MakeResult<bool>(false); 1058 return MakeResult<bool>(false);
1043 } 1059 }
1044 1060
1045 return MakeResult<bool>(true); 1061 return MakeResult<bool>(true);
1046 }); 1062 });
1047 if (result.IsError()) { 1063 if (result.IsError()) {
1048 LOG_ERROR(Service_LDR, "Error applying exit relocation %08X", result.raw); 1064 LOG_ERROR(Service_LDR, "Error applying exit relocation %08X", result.raw);
1049 return result; 1065 return result;
@@ -1070,9 +1086,9 @@ static ResultCode VerifyStringTableLength(VAddr address, u32 size) {
1070 return RESULT_SUCCESS; 1086 return RESULT_SUCCESS;
1071} 1087}
1072 1088
1073ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, 1089ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment_addresss,
1074 VAddr data_segment_addresss, u32 data_segment_size, 1090 u32 data_segment_size, VAddr bss_segment_address, u32 bss_segment_size,
1075 VAddr bss_segment_address, u32 bss_segment_size, bool is_crs) { 1091 bool is_crs) {
1076 1092
1077 ResultCode result = RebaseHeader(cro_size); 1093 ResultCode result = RebaseHeader(cro_size);
1078 if (result.IsError()) { 1094 if (result.IsError()) {
@@ -1088,9 +1104,8 @@ ResultCode CROHelper::Rebase(VAddr crs_address, u32 cro_size,
1088 1104
1089 u32 prev_data_segment_address = 0; 1105 u32 prev_data_segment_address = 0;
1090 if (!is_crs) { 1106 if (!is_crs) {
1091 auto result_val = RebaseSegmentTable(cro_size, 1107 auto result_val = RebaseSegmentTable(cro_size, data_segment_addresss, data_segment_size,
1092 data_segment_addresss, data_segment_size, 1108 bss_segment_address, bss_segment_size);
1093 bss_segment_address, bss_segment_size);
1094 if (result_val.Failed()) { 1109 if (result_val.Failed()) {
1095 LOG_ERROR(Service_LDR, "Error rebasing segment table %08X", result_val.Code().raw); 1110 LOG_ERROR(Service_LDR, "Error rebasing segment table %08X", result_val.Code().raw);
1096 return result_val.Code(); 1111 return result_val.Code();
@@ -1374,7 +1389,8 @@ void CROHelper::Unregister(VAddr crs_address) {
1374 CROHelper next_head(crs.NextModule()), previous_head(crs.PreviousModule()); 1389 CROHelper next_head(crs.NextModule()), previous_head(crs.PreviousModule());
1375 CROHelper next(NextModule()), previous(PreviousModule()); 1390 CROHelper next(NextModule()), previous(PreviousModule());
1376 1391
1377 if (module_address == next_head.module_address || module_address == previous_head.module_address) { 1392 if (module_address == next_head.module_address ||
1393 module_address == previous_head.module_address) {
1378 // removing head 1394 // removing head
1379 if (next.module_address) { 1395 if (next.module_address) {
1380 // the next is new head 1396 // the next is new head
@@ -1400,7 +1416,8 @@ void CROHelper::Unregister(VAddr crs_address) {
1400 // let head's previous point to the new tail 1416 // let head's previous point to the new tail
1401 if (next_head.module_address && next_head.PreviousModule() == module_address) { 1417 if (next_head.module_address && next_head.PreviousModule() == module_address) {
1402 next_head.SetPreviousModule(previous.module_address); 1418 next_head.SetPreviousModule(previous.module_address);
1403 } else if (previous_head.module_address && previous_head.PreviousModule() == module_address) { 1419 } else if (previous_head.module_address &&
1420 previous_head.PreviousModule() == module_address) {
1404 previous_head.SetPreviousModule(previous.module_address); 1421 previous_head.SetPreviousModule(previous.module_address);
1405 } else { 1422 } else {
1406 UNREACHABLE(); 1423 UNREACHABLE();
@@ -1419,9 +1436,9 @@ u32 CROHelper::GetFixEnd(u32 fix_level) const {
1419 u32 entry_size_i = 2; 1436 u32 entry_size_i = 2;
1420 int field = ModuleNameOffset; 1437 int field = ModuleNameOffset;
1421 while (true) { 1438 while (true) {
1422 end = std::max<u32>(end, 1439 end = std::max<u32>(end, GetField(static_cast<HeaderField>(field)) +
1423 GetField(static_cast<HeaderField>(field)) + 1440 GetField(static_cast<HeaderField>(field + 1)) *
1424 GetField(static_cast<HeaderField>(field + 1)) * ENTRY_SIZE[entry_size_i]); 1441 ENTRY_SIZE[entry_size_i]);
1425 1442
1426 ++entry_size_i; 1443 ++entry_size_i;
1427 field += 2; 1444 field += 2;
diff --git a/src/core/hle/service/ldr_ro/cro_helper.h b/src/core/hle/service/ldr_ro/cro_helper.h
index 34e357afd..e4457d4be 100644
--- a/src/core/hle/service/ldr_ro/cro_helper.h
+++ b/src/core/hle/service/ldr_ro/cro_helper.h
@@ -10,8 +10,8 @@
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/swap.h" 11#include "common/swap.h"
12 12
13#include "core/memory.h"
14#include "core/hle/result.h" 13#include "core/hle/result.h"
14#include "core/memory.h"
15 15
16//////////////////////////////////////////////////////////////////////////////////////////////////// 16////////////////////////////////////////////////////////////////////////////////////////////////////
17// Namespace LDR_RO 17// Namespace LDR_RO
@@ -21,14 +21,17 @@ namespace LDR_RO {
21// GCC versions < 5.0 do not implement std::is_trivially_copyable. 21// GCC versions < 5.0 do not implement std::is_trivially_copyable.
22// Excluding MSVC because it has weird behaviour for std::is_trivially_copyable. 22// Excluding MSVC because it has weird behaviour for std::is_trivially_copyable.
23#if (__GNUC__ >= 5) || defined(__clang__) 23#if (__GNUC__ >= 5) || defined(__clang__)
24 #define ASSERT_CRO_STRUCT(name, size) \ 24#define ASSERT_CRO_STRUCT(name, size) \
25 static_assert(std::is_standard_layout<name>::value, "CRO structure " #name " doesn't use standard layout"); \ 25 static_assert(std::is_standard_layout<name>::value, \
26 static_assert(std::is_trivially_copyable<name>::value, "CRO structure " #name " isn't trivially copyable"); \ 26 "CRO structure " #name " doesn't use standard layout"); \
27 static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name) 27 static_assert(std::is_trivially_copyable<name>::value, \
28 "CRO structure " #name " isn't trivially copyable"); \
29 static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name)
28#else 30#else
29 #define ASSERT_CRO_STRUCT(name, size) \ 31#define ASSERT_CRO_STRUCT(name, size) \
30 static_assert(std::is_standard_layout<name>::value, "CRO structure " #name " doesn't use standard layout"); \ 32 static_assert(std::is_standard_layout<name>::value, \
31 static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name) 33 "CRO structure " #name " doesn't use standard layout"); \
34 static_assert(sizeof(name) == (size), "Unexpected struct size for CRO structure " #name)
32#endif 35#endif
33 36
34static constexpr u32 CRO_HEADER_SIZE = 0x138; 37static constexpr u32 CRO_HEADER_SIZE = 0x138;
@@ -59,9 +62,9 @@ public:
59 * @param is_crs true if the module itself is the static module 62 * @param is_crs true if the module itself is the static module
60 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. 63 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
61 */ 64 */
62 ResultCode Rebase(VAddr crs_address, u32 cro_size, 65 ResultCode Rebase(VAddr crs_address, u32 cro_size, VAddr data_segment_addresss,
63 VAddr data_segment_addresss, u32 data_segment_size, 66 u32 data_segment_size, VAddr bss_segment_address, u32 bss_segment_size,
64 VAddr bss_segment_address, u32 bss_segment_size, bool is_crs); 67 bool is_crs);
65 68
66 /** 69 /**
67 * Unrebases the module. 70 * Unrebases the module.
@@ -148,8 +151,10 @@ private:
148 const VAddr module_address; ///< the virtual address of this module 151 const VAddr module_address; ///< the virtual address of this module
149 152
150 /** 153 /**
151 * Each item in this enum represents a u32 field in the header begin from address+0x80, successively. 154 * Each item in this enum represents a u32 field in the header begin from address+0x80,
152 * We don't directly use a struct here, to avoid GetPointer, reinterpret_cast, or Read/WriteBlock repeatedly. 155 * successively.
156 * We don't directly use a struct here, to avoid GetPointer, reinterpret_cast, or
157 * Read/WriteBlock repeatedly.
153 */ 158 */
154 enum HeaderField { 159 enum HeaderField {
155 Magic = 0, 160 Magic = 0,
@@ -208,18 +213,20 @@ private:
208 Fix2Barrier = ImportModuleTableOffset, 213 Fix2Barrier = ImportModuleTableOffset,
209 Fix1Barrier = StaticAnonymousSymbolTableOffset, 214 Fix1Barrier = StaticAnonymousSymbolTableOffset,
210 }; 215 };
211 static_assert(Fix0Barrier == (CRO_HEADER_SIZE - CRO_HASH_SIZE) / 4, "CRO Header fields are wrong!"); 216 static_assert(Fix0Barrier == (CRO_HEADER_SIZE - CRO_HASH_SIZE) / 4,
217 "CRO Header fields are wrong!");
212 218
213 enum class SegmentType : u32 { 219 enum class SegmentType : u32 {
214 Code = 0, 220 Code = 0,
215 ROData = 1, 221 ROData = 1,
216 Data = 2, 222 Data = 2,
217 BSS = 3, 223 BSS = 3,
218 }; 224 };
219 225
220 /** 226 /**
221 * Identifies a program location inside of a segment. 227 * Identifies a program location inside of a segment.
222 * Required to refer to program locations because individual segments may be relocated independently of each other. 228 * Required to refer to program locations because individual segments may be relocated
229 * independently of each other.
223 */ 230 */
224 union SegmentTag { 231 union SegmentTag {
225 u32_le raw; 232 u32_le raw;
@@ -227,7 +234,8 @@ private:
227 BitField<4, 28, u32_le> offset_into_segment; 234 BitField<4, 28, u32_le> offset_into_segment;
228 235
229 SegmentTag() = default; 236 SegmentTag() = default;
230 explicit SegmentTag(u32 raw_) : raw(raw_) {} 237 explicit SegmentTag(u32 raw_) : raw(raw_) {
238 }
231 }; 239 };
232 240
233 /// Information of a segment in this module. 241 /// Information of a segment in this module.
@@ -282,7 +290,7 @@ private:
282 290
283 /// Identifies an indexed symbol imported from another module. 291 /// Identifies an indexed symbol imported from another module.
284 struct ImportIndexedSymbolEntry { 292 struct ImportIndexedSymbolEntry {
285 u32_le index; // index of an ExportIndexedSymbolEntry in the exporting module 293 u32_le index; // index of an ExportIndexedSymbolEntry in the exporting module
286 u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable 294 u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable
287 295
288 static constexpr HeaderField TABLE_OFFSET_FIELD = ImportIndexedSymbolTableOffset; 296 static constexpr HeaderField TABLE_OFFSET_FIELD = ImportIndexedSymbolTableOffset;
@@ -291,8 +299,8 @@ private:
291 299
292 /// Identifies an anonymous symbol imported from another module. 300 /// Identifies an anonymous symbol imported from another module.
293 struct ImportAnonymousSymbolEntry { 301 struct ImportAnonymousSymbolEntry {
294 SegmentTag symbol_position; // in the exporting segment 302 SegmentTag symbol_position; // in the exporting segment
295 u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable 303 u32_le relocation_batch_offset; // pointing to a relocation batch in ExternalRelocationTable
296 304
297 static constexpr HeaderField TABLE_OFFSET_FIELD = ImportAnonymousSymbolTableOffset; 305 static constexpr HeaderField TABLE_OFFSET_FIELD = ImportAnonymousSymbolTableOffset;
298 }; 306 };
@@ -300,42 +308,47 @@ private:
300 308
301 /// Information of a imported module and symbols imported from it. 309 /// Information of a imported module and symbols imported from it.
302 struct ImportModuleEntry { 310 struct ImportModuleEntry {
303 u32_le name_offset; // pointing to a substring in ImportStrings 311 u32_le name_offset; // pointing to a substring in ImportStrings
304 u32_le import_indexed_symbol_table_offset; // pointing to a subtable in ImportIndexedSymbolTable 312 u32_le import_indexed_symbol_table_offset; // pointing to a subtable in
313 // ImportIndexedSymbolTable
305 u32_le import_indexed_symbol_num; 314 u32_le import_indexed_symbol_num;
306 u32_le import_anonymous_symbol_table_offset; // pointing to a subtable in ImportAnonymousSymbolTable 315 u32_le import_anonymous_symbol_table_offset; // pointing to a subtable in
316 // ImportAnonymousSymbolTable
307 u32_le import_anonymous_symbol_num; 317 u32_le import_anonymous_symbol_num;
308 318
309 static constexpr HeaderField TABLE_OFFSET_FIELD = ImportModuleTableOffset; 319 static constexpr HeaderField TABLE_OFFSET_FIELD = ImportModuleTableOffset;
310 320
311 void GetImportIndexedSymbolEntry(u32 index, ImportIndexedSymbolEntry& entry) { 321 void GetImportIndexedSymbolEntry(u32 index, ImportIndexedSymbolEntry& entry) {
312 Memory::ReadBlock(import_indexed_symbol_table_offset + index * sizeof(ImportIndexedSymbolEntry), 322 Memory::ReadBlock(import_indexed_symbol_table_offset +
313 &entry, sizeof(ImportIndexedSymbolEntry)); 323 index * sizeof(ImportIndexedSymbolEntry),
324 &entry, sizeof(ImportIndexedSymbolEntry));
314 } 325 }
315 326
316 void GetImportAnonymousSymbolEntry(u32 index, ImportAnonymousSymbolEntry& entry) { 327 void GetImportAnonymousSymbolEntry(u32 index, ImportAnonymousSymbolEntry& entry) {
317 Memory::ReadBlock(import_anonymous_symbol_table_offset + index * sizeof(ImportAnonymousSymbolEntry), 328 Memory::ReadBlock(import_anonymous_symbol_table_offset +
318 &entry, sizeof(ImportAnonymousSymbolEntry)); 329 index * sizeof(ImportAnonymousSymbolEntry),
330 &entry, sizeof(ImportAnonymousSymbolEntry));
319 } 331 }
320 }; 332 };
321 ASSERT_CRO_STRUCT(ImportModuleEntry, 20); 333 ASSERT_CRO_STRUCT(ImportModuleEntry, 20);
322 334
323 enum class RelocationType : u8 { 335 enum class RelocationType : u8 {
324 Nothing = 0, 336 Nothing = 0,
325 AbsoluteAddress = 2, 337 AbsoluteAddress = 2,
326 RelativeAddress = 3, 338 RelativeAddress = 3,
327 ThumbBranch = 10, 339 ThumbBranch = 10,
328 ArmBranch = 28, 340 ArmBranch = 28,
329 ModifyArmBranch = 29, 341 ModifyArmBranch = 29,
330 AbsoluteAddress2 = 38, 342 AbsoluteAddress2 = 38,
331 AlignedRelativeAddress = 42, 343 AlignedRelativeAddress = 42,
332 }; 344 };
333 345
334 struct RelocationEntry { 346 struct RelocationEntry {
335 SegmentTag target_position; // to self's segment as an ExternalRelocationEntry; to static module segment as a StaticRelocationEntry 347 SegmentTag target_position; // to self's segment as an ExternalRelocationEntry; to static
348 // module segment as a StaticRelocationEntry
336 RelocationType type; 349 RelocationType type;
337 u8 is_batch_end; 350 u8 is_batch_end;
338 u8 is_batch_resolved; // set at a batch beginning if the batch is resolved 351 u8 is_batch_resolved; // set at a batch beginning if the batch is resolved
339 INSERT_PADDING_BYTES(1); 352 INSERT_PADDING_BYTES(1);
340 u32_le addend; 353 u32_le addend;
341 }; 354 };
@@ -366,8 +379,8 @@ private:
366 379
367 /// Identifies a special static anonymous symbol (no game is known using this). 380 /// Identifies a special static anonymous symbol (no game is known using this).
368 struct StaticAnonymousSymbolEntry { 381 struct StaticAnonymousSymbolEntry {
369 SegmentTag symbol_position; // to self's segment 382 SegmentTag symbol_position; // to self's segment
370 u32_le relocation_batch_offset; // pointing to a relocation batch in StaticRelocationTable 383 u32_le relocation_batch_offset; // pointing to a relocation batch in StaticRelocationTable
371 384
372 static constexpr HeaderField TABLE_OFFSET_FIELD = StaticAnonymousSymbolTableOffset; 385 static constexpr HeaderField TABLE_OFFSET_FIELD = StaticAnonymousSymbolTableOffset;
373 }; 386 };
@@ -446,12 +459,15 @@ private:
446 } 459 }
447 460
448 /** 461 /**
449 * A helper function iterating over all registered auto-link modules, including the static module. 462 * A helper function iterating over all registered auto-link modules, including the static
463 * module.
450 * @param crs_address the virtual address of the static module 464 * @param crs_address the virtual address of the static module
451 * @param func a function object to operate on a module. It accepts one parameter 465 * @param func a function object to operate on a module. It accepts one parameter
452 * CROHelper and returns ResultVal<bool>. It should return true to continue the iteration, 466 * CROHelper and returns ResultVal<bool>. It should return true to continue the
467 * iteration,
453 * false to stop the iteration, or an error code (which will also stop the iteration). 468 * false to stop the iteration, or an error code (which will also stop the iteration).
454 * @returns ResultCode indicating the result of the operation, RESULT_SUCCESS if all iteration success, 469 * @returns ResultCode indicating the result of the operation, RESULT_SUCCESS if all iteration
470 * success,
455 * otherwise error code of the last iteration. 471 * otherwise error code of the last iteration.
456 */ 472 */
457 template <typename FunctionObject> 473 template <typename FunctionObject>
@@ -477,8 +493,8 @@ private:
477 * Usually equals to target_address, but will be different for a target in .data segment 493 * Usually equals to target_address, but will be different for a target in .data segment
478 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. 494 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
479 */ 495 */
480 ResultCode ApplyRelocation(VAddr target_address, RelocationType relocation_type, 496 ResultCode ApplyRelocation(VAddr target_address, RelocationType relocation_type, u32 addend,
481 u32 addend, u32 symbol_address, u32 target_future_address); 497 u32 symbol_address, u32 target_future_address);
482 498
483 /** 499 /**
484 * Clears a relocation to zero 500 * Clears a relocation to zero
@@ -492,7 +508,8 @@ private:
492 * Applies or resets a batch of relocations 508 * Applies or resets a batch of relocations
493 * @param batch the virtual address of the first relocation in the batch 509 * @param batch the virtual address of the first relocation in the batch
494 * @param symbol_address the symbol address to be relocated with 510 * @param symbol_address the symbol address to be relocated with
495 * @param reset false to set the batch to resolved state, true to reset the batch to unresolved state 511 * @param reset false to set the batch to resolved state, true to reset the batch to unresolved
512 * state
496 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. 513 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
497 */ 514 */
498 ResultCode ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool reset = false); 515 ResultCode ApplyRelocationBatch(VAddr batch, u32 symbol_address, bool reset = false);
@@ -507,7 +524,8 @@ private:
507 /** 524 /**
508 * Rebases offsets in module header according to module address. 525 * Rebases offsets in module header according to module address.
509 * @param cro_size the size of the CRO file 526 * @param cro_size the size of the CRO file
510 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code. 527 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
528 * code.
511 */ 529 */
512 ResultCode RebaseHeader(u32 cro_size); 530 ResultCode RebaseHeader(u32 cro_size);
513 531
@@ -520,43 +538,49 @@ private:
520 * @param bss_segment_size the buffer size for .bss segment 538 * @param bss_segment_size the buffer size for .bss segment
521 * @returns ResultVal<VAddr> with the virtual address of .data segment in CRO. 539 * @returns ResultVal<VAddr> with the virtual address of .data segment in CRO.
522 */ 540 */
523 ResultVal<VAddr> RebaseSegmentTable(u32 cro_size, 541 ResultVal<VAddr> RebaseSegmentTable(u32 cro_size, VAddr data_segment_address,
524 VAddr data_segment_address, u32 data_segment_size, 542 u32 data_segment_size, VAddr bss_segment_address,
525 VAddr bss_segment_address, u32 bss_segment_size); 543 u32 bss_segment_size);
526 544
527 /** 545 /**
528 * Rebases offsets in exported named symbol table according to module address. 546 * Rebases offsets in exported named symbol table according to module address.
529 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code. 547 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
548 * code.
530 */ 549 */
531 ResultCode RebaseExportNamedSymbolTable(); 550 ResultCode RebaseExportNamedSymbolTable();
532 551
533 /** 552 /**
534 * Verifies indices in export tree table. 553 * Verifies indices in export tree table.
535 * @returns ResultCode RESULT_SUCCESS if all indices are verified as valid, otherwise error code. 554 * @returns ResultCode RESULT_SUCCESS if all indices are verified as valid, otherwise error
555 * code.
536 */ 556 */
537 ResultCode VerifyExportTreeTable() const; 557 ResultCode VerifyExportTreeTable() const;
538 558
539 /** 559 /**
540 * Rebases offsets in exported module table according to module address. 560 * Rebases offsets in exported module table according to module address.
541 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code. 561 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
562 * code.
542 */ 563 */
543 ResultCode RebaseImportModuleTable(); 564 ResultCode RebaseImportModuleTable();
544 565
545 /** 566 /**
546 * Rebases offsets in imported named symbol table according to module address. 567 * Rebases offsets in imported named symbol table according to module address.
547 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code. 568 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
569 * code.
548 */ 570 */
549 ResultCode RebaseImportNamedSymbolTable(); 571 ResultCode RebaseImportNamedSymbolTable();
550 572
551 /** 573 /**
552 * Rebases offsets in imported indexed symbol table according to module address. 574 * Rebases offsets in imported indexed symbol table according to module address.
553 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code. 575 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
576 * code.
554 */ 577 */
555 ResultCode RebaseImportIndexedSymbolTable(); 578 ResultCode RebaseImportIndexedSymbolTable();
556 579
557 /** 580 /**
558 * Rebases offsets in imported anonymous symbol table according to module address. 581 * Rebases offsets in imported anonymous symbol table according to module address.
559 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error code. 582 * @returns ResultCode RESULT_SUCCESS if all offsets are verified as valid, otherwise error
583 * code.
560 */ 584 */
561 ResultCode RebaseImportAnonymousSymbolTable(); 585 ResultCode RebaseImportAnonymousSymbolTable();
562 586
@@ -621,7 +645,8 @@ private:
621 void UnrebaseHeader(); 645 void UnrebaseHeader();
622 646
623 /** 647 /**
624 * Looks up all imported named symbols of this module in all registered auto-link modules, and resolves them if found. 648 * Looks up all imported named symbols of this module in all registered auto-link modules, and
649 * resolves them if found.
625 * @param crs_address the virtual address of the static module 650 * @param crs_address the virtual address of the static module
626 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. 651 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
627 */ 652 */
@@ -646,7 +671,8 @@ private:
646 ResultCode ResetImportAnonymousSymbol(); 671 ResultCode ResetImportAnonymousSymbol();
647 672
648 /** 673 /**
649 * Finds registered auto-link modules that this module imports, and resolves indexed and anonymous symbols exported by them. 674 * Finds registered auto-link modules that this module imports, and resolves indexed and
675 * anonymous symbols exported by them.
650 * @param crs_address the virtual address of the static module 676 * @param crs_address the virtual address of the static module
651 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. 677 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
652 */ 678 */
@@ -667,7 +693,8 @@ private:
667 ResultCode ResetExportNamedSymbol(CROHelper target); 693 ResultCode ResetExportNamedSymbol(CROHelper target);
668 694
669 /** 695 /**
670 * Resolves imported indexed and anonymous symbols in the target module which imports this module. 696 * Resolves imported indexed and anonymous symbols in the target module which imports this
697 * module.
671 * @param target the module to resolve. 698 * @param target the module to resolve.
672 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code. 699 * @returns ResultCode RESULT_SUCCESS on success, otherwise error code.
673 */ 700 */
diff --git a/src/core/hle/service/ldr_ro/ldr_ro.cpp b/src/core/hle/service/ldr_ro/ldr_ro.cpp
index 8ba73ea8d..ae5d3921f 100644
--- a/src/core/hle/service/ldr_ro/ldr_ro.cpp
+++ b/src/core/hle/service/ldr_ro/ldr_ro.cpp
@@ -18,24 +18,33 @@
18 18
19namespace LDR_RO { 19namespace LDR_RO {
20 20
21static const ResultCode ERROR_ALREADY_INITIALIZED = // 0xD9612FF9 21static const ResultCode ERROR_ALREADY_INITIALIZED = // 0xD9612FF9
22 ResultCode(ErrorDescription::AlreadyInitialized, ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Permanent); 22 ResultCode(ErrorDescription::AlreadyInitialized, ErrorModule::RO, ErrorSummary::Internal,
23static const ResultCode ERROR_NOT_INITIALIZED = // 0xD9612FF8 23 ErrorLevel::Permanent);
24 ResultCode(ErrorDescription::NotInitialized, ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Permanent); 24static const ResultCode ERROR_NOT_INITIALIZED = // 0xD9612FF8
25static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F 25 ResultCode(ErrorDescription::NotInitialized, ErrorModule::RO, ErrorSummary::Internal,
26 ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 26 ErrorLevel::Permanent);
27static const ResultCode ERROR_MISALIGNED_ADDRESS = // 0xD9012FF1 27static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F
28 ResultCode(ErrorDescription::MisalignedAddress, ErrorModule::RO, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 28 ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument,
29static const ResultCode ERROR_MISALIGNED_SIZE = // 0xD9012FF2 29 ErrorLevel::Usage);
30 ResultCode(ErrorDescription::MisalignedSize, ErrorModule::RO, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 30static const ResultCode ERROR_MISALIGNED_ADDRESS = // 0xD9012FF1
31static const ResultCode ERROR_ILLEGAL_ADDRESS = // 0xE1612C0F 31 ResultCode(ErrorDescription::MisalignedAddress, ErrorModule::RO, ErrorSummary::WrongArgument,
32 ResultCode(static_cast<ErrorDescription>(15), ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Usage); 32 ErrorLevel::Permanent);
33static const ResultCode ERROR_INVALID_MEMORY_STATE = // 0xD8A12C08 33static const ResultCode ERROR_MISALIGNED_SIZE = // 0xD9012FF2
34 ResultCode(static_cast<ErrorDescription>(8), ErrorModule::RO, ErrorSummary::InvalidState, ErrorLevel::Permanent); 34 ResultCode(ErrorDescription::MisalignedSize, ErrorModule::RO, ErrorSummary::WrongArgument,
35static const ResultCode ERROR_NOT_LOADED = // 0xD8A12C0D 35 ErrorLevel::Permanent);
36 ResultCode(static_cast<ErrorDescription>(13), ErrorModule::RO, ErrorSummary::InvalidState, ErrorLevel::Permanent); 36static const ResultCode ERROR_ILLEGAL_ADDRESS = // 0xE1612C0F
37static const ResultCode ERROR_INVALID_DESCRIPTOR = // 0xD9001830 37 ResultCode(static_cast<ErrorDescription>(15), ErrorModule::RO, ErrorSummary::Internal,
38 ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 38 ErrorLevel::Usage);
39static const ResultCode ERROR_INVALID_MEMORY_STATE = // 0xD8A12C08
40 ResultCode(static_cast<ErrorDescription>(8), ErrorModule::RO, ErrorSummary::InvalidState,
41 ErrorLevel::Permanent);
42static const ResultCode ERROR_NOT_LOADED = // 0xD8A12C0D
43 ResultCode(static_cast<ErrorDescription>(13), ErrorModule::RO, ErrorSummary::InvalidState,
44 ErrorLevel::Permanent);
45static const ResultCode ERROR_INVALID_DESCRIPTOR = // 0xD9001830
46 ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS,
47 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
39 48
40static MemorySynchronizer memory_synchronizer; 49static MemorySynchronizer memory_synchronizer;
41 50
@@ -44,10 +53,10 @@ static VAddr loaded_crs; ///< the virtual address of the static module
44 53
45static bool VerifyBufferState(VAddr buffer_ptr, u32 size) { 54static bool VerifyBufferState(VAddr buffer_ptr, u32 size) {
46 auto vma = Kernel::g_current_process->vm_manager.FindVMA(buffer_ptr); 55 auto vma = Kernel::g_current_process->vm_manager.FindVMA(buffer_ptr);
47 return vma != Kernel::g_current_process->vm_manager.vma_map.end() 56 return vma != Kernel::g_current_process->vm_manager.vma_map.end() &&
48 && vma->second.base + vma->second.size >= buffer_ptr + size 57 vma->second.base + vma->second.size >= buffer_ptr + size &&
49 && vma->second.permissions == Kernel::VMAPermission::ReadWrite 58 vma->second.permissions == Kernel::VMAPermission::ReadWrite &&
50 && vma->second.meminfo_state == Kernel::MemoryState::Private; 59 vma->second.meminfo_state == Kernel::MemoryState::Private;
51} 60}
52 61
53/** 62/**
@@ -66,13 +75,14 @@ static bool VerifyBufferState(VAddr buffer_ptr, u32 size) {
66static void Initialize(Service::Interface* self) { 75static void Initialize(Service::Interface* self) {
67 u32* cmd_buff = Kernel::GetCommandBuffer(); 76 u32* cmd_buff = Kernel::GetCommandBuffer();
68 VAddr crs_buffer_ptr = cmd_buff[1]; 77 VAddr crs_buffer_ptr = cmd_buff[1];
69 u32 crs_size = cmd_buff[2]; 78 u32 crs_size = cmd_buff[2];
70 VAddr crs_address = cmd_buff[3]; 79 VAddr crs_address = cmd_buff[3];
71 u32 descriptor = cmd_buff[4]; 80 u32 descriptor = cmd_buff[4];
72 u32 process = cmd_buff[5]; 81 u32 process = cmd_buff[5];
73 82
74 LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, crs_address=0x%08X, crs_size=0x%X, descriptor=0x%08X, process=0x%08X", 83 LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, crs_address=0x%08X, crs_size=0x%X, "
75 crs_buffer_ptr, crs_address, crs_size, descriptor, process); 84 "descriptor=0x%08X, process=0x%08X",
85 crs_buffer_ptr, crs_address, crs_size, descriptor, process);
76 86
77 if (descriptor != 0) { 87 if (descriptor != 0) {
78 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 88 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -119,7 +129,8 @@ static void Initialize(Service::Interface* self) {
119 return; 129 return;
120 } 130 }
121 131
122 if (crs_address < Memory::PROCESS_IMAGE_VADDR || crs_address + crs_size > Memory::PROCESS_IMAGE_VADDR_END) { 132 if (crs_address < Memory::PROCESS_IMAGE_VADDR ||
133 crs_address + crs_size > Memory::PROCESS_IMAGE_VADDR_END) {
123 LOG_ERROR(Service_LDR, "CRS mapping address is not in the process image region"); 134 LOG_ERROR(Service_LDR, "CRS mapping address is not in the process image region");
124 cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw; 135 cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw;
125 return; 136 return;
@@ -131,14 +142,17 @@ static void Initialize(Service::Interface* self) {
131 // TODO(wwylele): should be memory aliasing 142 // TODO(wwylele): should be memory aliasing
132 std::shared_ptr<std::vector<u8>> crs_mem = std::make_shared<std::vector<u8>>(crs_size); 143 std::shared_ptr<std::vector<u8>> crs_mem = std::make_shared<std::vector<u8>>(crs_size);
133 Memory::ReadBlock(crs_buffer_ptr, crs_mem->data(), crs_size); 144 Memory::ReadBlock(crs_buffer_ptr, crs_mem->data(), crs_size);
134 result = Kernel::g_current_process->vm_manager.MapMemoryBlock(crs_address, crs_mem, 0, crs_size, Kernel::MemoryState::Code).Code(); 145 result = Kernel::g_current_process->vm_manager
146 .MapMemoryBlock(crs_address, crs_mem, 0, crs_size, Kernel::MemoryState::Code)
147 .Code();
135 if (result.IsError()) { 148 if (result.IsError()) {
136 LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw); 149 LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw);
137 cmd_buff[1] = result.raw; 150 cmd_buff[1] = result.raw;
138 return; 151 return;
139 } 152 }
140 153
141 result = Kernel::g_current_process->vm_manager.ReprotectRange(crs_address, crs_size, Kernel::VMAPermission::Read); 154 result = Kernel::g_current_process->vm_manager.ReprotectRange(crs_address, crs_size,
155 Kernel::VMAPermission::Read);
142 if (result.IsError()) { 156 if (result.IsError()) {
143 LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); 157 LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw);
144 cmd_buff[1] = result.raw; 158 cmd_buff[1] = result.raw;
@@ -186,9 +200,9 @@ static void Initialize(Service::Interface* self) {
186static void LoadCRR(Service::Interface* self) { 200static void LoadCRR(Service::Interface* self) {
187 u32* cmd_buff = Kernel::GetCommandBuffer(); 201 u32* cmd_buff = Kernel::GetCommandBuffer();
188 u32 crr_buffer_ptr = cmd_buff[1]; 202 u32 crr_buffer_ptr = cmd_buff[1];
189 u32 crr_size = cmd_buff[2]; 203 u32 crr_size = cmd_buff[2];
190 u32 descriptor = cmd_buff[3]; 204 u32 descriptor = cmd_buff[3];
191 u32 process = cmd_buff[4]; 205 u32 process = cmd_buff[4];
192 206
193 if (descriptor != 0) { 207 if (descriptor != 0) {
194 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 208 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -200,7 +214,8 @@ static void LoadCRR(Service::Interface* self) {
200 cmd_buff[0] = IPC::MakeHeader(2, 1, 0); 214 cmd_buff[0] = IPC::MakeHeader(2, 1, 0);
201 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 215 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
202 216
203 LOG_WARNING(Service_LDR, "(STUBBED) called, crr_buffer_ptr=0x%08X, crr_size=0x%08X, descriptor=0x%08X, process=0x%08X", 217 LOG_WARNING(Service_LDR, "(STUBBED) called, crr_buffer_ptr=0x%08X, crr_size=0x%08X, "
218 "descriptor=0x%08X, process=0x%08X",
204 crr_buffer_ptr, crr_size, descriptor, process); 219 crr_buffer_ptr, crr_size, descriptor, process);
205} 220}
206 221
@@ -218,8 +233,8 @@ static void LoadCRR(Service::Interface* self) {
218static void UnloadCRR(Service::Interface* self) { 233static void UnloadCRR(Service::Interface* self) {
219 u32* cmd_buff = Kernel::GetCommandBuffer(); 234 u32* cmd_buff = Kernel::GetCommandBuffer();
220 u32 crr_buffer_ptr = cmd_buff[1]; 235 u32 crr_buffer_ptr = cmd_buff[1];
221 u32 descriptor = cmd_buff[2]; 236 u32 descriptor = cmd_buff[2];
222 u32 process = cmd_buff[3]; 237 u32 process = cmd_buff[3];
223 238
224 if (descriptor != 0) { 239 if (descriptor != 0) {
225 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 240 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -231,7 +246,8 @@ static void UnloadCRR(Service::Interface* self) {
231 cmd_buff[0] = IPC::MakeHeader(3, 1, 0); 246 cmd_buff[0] = IPC::MakeHeader(3, 1, 0);
232 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 247 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
233 248
234 LOG_WARNING(Service_LDR, "(STUBBED) called, crr_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X", 249 LOG_WARNING(Service_LDR,
250 "(STUBBED) called, crr_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X",
235 crr_buffer_ptr, descriptor, process); 251 crr_buffer_ptr, descriptor, process);
236} 252}
237 253
@@ -263,27 +279,28 @@ static void UnloadCRR(Service::Interface* self) {
263 */ 279 */
264static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { 280static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
265 u32* cmd_buff = Kernel::GetCommandBuffer(); 281 u32* cmd_buff = Kernel::GetCommandBuffer();
266 VAddr cro_buffer_ptr = cmd_buff[1]; 282 VAddr cro_buffer_ptr = cmd_buff[1];
267 VAddr cro_address = cmd_buff[2]; 283 VAddr cro_address = cmd_buff[2];
268 u32 cro_size = cmd_buff[3]; 284 u32 cro_size = cmd_buff[3];
269 VAddr data_segment_address = cmd_buff[4]; 285 VAddr data_segment_address = cmd_buff[4];
270 u32 zero = cmd_buff[5]; 286 u32 zero = cmd_buff[5];
271 u32 data_segment_size = cmd_buff[6]; 287 u32 data_segment_size = cmd_buff[6];
272 u32 bss_segment_address = cmd_buff[7]; 288 u32 bss_segment_address = cmd_buff[7];
273 u32 bss_segment_size = cmd_buff[8]; 289 u32 bss_segment_size = cmd_buff[8];
274 bool auto_link = (cmd_buff[9] & 0xFF) != 0; 290 bool auto_link = (cmd_buff[9] & 0xFF) != 0;
275 u32 fix_level = cmd_buff[10]; 291 u32 fix_level = cmd_buff[10];
276 VAddr crr_address = cmd_buff[11]; 292 VAddr crr_address = cmd_buff[11];
277 u32 descriptor = cmd_buff[12]; 293 u32 descriptor = cmd_buff[12];
278 u32 process = cmd_buff[13]; 294 u32 process = cmd_buff[13];
279 295
280 LOG_DEBUG(Service_LDR, "called (%s), cro_buffer_ptr=0x%08X, cro_address=0x%08X, cro_size=0x%X, " 296 LOG_DEBUG(Service_LDR,
281 "data_segment_address=0x%08X, zero=%d, data_segment_size=0x%X, bss_segment_address=0x%08X, bss_segment_size=0x%X, " 297 "called (%s), cro_buffer_ptr=0x%08X, cro_address=0x%08X, cro_size=0x%X, "
282 "auto_link=%s, fix_level=%d, crr_address=0x%08X, descriptor=0x%08X, process=0x%08X", 298 "data_segment_address=0x%08X, zero=%d, data_segment_size=0x%X, "
283 link_on_load_bug_fix ? "new" : "old", cro_buffer_ptr, cro_address, cro_size, 299 "bss_segment_address=0x%08X, bss_segment_size=0x%X, "
284 data_segment_address, zero, data_segment_size, bss_segment_address, bss_segment_size, 300 "auto_link=%s, fix_level=%d, crr_address=0x%08X, descriptor=0x%08X, process=0x%08X",
285 auto_link ? "true" : "false", fix_level, crr_address, descriptor, process 301 link_on_load_bug_fix ? "new" : "old", cro_buffer_ptr, cro_address, cro_size,
286 ); 302 data_segment_address, zero, data_segment_size, bss_segment_address, bss_segment_size,
303 auto_link ? "true" : "false", fix_level, crr_address, descriptor, process);
287 304
288 if (descriptor != 0) { 305 if (descriptor != 0) {
289 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 306 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -330,8 +347,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
330 return; 347 return;
331 } 348 }
332 349
333 if (cro_address < Memory::PROCESS_IMAGE_VADDR 350 if (cro_address < Memory::PROCESS_IMAGE_VADDR ||
334 || cro_address + cro_size > Memory::PROCESS_IMAGE_VADDR_END) { 351 cro_address + cro_size > Memory::PROCESS_IMAGE_VADDR_END) {
335 LOG_ERROR(Service_LDR, "CRO mapping address is not in the process image region"); 352 LOG_ERROR(Service_LDR, "CRO mapping address is not in the process image region");
336 cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw; 353 cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw;
337 return; 354 return;
@@ -339,7 +356,9 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
339 356
340 if (zero) { 357 if (zero) {
341 LOG_ERROR(Service_LDR, "Zero is not zero %d", zero); 358 LOG_ERROR(Service_LDR, "Zero is not zero %d", zero);
342 cmd_buff[1] = ResultCode(static_cast<ErrorDescription>(29), ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Usage).raw; 359 cmd_buff[1] = ResultCode(static_cast<ErrorDescription>(29), ErrorModule::RO,
360 ErrorSummary::Internal, ErrorLevel::Usage)
361 .raw;
343 return; 362 return;
344 } 363 }
345 364
@@ -349,14 +368,17 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
349 // TODO(wwylele): should be memory aliasing 368 // TODO(wwylele): should be memory aliasing
350 std::shared_ptr<std::vector<u8>> cro_mem = std::make_shared<std::vector<u8>>(cro_size); 369 std::shared_ptr<std::vector<u8>> cro_mem = std::make_shared<std::vector<u8>>(cro_size);
351 Memory::ReadBlock(cro_buffer_ptr, cro_mem->data(), cro_size); 370 Memory::ReadBlock(cro_buffer_ptr, cro_mem->data(), cro_size);
352 result = Kernel::g_current_process->vm_manager.MapMemoryBlock(cro_address, cro_mem, 0, cro_size, Kernel::MemoryState::Code).Code(); 371 result = Kernel::g_current_process->vm_manager
372 .MapMemoryBlock(cro_address, cro_mem, 0, cro_size, Kernel::MemoryState::Code)
373 .Code();
353 if (result.IsError()) { 374 if (result.IsError()) {
354 LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw); 375 LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw);
355 cmd_buff[1] = result.raw; 376 cmd_buff[1] = result.raw;
356 return; 377 return;
357 } 378 }
358 379
359 result = Kernel::g_current_process->vm_manager.ReprotectRange(cro_address, cro_size, Kernel::VMAPermission::Read); 380 result = Kernel::g_current_process->vm_manager.ReprotectRange(cro_address, cro_size,
381 Kernel::VMAPermission::Read);
360 if (result.IsError()) { 382 if (result.IsError()) {
361 LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); 383 LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw);
362 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); 384 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size);
@@ -384,7 +406,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
384 return; 406 return;
385 } 407 }
386 408
387 result = cro.Rebase(loaded_crs, cro_size, data_segment_address, data_segment_size, bss_segment_address, bss_segment_size, false); 409 result = cro.Rebase(loaded_crs, cro_size, data_segment_address, data_segment_size,
410 bss_segment_address, bss_segment_size, false);
388 if (result.IsError()) { 411 if (result.IsError()) {
389 LOG_ERROR(Service_LDR, "Error rebasing CRO %08X", result.raw); 412 LOG_ERROR(Service_LDR, "Error rebasing CRO %08X", result.raw);
390 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); 413 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size);
@@ -409,7 +432,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
409 // TODO(wwylele): verify the behaviour when buffer_ptr == address 432 // TODO(wwylele): verify the behaviour when buffer_ptr == address
410 if (cro_buffer_ptr != cro_address) { 433 if (cro_buffer_ptr != cro_address) {
411 if (fix_size != cro_size) { 434 if (fix_size != cro_size) {
412 result = Kernel::g_current_process->vm_manager.UnmapRange(cro_address + fix_size, cro_size - fix_size); 435 result = Kernel::g_current_process->vm_manager.UnmapRange(cro_address + fix_size,
436 cro_size - fix_size);
413 if (result.IsError()) { 437 if (result.IsError()) {
414 LOG_ERROR(Service_LDR, "Error unmapping memory block %08X", result.raw); 438 LOG_ERROR(Service_LDR, "Error unmapping memory block %08X", result.raw);
415 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); 439 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size);
@@ -426,7 +450,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
426 u32 exe_size; 450 u32 exe_size;
427 std::tie(exe_begin, exe_size) = cro.GetExecutablePages(); 451 std::tie(exe_begin, exe_size) = cro.GetExecutablePages();
428 if (exe_begin) { 452 if (exe_begin) {
429 result = Kernel::g_current_process->vm_manager.ReprotectRange(exe_begin, exe_size, Kernel::VMAPermission::ReadExecute); 453 result = Kernel::g_current_process->vm_manager.ReprotectRange(
454 exe_begin, exe_size, Kernel::VMAPermission::ReadExecute);
430 if (result.IsError()) { 455 if (result.IsError()) {
431 LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); 456 LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw);
432 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, fix_size); 457 Kernel::g_current_process->vm_manager.UnmapRange(cro_address, fix_size);
@@ -437,8 +462,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) {
437 462
438 Core::g_app_core->ClearInstructionCache(); 463 Core::g_app_core->ClearInstructionCache();
439 464
440 LOG_INFO(Service_LDR, "CRO \"%s\" loaded at 0x%08X, fixed_end=0x%08X", 465 LOG_INFO(Service_LDR, "CRO \"%s\" loaded at 0x%08X, fixed_end=0x%08X", cro.ModuleName().data(),
441 cro.ModuleName().data(), cro_address, cro_address+fix_size); 466 cro_address, cro_address + fix_size);
442 467
443 cmd_buff[1] = RESULT_SUCCESS.raw; 468 cmd_buff[1] = RESULT_SUCCESS.raw;
444 cmd_buff[2] = fix_size; 469 cmd_buff[2] = fix_size;
@@ -464,14 +489,15 @@ static void LoadCRO(Service::Interface* self) {
464 */ 489 */
465static void UnloadCRO(Service::Interface* self) { 490static void UnloadCRO(Service::Interface* self) {
466 u32* cmd_buff = Kernel::GetCommandBuffer(); 491 u32* cmd_buff = Kernel::GetCommandBuffer();
467 VAddr cro_address = cmd_buff[1]; 492 VAddr cro_address = cmd_buff[1];
468 u32 zero = cmd_buff[2]; 493 u32 zero = cmd_buff[2];
469 VAddr cro_buffer_ptr = cmd_buff[3]; 494 VAddr cro_buffer_ptr = cmd_buff[3];
470 u32 descriptor = cmd_buff[4]; 495 u32 descriptor = cmd_buff[4];
471 u32 process = cmd_buff[5]; 496 u32 process = cmd_buff[5];
472 497
473 LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, zero=%d, cro_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X", 498 LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, zero=%d, cro_buffer_ptr=0x%08X, "
474 cro_address, zero, cro_buffer_ptr, descriptor, process); 499 "descriptor=0x%08X, process=0x%08X",
500 cro_address, zero, cro_buffer_ptr, descriptor, process);
475 501
476 if (descriptor != 0) { 502 if (descriptor != 0) {
477 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 503 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -558,11 +584,11 @@ static void UnloadCRO(Service::Interface* self) {
558static void LinkCRO(Service::Interface* self) { 584static void LinkCRO(Service::Interface* self) {
559 u32* cmd_buff = Kernel::GetCommandBuffer(); 585 u32* cmd_buff = Kernel::GetCommandBuffer();
560 VAddr cro_address = cmd_buff[1]; 586 VAddr cro_address = cmd_buff[1];
561 u32 descriptor = cmd_buff[2]; 587 u32 descriptor = cmd_buff[2];
562 u32 process = cmd_buff[3]; 588 u32 process = cmd_buff[3];
563 589
564 LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X", 590 LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X",
565 cro_address, descriptor, process); 591 cro_address, descriptor, process);
566 592
567 if (descriptor != 0) { 593 if (descriptor != 0) {
568 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 594 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -620,11 +646,11 @@ static void LinkCRO(Service::Interface* self) {
620static void UnlinkCRO(Service::Interface* self) { 646static void UnlinkCRO(Service::Interface* self) {
621 u32* cmd_buff = Kernel::GetCommandBuffer(); 647 u32* cmd_buff = Kernel::GetCommandBuffer();
622 VAddr cro_address = cmd_buff[1]; 648 VAddr cro_address = cmd_buff[1];
623 u32 descriptor = cmd_buff[2]; 649 u32 descriptor = cmd_buff[2];
624 u32 process = cmd_buff[3]; 650 u32 process = cmd_buff[3];
625 651
626 LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X", 652 LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X",
627 cro_address, descriptor, process); 653 cro_address, descriptor, process);
628 654
629 if (descriptor != 0) { 655 if (descriptor != 0) {
630 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 656 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -682,11 +708,11 @@ static void UnlinkCRO(Service::Interface* self) {
682static void Shutdown(Service::Interface* self) { 708static void Shutdown(Service::Interface* self) {
683 u32* cmd_buff = Kernel::GetCommandBuffer(); 709 u32* cmd_buff = Kernel::GetCommandBuffer();
684 VAddr crs_buffer_ptr = cmd_buff[1]; 710 VAddr crs_buffer_ptr = cmd_buff[1];
685 u32 descriptor = cmd_buff[2]; 711 u32 descriptor = cmd_buff[2];
686 u32 process = cmd_buff[3]; 712 u32 process = cmd_buff[3];
687 713
688 LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X", 714 LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X",
689 crs_buffer_ptr, descriptor, process); 715 crs_buffer_ptr, descriptor, process);
690 716
691 if (descriptor != 0) { 717 if (descriptor != 0) {
692 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); 718 LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor);
@@ -724,15 +750,11 @@ static void Shutdown(Service::Interface* self) {
724} 750}
725 751
726const Interface::FunctionInfo FunctionTable[] = { 752const Interface::FunctionInfo FunctionTable[] = {
727 {0x000100C2, Initialize, "Initialize"}, 753 {0x000100C2, Initialize, "Initialize"}, {0x00020082, LoadCRR, "LoadCRR"},
728 {0x00020082, LoadCRR, "LoadCRR"}, 754 {0x00030042, UnloadCRR, "UnloadCRR"}, {0x000402C2, LoadCRO<false>, "LoadCRO"},
729 {0x00030042, UnloadCRR, "UnloadCRR"}, 755 {0x000500C2, UnloadCRO, "UnloadCRO"}, {0x00060042, LinkCRO, "LinkCRO"},
730 {0x000402C2, LoadCRO<false>, "LoadCRO"}, 756 {0x00070042, UnlinkCRO, "UnlinkCRO"}, {0x00080042, Shutdown, "Shutdown"},
731 {0x000500C2, UnloadCRO, "UnloadCRO"}, 757 {0x000902C2, LoadCRO<true>, "LoadCRO_New"},
732 {0x00060042, LinkCRO, "LinkCRO"},
733 {0x00070042, UnlinkCRO, "UnlinkCRO"},
734 {0x00080042, Shutdown, "Shutdown"},
735 {0x000902C2, LoadCRO<true>, "LoadCRO_New"},
736}; 758};
737 759
738//////////////////////////////////////////////////////////////////////////////////////////////////// 760////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/ldr_ro/memory_synchronizer.cpp b/src/core/hle/service/ldr_ro/memory_synchronizer.cpp
index 4402876e6..aed6d3365 100644
--- a/src/core/hle/service/ldr_ro/memory_synchronizer.cpp
+++ b/src/core/hle/service/ldr_ro/memory_synchronizer.cpp
@@ -14,9 +14,8 @@
14namespace LDR_RO { 14namespace LDR_RO {
15 15
16auto MemorySynchronizer::FindMemoryBlock(VAddr mapping, VAddr original) { 16auto MemorySynchronizer::FindMemoryBlock(VAddr mapping, VAddr original) {
17 auto block = std::find_if(memory_blocks.begin(), memory_blocks.end(), [=](MemoryBlock& b){ 17 auto block = std::find_if(memory_blocks.begin(), memory_blocks.end(),
18 return b.original == original; 18 [=](MemoryBlock& b) { return b.original == original; });
19 });
20 ASSERT(block->mapping == mapping); 19 ASSERT(block->mapping == mapping);
21 return block; 20 return block;
22} 21}
diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp
index f792bc9cd..edd1ea97b 100644
--- a/src/core/hle/service/mic_u.cpp
+++ b/src/core/hle/service/mic_u.cpp
@@ -10,22 +10,22 @@
10namespace MIC_U { 10namespace MIC_U {
11 11
12const Interface::FunctionInfo FunctionTable[] = { 12const Interface::FunctionInfo FunctionTable[] = {
13 {0x00010042, nullptr, "MapSharedMem"}, 13 {0x00010042, nullptr, "MapSharedMem"},
14 {0x00020000, nullptr, "UnmapSharedMem"}, 14 {0x00020000, nullptr, "UnmapSharedMem"},
15 {0x00030140, nullptr, "Initialize"}, 15 {0x00030140, nullptr, "Initialize"},
16 {0x00040040, nullptr, "AdjustSampling"}, 16 {0x00040040, nullptr, "AdjustSampling"},
17 {0x00050000, nullptr, "StopSampling"}, 17 {0x00050000, nullptr, "StopSampling"},
18 {0x00060000, nullptr, "IsSampling"}, 18 {0x00060000, nullptr, "IsSampling"},
19 {0x00070000, nullptr, "GetEventHandle"}, 19 {0x00070000, nullptr, "GetEventHandle"},
20 {0x00080040, nullptr, "SetGain"}, 20 {0x00080040, nullptr, "SetGain"},
21 {0x00090000, nullptr, "GetGain"}, 21 {0x00090000, nullptr, "GetGain"},
22 {0x000A0040, nullptr, "SetPower"}, 22 {0x000A0040, nullptr, "SetPower"},
23 {0x000B0000, nullptr, "GetPower"}, 23 {0x000B0000, nullptr, "GetPower"},
24 {0x000C0042, nullptr, "size"}, 24 {0x000C0042, nullptr, "size"},
25 {0x000D0040, nullptr, "SetClamp"}, 25 {0x000D0040, nullptr, "SetClamp"},
26 {0x000E0000, nullptr, "GetClamp"}, 26 {0x000E0000, nullptr, "GetClamp"},
27 {0x000F0040, nullptr, "SetAllowShellClosed"}, 27 {0x000F0040, nullptr, "SetAllowShellClosed"},
28 {0x00100040, nullptr, "unknown_input2"}, 28 {0x00100040, nullptr, "unknown_input2"},
29}; 29};
30 30
31//////////////////////////////////////////////////////////////////////////////////////////////////// 31////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/ndm/ndm.cpp b/src/core/hle/service/ndm/ndm.cpp
index bc9c3413d..9f1536aef 100644
--- a/src/core/hle/service/ndm/ndm.cpp
+++ b/src/core/hle/service/ndm/ndm.cpp
@@ -2,23 +2,21 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/hle/service/ndm/ndm.h"
5#include "common/common_types.h" 6#include "common/common_types.h"
6#include "common/logging/log.h" 7#include "common/logging/log.h"
7#include "core/hle/service/service.h"
8#include "core/hle/service/ndm/ndm.h"
9#include "core/hle/service/ndm/ndm_u.h" 8#include "core/hle/service/ndm/ndm_u.h"
9#include "core/hle/service/service.h"
10 10
11namespace Service { 11namespace Service {
12namespace NDM { 12namespace NDM {
13 13
14enum : u32 { 14enum : u32 { DEFAULT_RETRY_INTERVAL = 10, DEFAULT_SCAN_INTERVAL = 30 };
15 DEFAULT_RETRY_INTERVAL = 10,
16 DEFAULT_SCAN_INTERVAL = 30
17};
18 15
19static DaemonMask daemon_bit_mask = DaemonMask::Default; 16static DaemonMask daemon_bit_mask = DaemonMask::Default;
20static DaemonMask default_daemon_bit_mask = DaemonMask::Default; 17static DaemonMask default_daemon_bit_mask = DaemonMask::Default;
21static std::array<DaemonStatus, 4> daemon_status = { DaemonStatus::Idle, DaemonStatus::Idle, DaemonStatus::Idle, DaemonStatus::Idle }; 18static std::array<DaemonStatus, 4> daemon_status = {DaemonStatus::Idle, DaemonStatus::Idle,
19 DaemonStatus::Idle, DaemonStatus::Idle};
22static ExclusiveState exclusive_state = ExclusiveState::None; 20static ExclusiveState exclusive_state = ExclusiveState::None;
23static u32 scan_interval = DEFAULT_SCAN_INTERVAL; 21static u32 scan_interval = DEFAULT_SCAN_INTERVAL;
24static u32 retry_interval = DEFAULT_RETRY_INTERVAL; 22static u32 retry_interval = DEFAULT_RETRY_INTERVAL;
@@ -72,7 +70,8 @@ void UnlockState(Service::Interface* self) {
72void SuspendDaemons(Service::Interface* self) { 70void SuspendDaemons(Service::Interface* self) {
73 u32* cmd_buff = Kernel::GetCommandBuffer(); 71 u32* cmd_buff = Kernel::GetCommandBuffer();
74 u32 bit_mask = cmd_buff[1] & 0xF; 72 u32 bit_mask = cmd_buff[1] & 0xF;
75 daemon_bit_mask = static_cast<DaemonMask>(static_cast<u32>(default_daemon_bit_mask) & ~bit_mask); 73 daemon_bit_mask =
74 static_cast<DaemonMask>(static_cast<u32>(default_daemon_bit_mask) & ~bit_mask);
76 for (size_t index = 0; index < daemon_status.size(); ++index) { 75 for (size_t index = 0; index < daemon_status.size(); ++index) {
77 if (bit_mask & (1 << index)) { 76 if (bit_mask & (1 << index)) {
78 daemon_status[index] = DaemonStatus::Suspended; 77 daemon_status[index] = DaemonStatus::Suspended;
@@ -229,8 +228,7 @@ void Init() {
229} 228}
230 229
231void Shutdown() { 230void Shutdown() {
232
233} 231}
234 232
235}// namespace NDM 233} // namespace NDM
236}// namespace Service 234} // namespace Service
diff --git a/src/core/hle/service/ndm/ndm.h b/src/core/hle/service/ndm/ndm.h
index 5c2b968dc..fb574541d 100644
--- a/src/core/hle/service/ndm/ndm.h
+++ b/src/core/hle/service/ndm/ndm.h
@@ -12,36 +12,26 @@ class Interface;
12 12
13namespace NDM { 13namespace NDM {
14 14
15enum class Daemon : u32 { 15enum class Daemon : u32 { Cec = 0, Boss = 1, Nim = 2, Friend = 3 };
16 Cec = 0,
17 Boss = 1,
18 Nim = 2,
19 Friend = 3
20};
21 16
22enum class DaemonMask : u32 { 17enum class DaemonMask : u32 {
23 None = 0, 18 None = 0,
24 Cec = (1 << static_cast<u32>(Daemon::Cec)), 19 Cec = (1 << static_cast<u32>(Daemon::Cec)),
25 Boss = (1 << static_cast<u32>(Daemon::Boss)), 20 Boss = (1 << static_cast<u32>(Daemon::Boss)),
26 Nim = (1 << static_cast<u32>(Daemon::Nim)), 21 Nim = (1 << static_cast<u32>(Daemon::Nim)),
27 Friend = (1 << static_cast<u32>(Daemon::Friend)), 22 Friend = (1 << static_cast<u32>(Daemon::Friend)),
28 Default = Cec | Friend, 23 Default = Cec | Friend,
29 All = Cec | Boss | Nim | Friend 24 All = Cec | Boss | Nim | Friend
30}; 25};
31 26
32enum class DaemonStatus : u32 { 27enum class DaemonStatus : u32 { Busy = 0, Idle = 1, Suspending = 2, Suspended = 3 };
33 Busy = 0,
34 Idle = 1,
35 Suspending = 2,
36 Suspended = 3
37};
38 28
39enum class ExclusiveState : u32 { 29enum class ExclusiveState : u32 {
40 None = 0, 30 None = 0,
41 Infrastructure = 1, 31 Infrastructure = 1,
42 LocalCommunications = 2, 32 LocalCommunications = 2,
43 Streetpass = 3, 33 Streetpass = 3,
44 StreetpassData = 4, 34 StreetpassData = 4,
45}; 35};
46 36
47/** 37/**
@@ -205,7 +195,6 @@ void SetRetryInterval(Service::Interface* self);
205 */ 195 */
206void GetRetryInterval(Service::Interface* self); 196void GetRetryInterval(Service::Interface* self);
207 197
208
209/** 198/**
210 * NDM::OverrideDefaultDaemons service function 199 * NDM::OverrideDefaultDaemons service function
211 * Inputs: 200 * Inputs:
@@ -233,7 +222,8 @@ void ResetDefaultDaemons(Service::Interface* self);
233 * 1 : Result, 0 on success, otherwise error code 222 * 1 : Result, 0 on success, otherwise error code
234 * 2 : Daemon bit mask 223 * 2 : Daemon bit mask
235 * Note: 224 * Note:
236 * Gets the current default daemon bit mask. The default value is (DAEMONMASK_CEC | DAEMONMASK_FRIENDS) 225 * Gets the current default daemon bit mask. The default value is (DAEMONMASK_CEC |
226 * DAEMONMASK_FRIENDS)
237 */ 227 */
238void GetDefaultDaemons(Service::Interface* self); 228void GetDefaultDaemons(Service::Interface* self);
239 229
@@ -252,5 +242,5 @@ void Init();
252/// Shutdown NDM service 242/// Shutdown NDM service
253void Shutdown(); 243void Shutdown();
254 244
255}// namespace NDM 245} // namespace NDM
256}// namespace Service 246} // namespace Service
diff --git a/src/core/hle/service/ndm/ndm_u.cpp b/src/core/hle/service/ndm/ndm_u.cpp
index 3ff0744ee..f5c7a341a 100644
--- a/src/core/hle/service/ndm/ndm_u.cpp
+++ b/src/core/hle/service/ndm/ndm_u.cpp
@@ -9,28 +9,28 @@ namespace Service {
9namespace NDM { 9namespace NDM {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010042, EnterExclusiveState, "EnterExclusiveState"}, 12 {0x00010042, EnterExclusiveState, "EnterExclusiveState"},
13 {0x00020002, LeaveExclusiveState, "LeaveExclusiveState"}, 13 {0x00020002, LeaveExclusiveState, "LeaveExclusiveState"},
14 {0x00030000, QueryExclusiveMode, "QueryExclusiveMode"}, 14 {0x00030000, QueryExclusiveMode, "QueryExclusiveMode"},
15 {0x00040002, LockState, "LockState"}, 15 {0x00040002, LockState, "LockState"},
16 {0x00050002, UnlockState, "UnlockState"}, 16 {0x00050002, UnlockState, "UnlockState"},
17 {0x00060040, SuspendDaemons, "SuspendDaemons"}, 17 {0x00060040, SuspendDaemons, "SuspendDaemons"},
18 {0x00070040, ResumeDaemons, "ResumeDaemons"}, 18 {0x00070040, ResumeDaemons, "ResumeDaemons"},
19 {0x00080040, SuspendScheduler, "SuspendScheduler"}, 19 {0x00080040, SuspendScheduler, "SuspendScheduler"},
20 {0x00090000, ResumeScheduler, "ResumeScheduler"}, 20 {0x00090000, ResumeScheduler, "ResumeScheduler"},
21 {0x000A0000, nullptr, "GetCurrentState"}, 21 {0x000A0000, nullptr, "GetCurrentState"},
22 {0x000B0000, nullptr, "GetTargetState"}, 22 {0x000B0000, nullptr, "GetTargetState"},
23 {0x000C0000, nullptr, "<Stubbed>"}, 23 {0x000C0000, nullptr, "<Stubbed>"},
24 {0x000D0040, QueryStatus, "QueryStatus"}, 24 {0x000D0040, QueryStatus, "QueryStatus"},
25 {0x000E0040, GetDaemonDisableCount, "GetDaemonDisableCount"}, 25 {0x000E0040, GetDaemonDisableCount, "GetDaemonDisableCount"},
26 {0x000F0000, GetSchedulerDisableCount,"GetSchedulerDisableCount"}, 26 {0x000F0000, GetSchedulerDisableCount, "GetSchedulerDisableCount"},
27 {0x00100040, SetScanInterval, "SetScanInterval"}, 27 {0x00100040, SetScanInterval, "SetScanInterval"},
28 {0x00110000, GetScanInterval, "GetScanInterval"}, 28 {0x00110000, GetScanInterval, "GetScanInterval"},
29 {0x00120040, SetRetryInterval, "SetRetryInterval"}, 29 {0x00120040, SetRetryInterval, "SetRetryInterval"},
30 {0x00130000, GetRetryInterval, "GetRetryInterval"}, 30 {0x00130000, GetRetryInterval, "GetRetryInterval"},
31 {0x00140040, OverrideDefaultDaemons, "OverrideDefaultDaemons"}, 31 {0x00140040, OverrideDefaultDaemons, "OverrideDefaultDaemons"},
32 {0x00150000, ResetDefaultDaemons, "ResetDefaultDaemons"}, 32 {0x00150000, ResetDefaultDaemons, "ResetDefaultDaemons"},
33 {0x00160000, GetDefaultDaemons, "GetDefaultDaemons"}, 33 {0x00160000, GetDefaultDaemons, "GetDefaultDaemons"},
34 {0x00170000, ClearHalfAwakeMacFilter, "ClearHalfAwakeMacFilter"}, 34 {0x00170000, ClearHalfAwakeMacFilter, "ClearHalfAwakeMacFilter"},
35}; 35};
36 36
diff --git a/src/core/hle/service/news/news.cpp b/src/core/hle/service/news/news.cpp
index b3f500694..983e0777c 100644
--- a/src/core/hle/service/news/news.cpp
+++ b/src/core/hle/service/news/news.cpp
@@ -4,10 +4,10 @@
4 4
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6 6
7#include "core/hle/service/service.h"
8#include "core/hle/service/news/news.h" 7#include "core/hle/service/news/news.h"
9#include "core/hle/service/news/news_s.h" 8#include "core/hle/service/news/news_s.h"
10#include "core/hle/service/news/news_u.h" 9#include "core/hle/service/news/news_u.h"
10#include "core/hle/service/service.h"
11 11
12namespace Service { 12namespace Service {
13namespace NEWS { 13namespace NEWS {
diff --git a/src/core/hle/service/news/news_s.cpp b/src/core/hle/service/news/news_s.cpp
index 39b5a50f8..dda3d0f6a 100644
--- a/src/core/hle/service/news/news_s.cpp
+++ b/src/core/hle/service/news/news_s.cpp
@@ -9,19 +9,19 @@ namespace Service {
9namespace NEWS { 9namespace NEWS {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x000100C6, nullptr, "AddNotification"}, 12 {0x000100C6, nullptr, "AddNotification"},
13 {0x00050000, nullptr, "GetTotalNotifications"}, 13 {0x00050000, nullptr, "GetTotalNotifications"},
14 {0x00060042, nullptr, "SetNewsDBHeader"}, 14 {0x00060042, nullptr, "SetNewsDBHeader"},
15 {0x00070082, nullptr, "SetNotificationHeader"}, 15 {0x00070082, nullptr, "SetNotificationHeader"},
16 {0x00080082, nullptr, "SetNotificationMessage"}, 16 {0x00080082, nullptr, "SetNotificationMessage"},
17 {0x00090082, nullptr, "SetNotificationImage"}, 17 {0x00090082, nullptr, "SetNotificationImage"},
18 {0x000A0042, nullptr, "GetNewsDBHeader"}, 18 {0x000A0042, nullptr, "GetNewsDBHeader"},
19 {0x000B0082, nullptr, "GetNotificationHeader"}, 19 {0x000B0082, nullptr, "GetNotificationHeader"},
20 {0x000C0082, nullptr, "GetNotificationMessage"}, 20 {0x000C0082, nullptr, "GetNotificationMessage"},
21 {0x000D0082, nullptr, "GetNotificationImage"}, 21 {0x000D0082, nullptr, "GetNotificationImage"},
22 {0x000E0040, nullptr, "SetInfoLEDPattern"}, 22 {0x000E0040, nullptr, "SetInfoLEDPattern"},
23 {0x00120082, nullptr, "GetNotificationHeaderOther"}, 23 {0x00120082, nullptr, "GetNotificationHeaderOther"},
24 {0x00130000, nullptr, "WriteNewsDBSavedata"}, 24 {0x00130000, nullptr, "WriteNewsDBSavedata"},
25}; 25};
26 26
27NEWS_S_Interface::NEWS_S_Interface() { 27NEWS_S_Interface::NEWS_S_Interface() {
diff --git a/src/core/hle/service/news/news_u.cpp b/src/core/hle/service/news/news_u.cpp
index 6b75cc24e..a07e466de 100644
--- a/src/core/hle/service/news/news_u.cpp
+++ b/src/core/hle/service/news/news_u.cpp
@@ -8,7 +8,7 @@ namespace Service {
8namespace NEWS { 8namespace NEWS {
9 9
10const Interface::FunctionInfo FunctionTable[] = { 10const Interface::FunctionInfo FunctionTable[] = {
11 {0x000100C6, nullptr, "AddNotification"}, 11 {0x000100C6, nullptr, "AddNotification"},
12}; 12};
13 13
14NEWS_U_Interface::NEWS_U_Interface() { 14NEWS_U_Interface::NEWS_U_Interface() {
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp
index ed42464ce..f3c01d6e6 100644
--- a/src/core/hle/service/nim/nim.cpp
+++ b/src/core/hle/service/nim/nim.cpp
@@ -5,11 +5,11 @@
5#include "common/common_types.h" 5#include "common/common_types.h"
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7 7
8#include "core/hle/service/service.h"
9#include "core/hle/service/nim/nim.h" 8#include "core/hle/service/nim/nim.h"
10#include "core/hle/service/nim/nim_aoc.h" 9#include "core/hle/service/nim/nim_aoc.h"
11#include "core/hle/service/nim/nim_s.h" 10#include "core/hle/service/nim/nim_s.h"
12#include "core/hle/service/nim/nim_u.h" 11#include "core/hle/service/nim/nim_u.h"
12#include "core/hle/service/service.h"
13 13
14namespace Service { 14namespace Service {
15namespace NIM { 15namespace NIM {
diff --git a/src/core/hle/service/nim/nim_aoc.cpp b/src/core/hle/service/nim/nim_aoc.cpp
index 4a4818d57..2d0fb6fc4 100644
--- a/src/core/hle/service/nim/nim_aoc.cpp
+++ b/src/core/hle/service/nim/nim_aoc.cpp
@@ -8,14 +8,14 @@ namespace Service {
8namespace NIM { 8namespace NIM {
9 9
10const Interface::FunctionInfo FunctionTable[] = { 10const Interface::FunctionInfo FunctionTable[] = {
11 {0x00030042, nullptr, "SetApplicationId"}, 11 {0x00030042, nullptr, "SetApplicationId"},
12 {0x00040042, nullptr, "SetTin"}, 12 {0x00040042, nullptr, "SetTin"},
13 {0x000902D0, nullptr, "ListContentSetsEx"}, 13 {0x000902D0, nullptr, "ListContentSetsEx"},
14 {0x00180000, nullptr, "GetBalance"}, 14 {0x00180000, nullptr, "GetBalance"},
15 {0x001D0000, nullptr, "GetCustomerSupportCode"}, 15 {0x001D0000, nullptr, "GetCustomerSupportCode"},
16 {0x00210000, nullptr, "Initialize"}, 16 {0x00210000, nullptr, "Initialize"},
17 {0x00240282, nullptr, "CalculateContentsRequiredSize"}, 17 {0x00240282, nullptr, "CalculateContentsRequiredSize"},
18 {0x00250000, nullptr, "RefreshServerTime"}, 18 {0x00250000, nullptr, "RefreshServerTime"},
19}; 19};
20 20
21NIM_AOC_Interface::NIM_AOC_Interface() { 21NIM_AOC_Interface::NIM_AOC_Interface() {
diff --git a/src/core/hle/service/nim/nim_s.cpp b/src/core/hle/service/nim/nim_s.cpp
index dcaa0255a..e2ba693c9 100644
--- a/src/core/hle/service/nim/nim_s.cpp
+++ b/src/core/hle/service/nim/nim_s.cpp
@@ -8,10 +8,10 @@ namespace Service {
8namespace NIM { 8namespace NIM {
9 9
10const Interface::FunctionInfo FunctionTable[] = { 10const Interface::FunctionInfo FunctionTable[] = {
11 {0x000A0000, nullptr, "CheckSysupdateAvailableSOAP"}, 11 {0x000A0000, nullptr, "CheckSysupdateAvailableSOAP"},
12 {0x0016020A, nullptr, "ListTitles"}, 12 {0x0016020A, nullptr, "ListTitles"},
13 {0x002D0042, nullptr, "DownloadTickets"}, 13 {0x002D0042, nullptr, "DownloadTickets"},
14 {0x00420240, nullptr, "StartDownload"}, 14 {0x00420240, nullptr, "StartDownload"},
15}; 15};
16 16
17NIM_S_Interface::NIM_S_Interface() { 17NIM_S_Interface::NIM_S_Interface() {
@@ -20,4 +20,3 @@ NIM_S_Interface::NIM_S_Interface() {
20 20
21} // namespace NIM 21} // namespace NIM
22} // namespace Service 22} // namespace Service
23
diff --git a/src/core/hle/service/nim/nim_u.cpp b/src/core/hle/service/nim/nim_u.cpp
index eae45ebc0..7e07d02e8 100644
--- a/src/core/hle/service/nim/nim_u.cpp
+++ b/src/core/hle/service/nim/nim_u.cpp
@@ -9,12 +9,12 @@ namespace Service {
9namespace NIM { 9namespace NIM {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010000, nullptr, "StartSysUpdate"}, 12 {0x00010000, nullptr, "StartSysUpdate"},
13 {0x00020000, nullptr, "GetUpdateDownloadProgress"}, 13 {0x00020000, nullptr, "GetUpdateDownloadProgress"},
14 {0x00040000, nullptr, "FinishTitlesInstall"}, 14 {0x00040000, nullptr, "FinishTitlesInstall"},
15 {0x00050000, nullptr, "CheckForSysUpdateEvent"}, 15 {0x00050000, nullptr, "CheckForSysUpdateEvent"},
16 {0x00090000, CheckSysUpdateAvailable, "CheckSysUpdateAvailable"}, 16 {0x00090000, CheckSysUpdateAvailable, "CheckSysUpdateAvailable"},
17 {0x000A0000, nullptr, "GetState"}, 17 {0x000A0000, nullptr, "GetState"},
18}; 18};
19 19
20NIM_U_Interface::NIM_U_Interface() { 20NIM_U_Interface::NIM_U_Interface() {
@@ -23,4 +23,3 @@ NIM_U_Interface::NIM_U_Interface() {
23 23
24} // namespace NIM 24} // namespace NIM
25} // namespace Service 25} // namespace Service
26
diff --git a/src/core/hle/service/ns_s.cpp b/src/core/hle/service/ns_s.cpp
index 072918d62..6693f7c08 100644
--- a/src/core/hle/service/ns_s.cpp
+++ b/src/core/hle/service/ns_s.cpp
@@ -10,21 +10,21 @@
10namespace NS_S { 10namespace NS_S {
11 11
12const Interface::FunctionInfo FunctionTable[] = { 12const Interface::FunctionInfo FunctionTable[] = {
13 {0x000100C0, nullptr, "LaunchFIRM"}, 13 {0x000100C0, nullptr, "LaunchFIRM"},
14 {0x000200C0, nullptr, "LaunchTitle"}, 14 {0x000200C0, nullptr, "LaunchTitle"},
15 {0x00030000, nullptr, "TerminateApplication"}, 15 {0x00030000, nullptr, "TerminateApplication"},
16 {0x00040040, nullptr, "TerminateProcess"}, 16 {0x00040040, nullptr, "TerminateProcess"},
17 {0x000500C0, nullptr, "LaunchApplicationFIRM"}, 17 {0x000500C0, nullptr, "LaunchApplicationFIRM"},
18 {0x00060042, nullptr, "SetFIRMParams4A0"}, 18 {0x00060042, nullptr, "SetFIRMParams4A0"},
19 {0x00070042, nullptr, "CardUpdateInitialize"}, 19 {0x00070042, nullptr, "CardUpdateInitialize"},
20 {0x00080000, nullptr, "CardUpdateShutdown"}, 20 {0x00080000, nullptr, "CardUpdateShutdown"},
21 {0x000D0140, nullptr, "SetTWLBannerHMAC"}, 21 {0x000D0140, nullptr, "SetTWLBannerHMAC"},
22 {0x000E0000, nullptr, "ShutdownAsync"}, 22 {0x000E0000, nullptr, "ShutdownAsync"},
23 {0x00100180, nullptr, "RebootSystem"}, 23 {0x00100180, nullptr, "RebootSystem"},
24 {0x00110100, nullptr, "TerminateTitle"}, 24 {0x00110100, nullptr, "TerminateTitle"},
25 {0x001200C0, nullptr, "SetApplicationCpuTimeLimit"}, 25 {0x001200C0, nullptr, "SetApplicationCpuTimeLimit"},
26 {0x00150140, nullptr, "LaunchApplication"}, 26 {0x00150140, nullptr, "LaunchApplication"},
27 {0x00160000, nullptr, "RebootSystemClean"}, 27 {0x00160000, nullptr, "RebootSystemClean"},
28}; 28};
29 29
30//////////////////////////////////////////////////////////////////////////////////////////////////// 30////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/nwm_uds.cpp b/src/core/hle/service/nwm_uds.cpp
index ae4640409..ed417fa9a 100644
--- a/src/core/hle/service/nwm_uds.cpp
+++ b/src/core/hle/service/nwm_uds.cpp
@@ -54,22 +54,23 @@ static void Shutdown(Service::Interface* self) {
54static void RecvBeaconBroadcastData(Service::Interface* self) { 54static void RecvBeaconBroadcastData(Service::Interface* self) {
55 u32* cmd_buff = Kernel::GetCommandBuffer(); 55 u32* cmd_buff = Kernel::GetCommandBuffer();
56 u32 out_buffer_size = cmd_buff[1]; 56 u32 out_buffer_size = cmd_buff[1];
57 u32 unk1 = cmd_buff[2]; 57 u32 unk1 = cmd_buff[2];
58 u32 unk2 = cmd_buff[3]; 58 u32 unk2 = cmd_buff[3];
59 u32 mac_address = cmd_buff[4]; 59 u32 mac_address = cmd_buff[4];
60 60
61 u32 unk3 = cmd_buff[6]; 61 u32 unk3 = cmd_buff[6];
62 62
63 u32 wlan_comm_id = cmd_buff[15]; 63 u32 wlan_comm_id = cmd_buff[15];
64 u32 ctr_gen_id = cmd_buff[16]; 64 u32 ctr_gen_id = cmd_buff[16];
65 u32 value = cmd_buff[17]; 65 u32 value = cmd_buff[17];
66 u32 input_handle = cmd_buff[18]; 66 u32 input_handle = cmd_buff[18];
67 u32 new_buffer_size = cmd_buff[19]; 67 u32 new_buffer_size = cmd_buff[19];
68 u32 out_buffer_ptr = cmd_buff[20]; 68 u32 out_buffer_ptr = cmd_buff[20];
69 69
70 cmd_buff[1] = RESULT_SUCCESS.raw; 70 cmd_buff[1] = RESULT_SUCCESS.raw;
71 71
72 LOG_WARNING(Service_NWM, "(STUBBED) called out_buffer_size=0x%08X, unk1=0x%08X, unk2=0x%08X," 72 LOG_WARNING(Service_NWM,
73 "(STUBBED) called out_buffer_size=0x%08X, unk1=0x%08X, unk2=0x%08X,"
73 "mac_address=0x%08X, unk3=0x%08X, wlan_comm_id=0x%08X, ctr_gen_id=0x%08X," 74 "mac_address=0x%08X, unk3=0x%08X, wlan_comm_id=0x%08X, ctr_gen_id=0x%08X,"
74 "value=%u, input_handle=0x%08X, new_buffer_size=0x%08X, out_buffer_ptr=0x%08X", 75 "value=%u, input_handle=0x%08X, new_buffer_size=0x%08X, out_buffer_ptr=0x%08X",
75 out_buffer_size, unk1, unk2, mac_address, unk3, wlan_comm_id, ctr_gen_id, value, 76 out_buffer_size, unk1, unk2, mac_address, unk3, wlan_comm_id, ctr_gen_id, value,
@@ -92,46 +93,47 @@ static void RecvBeaconBroadcastData(Service::Interface* self) {
92 */ 93 */
93static void Initialize(Service::Interface* self) { 94static void Initialize(Service::Interface* self) {
94 u32* cmd_buff = Kernel::GetCommandBuffer(); 95 u32* cmd_buff = Kernel::GetCommandBuffer();
95 u32 unk1 = cmd_buff[1]; 96 u32 unk1 = cmd_buff[1];
96 u32 unk2 = cmd_buff[12]; 97 u32 unk2 = cmd_buff[12];
97 u32 value = cmd_buff[13]; 98 u32 value = cmd_buff[13];
98 u32 handle = cmd_buff[14]; 99 u32 handle = cmd_buff[14];
99 100
100 cmd_buff[1] = RESULT_SUCCESS.raw; 101 cmd_buff[1] = RESULT_SUCCESS.raw;
101 cmd_buff[2] = 0; 102 cmd_buff[2] = 0;
102 cmd_buff[3] = Kernel::g_handle_table.Create(handle_event).MoveFrom(); //TODO(purpasmart): Verify if this is a event handle 103 cmd_buff[3] = Kernel::g_handle_table.Create(handle_event)
104 .MoveFrom(); // TODO(purpasmart): Verify if this is a event handle
103 105
104 LOG_WARNING(Service_NWM, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, value=%u, handle=0x%08X", 106 LOG_WARNING(Service_NWM, "(STUBBED) called unk1=0x%08X, unk2=0x%08X, value=%u, handle=0x%08X",
105 unk1, unk2, value, handle); 107 unk1, unk2, value, handle);
106} 108}
107 109
108const Interface::FunctionInfo FunctionTable[] = { 110const Interface::FunctionInfo FunctionTable[] = {
109 {0x00020000, nullptr, "Scrap"}, 111 {0x00020000, nullptr, "Scrap"},
110 {0x00030000, Shutdown, "Shutdown"}, 112 {0x00030000, Shutdown, "Shutdown"},
111 {0x00040402, nullptr, "CreateNetwork"}, 113 {0x00040402, nullptr, "CreateNetwork"},
112 {0x00050040, nullptr, "EjectClient"}, 114 {0x00050040, nullptr, "EjectClient"},
113 {0x00060000, nullptr, "EjectSpectator"}, 115 {0x00060000, nullptr, "EjectSpectator"},
114 {0x00070080, nullptr, "UpdateNetworkAttribute"}, 116 {0x00070080, nullptr, "UpdateNetworkAttribute"},
115 {0x00080000, nullptr, "DestroyNetwork"}, 117 {0x00080000, nullptr, "DestroyNetwork"},
116 {0x000A0000, nullptr, "DisconnectNetwork"}, 118 {0x000A0000, nullptr, "DisconnectNetwork"},
117 {0x000B0000, nullptr, "GetConnectionStatus"}, 119 {0x000B0000, nullptr, "GetConnectionStatus"},
118 {0x000D0040, nullptr, "GetNodeInformation"}, 120 {0x000D0040, nullptr, "GetNodeInformation"},
119 {0x000F0404, RecvBeaconBroadcastData, "RecvBeaconBroadcastData"}, 121 {0x000F0404, RecvBeaconBroadcastData, "RecvBeaconBroadcastData"},
120 {0x00100042, nullptr, "SetBeaconAdditionalData"}, 122 {0x00100042, nullptr, "SetBeaconAdditionalData"},
121 {0x00110040, nullptr, "GetApplicationData"}, 123 {0x00110040, nullptr, "GetApplicationData"},
122 {0x00120100, nullptr, "Bind"}, 124 {0x00120100, nullptr, "Bind"},
123 {0x00130040, nullptr, "Unbind"}, 125 {0x00130040, nullptr, "Unbind"},
124 {0x001400C0, nullptr, "RecvBroadcastDataFrame"}, 126 {0x001400C0, nullptr, "RecvBroadcastDataFrame"},
125 {0x00150080, nullptr, "SetMaxSendDelay"}, 127 {0x00150080, nullptr, "SetMaxSendDelay"},
126 {0x00170182, nullptr, "SendTo"}, 128 {0x00170182, nullptr, "SendTo"},
127 {0x001A0000, nullptr, "GetChannel"}, 129 {0x001A0000, nullptr, "GetChannel"},
128 {0x001B0302, Initialize, "Initialize"}, 130 {0x001B0302, Initialize, "Initialize"},
129 {0x001D0044, nullptr, "BeginHostingNetwork"}, 131 {0x001D0044, nullptr, "BeginHostingNetwork"},
130 {0x001E0084, nullptr, "ConnectToNetwork"}, 132 {0x001E0084, nullptr, "ConnectToNetwork"},
131 {0x001F0006, nullptr, "DecryptBeaconData"}, 133 {0x001F0006, nullptr, "DecryptBeaconData"},
132 {0x00200040, nullptr, "Flush"}, 134 {0x00200040, nullptr, "Flush"},
133 {0x00210080, nullptr, "SetProbeResponseParam"}, 135 {0x00210080, nullptr, "SetProbeResponseParam"},
134 {0x00220402, nullptr, "ScanOnConnection"}, 136 {0x00220402, nullptr, "ScanOnConnection"},
135}; 137};
136 138
137//////////////////////////////////////////////////////////////////////////////////////////////////// 139////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/pm_app.cpp b/src/core/hle/service/pm_app.cpp
index 05d01bc48..7d91694f6 100644
--- a/src/core/hle/service/pm_app.cpp
+++ b/src/core/hle/service/pm_app.cpp
@@ -10,18 +10,18 @@
10namespace PM_APP { 10namespace PM_APP {
11 11
12const Interface::FunctionInfo FunctionTable[] = { 12const Interface::FunctionInfo FunctionTable[] = {
13 {0x00010140, nullptr, "LaunchTitle"}, 13 {0x00010140, nullptr, "LaunchTitle"},
14 {0x00020082, nullptr, "LaunchFIRMSetParams"}, 14 {0x00020082, nullptr, "LaunchFIRMSetParams"},
15 {0x00030080, nullptr, "TerminateProcesse"}, 15 {0x00030080, nullptr, "TerminateProcesse"},
16 {0x00040100, nullptr, "TerminateProcessTID"}, 16 {0x00040100, nullptr, "TerminateProcessTID"},
17 {0x000500C0, nullptr, "TerminateProcessTID_unknown"}, 17 {0x000500C0, nullptr, "TerminateProcessTID_unknown"},
18 {0x00070042, nullptr, "GetFIRMLaunchParams"}, 18 {0x00070042, nullptr, "GetFIRMLaunchParams"},
19 {0x00080100, nullptr, "GetTitleExheaderFlags"}, 19 {0x00080100, nullptr, "GetTitleExheaderFlags"},
20 {0x00090042, nullptr, "SetFIRMLaunchParams"}, 20 {0x00090042, nullptr, "SetFIRMLaunchParams"},
21 {0x000A0140, nullptr, "SetResourceLimit"}, 21 {0x000A0140, nullptr, "SetResourceLimit"},
22 {0x000B0140, nullptr, "GetResourceLimitMax"}, 22 {0x000B0140, nullptr, "GetResourceLimitMax"},
23 {0x000C0080, nullptr, "UnregisterProcess"}, 23 {0x000C0080, nullptr, "UnregisterProcess"},
24 {0x000D0240, nullptr, "LaunchTitleUpdate"}, 24 {0x000D0240, nullptr, "LaunchTitleUpdate"},
25}; 25};
26 26
27//////////////////////////////////////////////////////////////////////////////////////////////////// 27////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp
index e2c17d93b..80fa09f5f 100644
--- a/src/core/hle/service/ptm/ptm.cpp
+++ b/src/core/hle/service/ptm/ptm.cpp
@@ -2,21 +2,21 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/hle/service/ptm/ptm.h"
5#include "common/logging/log.h" 6#include "common/logging/log.h"
6#include "core/settings.h"
7#include "core/file_sys/file_backend.h" 7#include "core/file_sys/file_backend.h"
8#include "core/hle/service/fs/archive.h" 8#include "core/hle/service/fs/archive.h"
9#include "core/hle/service/ptm/ptm.h"
10#include "core/hle/service/ptm/ptm_play.h" 9#include "core/hle/service/ptm/ptm_play.h"
11#include "core/hle/service/ptm/ptm_sysm.h" 10#include "core/hle/service/ptm/ptm_sysm.h"
12#include "core/hle/service/ptm/ptm_u.h" 11#include "core/hle/service/ptm/ptm_u.h"
13#include "core/hle/service/service.h" 12#include "core/hle/service/service.h"
13#include "core/settings.h"
14 14
15namespace Service { 15namespace Service {
16namespace PTM { 16namespace PTM {
17 17
18/// Values for the default gamecoin.dat file 18/// Values for the default gamecoin.dat file
19static const GameCoin default_game_coin = { 0x4F00, 42, 0, 0, 0, 2014, 12, 29 }; 19static const GameCoin default_game_coin = {0x4F00, 42, 0, 0, 0, 2014, 12, 29};
20 20
21/// Id of the SharedExtData archive used by the PTM process 21/// Id of the SharedExtData archive used by the PTM process
22static const std::vector<u8> ptm_shared_extdata_id = {0, 0, 0, 0, 0x0B, 0, 0, 0xF0, 0, 0, 0, 0}; 22static const std::vector<u8> ptm_shared_extdata_id = {0, 0, 0, 0, 0x0B, 0, 0, 0xF0, 0, 0, 0, 0};
@@ -51,7 +51,8 @@ void GetBatteryLevel(Service::Interface* self) {
51 // it returns a valid result without implementing full functionality. 51 // it returns a valid result without implementing full functionality.
52 52
53 cmd_buff[1] = RESULT_SUCCESS.raw; 53 cmd_buff[1] = RESULT_SUCCESS.raw;
54 cmd_buff[2] = static_cast<u32>(ChargeLevels::CompletelyFull); // Set to a completely full battery 54 cmd_buff[2] =
55 static_cast<u32>(ChargeLevels::CompletelyFull); // Set to a completely full battery
55 56
56 LOG_WARNING(Service_PTM, "(STUBBED) called"); 57 LOG_WARNING(Service_PTM, "(STUBBED) called");
57} 58}
@@ -94,7 +95,8 @@ void CheckNew3DS(Service::Interface* self) {
94 const bool is_new_3ds = Settings::values.is_new_3ds; 95 const bool is_new_3ds = Settings::values.is_new_3ds;
95 96
96 if (is_new_3ds) { 97 if (is_new_3ds) {
97 LOG_CRITICAL(Service_PTM, "The option 'is_new_3ds' is enabled as part of the 'System' settings. Citra does not fully support New 3DS emulation yet!"); 98 LOG_CRITICAL(Service_PTM, "The option 'is_new_3ds' is enabled as part of the 'System' "
99 "settings. Citra does not fully support New 3DS emulation yet!");
98 } 100 }
99 101
100 cmd_buff[1] = RESULT_SUCCESS.raw; 102 cmd_buff[1] = RESULT_SUCCESS.raw;
@@ -111,15 +113,19 @@ void Init() {
111 shell_open = true; 113 shell_open = true;
112 battery_is_charging = true; 114 battery_is_charging = true;
113 115
114 // Open the SharedExtSaveData archive 0xF000000B and create the gamecoin.dat file if it doesn't exist 116 // Open the SharedExtSaveData archive 0xF000000B and create the gamecoin.dat file if it doesn't
117 // exist
115 FileSys::Path archive_path(ptm_shared_extdata_id); 118 FileSys::Path archive_path(ptm_shared_extdata_id);
116 auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); 119 auto archive_result =
120 Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path);
117 // If the archive didn't exist, create the files inside 121 // If the archive didn't exist, create the files inside
118 if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { 122 if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) {
119 // Format the archive to create the directories 123 // Format the archive to create the directories
120 Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, FileSys::ArchiveFormatInfo(), archive_path); 124 Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SharedExtSaveData,
125 FileSys::ArchiveFormatInfo(), archive_path);
121 // Open it again to get a valid archive now that the folder exists 126 // Open it again to get a valid archive now that the folder exists
122 archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); 127 archive_result =
128 Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path);
123 ASSERT_MSG(archive_result.Succeeded(), "Could not open the PTM SharedExtSaveData archive!"); 129 ASSERT_MSG(archive_result.Succeeded(), "Could not open the PTM SharedExtSaveData archive!");
124 130
125 FileSys::Path gamecoin_path("gamecoin.dat"); 131 FileSys::Path gamecoin_path("gamecoin.dat");
@@ -127,17 +133,18 @@ void Init() {
127 open_mode.write_flag.Assign(1); 133 open_mode.write_flag.Assign(1);
128 open_mode.create_flag.Assign(1); 134 open_mode.create_flag.Assign(1);
129 // Open the file and write the default gamecoin information 135 // Open the file and write the default gamecoin information
130 auto gamecoin_result = Service::FS::OpenFileFromArchive(*archive_result, gamecoin_path, open_mode); 136 auto gamecoin_result =
137 Service::FS::OpenFileFromArchive(*archive_result, gamecoin_path, open_mode);
131 if (gamecoin_result.Succeeded()) { 138 if (gamecoin_result.Succeeded()) {
132 auto gamecoin = gamecoin_result.MoveFrom(); 139 auto gamecoin = gamecoin_result.MoveFrom();
133 gamecoin->backend->Write(0, sizeof(GameCoin), 1, reinterpret_cast<const u8*>(&default_game_coin)); 140 gamecoin->backend->Write(0, sizeof(GameCoin), 1,
141 reinterpret_cast<const u8*>(&default_game_coin));
134 gamecoin->backend->Close(); 142 gamecoin->backend->Close();
135 } 143 }
136 } 144 }
137} 145}
138 146
139void Shutdown() { 147void Shutdown() {
140
141} 148}
142 149
143} // namespace PTM 150} // namespace PTM
diff --git a/src/core/hle/service/ptm/ptm.h b/src/core/hle/service/ptm/ptm.h
index 7ef8877c7..6e163a6f9 100644
--- a/src/core/hle/service/ptm/ptm.h
+++ b/src/core/hle/service/ptm/ptm.h
@@ -14,23 +14,24 @@ namespace PTM {
14 14
15/// Charge levels used by PTM functions 15/// Charge levels used by PTM functions
16enum class ChargeLevels : u32 { 16enum class ChargeLevels : u32 {
17 CriticalBattery = 1, 17 CriticalBattery = 1,
18 LowBattery = 2, 18 LowBattery = 2,
19 HalfFull = 3, 19 HalfFull = 3,
20 MostlyFull = 4, 20 MostlyFull = 4,
21 CompletelyFull = 5, 21 CompletelyFull = 5,
22}; 22};
23 23
24/** 24/**
25 * Represents the gamecoin file structure in the SharedExtData archive 25 * Represents the gamecoin file structure in the SharedExtData archive
26 * More information in 3dbrew (http://www.3dbrew.org/wiki/Extdata#Shared_Extdata_0xf000000b_gamecoin.dat) 26 * More information in 3dbrew
27 * (http://www.3dbrew.org/wiki/Extdata#Shared_Extdata_0xf000000b_gamecoin.dat)
27 */ 28 */
28struct GameCoin { 29struct GameCoin {
29 u32 magic; ///< Magic number: 0x4F00 30 u32 magic; ///< Magic number: 0x4F00
30 u16 total_coins; ///< Total Play Coins 31 u16 total_coins; ///< Total Play Coins
31 u16 total_coins_on_date; ///< Total Play Coins obtained on the date stored below. 32 u16 total_coins_on_date; ///< Total Play Coins obtained on the date stored below.
32 u32 step_count; ///< Total step count at the time a new Play Coin was obtained. 33 u32 step_count; ///< Total step count at the time a new Play Coin was obtained.
33 u32 last_step_count; ///< Step count for the day the last Play Coin was obtained 34 u32 last_step_count; ///< Step count for the day the last Play Coin was obtained
34 u16 year; 35 u16 year;
35 u8 month; 36 u8 month;
36 u8 day; 37 u8 day;
diff --git a/src/core/hle/service/ptm/ptm_play.cpp b/src/core/hle/service/ptm/ptm_play.cpp
index ca5dd0403..2e0c6e1a3 100644
--- a/src/core/hle/service/ptm/ptm_play.cpp
+++ b/src/core/hle/service/ptm/ptm_play.cpp
@@ -8,10 +8,10 @@ namespace Service {
8namespace PTM { 8namespace PTM {
9 9
10const Interface::FunctionInfo FunctionTable[] = { 10const Interface::FunctionInfo FunctionTable[] = {
11 {0x08070082, nullptr, "GetPlayHistory"}, 11 {0x08070082, nullptr, "GetPlayHistory"},
12 {0x08080000, nullptr, "GetPlayHistoryStart"}, 12 {0x08080000, nullptr, "GetPlayHistoryStart"},
13 {0x08090000, nullptr, "GetPlayHistoryLength"}, 13 {0x08090000, nullptr, "GetPlayHistoryLength"},
14 {0x080B0080, nullptr, "CalcPlayHistoryStart"}, 14 {0x080B0080, nullptr, "CalcPlayHistoryStart"},
15}; 15};
16 16
17PTM_Play_Interface::PTM_Play_Interface() { 17PTM_Play_Interface::PTM_Play_Interface() {
diff --git a/src/core/hle/service/ptm/ptm_play.h b/src/core/hle/service/ptm/ptm_play.h
index e5c3e04df..47f229581 100644
--- a/src/core/hle/service/ptm/ptm_play.h
+++ b/src/core/hle/service/ptm/ptm_play.h
@@ -13,9 +13,9 @@ class PTM_Play_Interface : public Service::Interface {
13public: 13public:
14 PTM_Play_Interface(); 14 PTM_Play_Interface();
15 15
16std::string GetPortName() const override { 16 std::string GetPortName() const override {
17 return "ptm:play"; 17 return "ptm:play";
18} 18 }
19}; 19};
20 20
21} // namespace PTM 21} // namespace PTM
diff --git a/src/core/hle/service/ptm/ptm_sysm.cpp b/src/core/hle/service/ptm/ptm_sysm.cpp
index cc4ef1101..693158dbf 100644
--- a/src/core/hle/service/ptm/ptm_sysm.cpp
+++ b/src/core/hle/service/ptm/ptm_sysm.cpp
@@ -9,37 +9,37 @@ namespace Service {
9namespace PTM { 9namespace PTM {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x040100C0, nullptr, "SetRtcAlarmEx"}, 12 {0x040100C0, nullptr, "SetRtcAlarmEx"},
13 {0x04020042, nullptr, "ReplySleepQuery"}, 13 {0x04020042, nullptr, "ReplySleepQuery"},
14 {0x04030042, nullptr, "NotifySleepPreparationComplete"}, 14 {0x04030042, nullptr, "NotifySleepPreparationComplete"},
15 {0x04040102, nullptr, "SetWakeupTrigger"}, 15 {0x04040102, nullptr, "SetWakeupTrigger"},
16 {0x04050000, nullptr, "GetAwakeReason"}, 16 {0x04050000, nullptr, "GetAwakeReason"},
17 {0x04060000, nullptr, "RequestSleep"}, 17 {0x04060000, nullptr, "RequestSleep"},
18 {0x040700C0, nullptr, "ShutdownAsync"}, 18 {0x040700C0, nullptr, "ShutdownAsync"},
19 {0x04080000, nullptr, "Awake"}, 19 {0x04080000, nullptr, "Awake"},
20 {0x04090080, nullptr, "RebootAsync"}, 20 {0x04090080, nullptr, "RebootAsync"},
21 {0x040A0000, CheckNew3DS, "CheckNew3DS"}, 21 {0x040A0000, CheckNew3DS, "CheckNew3DS"},
22 {0x08010640, nullptr, "SetInfoLEDPattern"}, 22 {0x08010640, nullptr, "SetInfoLEDPattern"},
23 {0x08020040, nullptr, "SetInfoLEDPatternHeader"}, 23 {0x08020040, nullptr, "SetInfoLEDPatternHeader"},
24 {0x08030000, nullptr, "GetInfoLEDStatus"}, 24 {0x08030000, nullptr, "GetInfoLEDStatus"},
25 {0x08040040, nullptr, "SetBatteryEmptyLEDPattern"}, 25 {0x08040040, nullptr, "SetBatteryEmptyLEDPattern"},
26 {0x08050000, nullptr, "ClearStepHistory"}, 26 {0x08050000, nullptr, "ClearStepHistory"},
27 {0x080600C2, nullptr, "SetStepHistory"}, 27 {0x080600C2, nullptr, "SetStepHistory"},
28 {0x08070082, nullptr, "GetPlayHistory"}, 28 {0x08070082, nullptr, "GetPlayHistory"},
29 {0x08080000, nullptr, "GetPlayHistoryStart"}, 29 {0x08080000, nullptr, "GetPlayHistoryStart"},
30 {0x08090000, nullptr, "GetPlayHistoryLength"}, 30 {0x08090000, nullptr, "GetPlayHistoryLength"},
31 {0x080A0000, nullptr, "ClearPlayHistory"}, 31 {0x080A0000, nullptr, "ClearPlayHistory"},
32 {0x080B0080, nullptr, "CalcPlayHistoryStart"}, 32 {0x080B0080, nullptr, "CalcPlayHistoryStart"},
33 {0x080C0080, nullptr, "SetUserTime"}, 33 {0x080C0080, nullptr, "SetUserTime"},
34 {0x080D0000, nullptr, "InvalidateSystemTime"}, 34 {0x080D0000, nullptr, "InvalidateSystemTime"},
35 {0x080E0140, nullptr, "NotifyPlayEvent"}, 35 {0x080E0140, nullptr, "NotifyPlayEvent"},
36 {0x080F0000, IsLegacyPowerOff, "IsLegacyPowerOff"}, 36 {0x080F0000, IsLegacyPowerOff, "IsLegacyPowerOff"},
37 {0x08100000, nullptr, "ClearLegacyPowerOff"}, 37 {0x08100000, nullptr, "ClearLegacyPowerOff"},
38 {0x08110000, GetShellState, "GetShellState"}, 38 {0x08110000, GetShellState, "GetShellState"},
39 {0x08120000, nullptr, "IsShutdownByBatteryEmpty"}, 39 {0x08120000, nullptr, "IsShutdownByBatteryEmpty"},
40 {0x08130000, nullptr, "FormatSavedata"}, 40 {0x08130000, nullptr, "FormatSavedata"},
41 {0x08140000, nullptr, "GetLegacyJumpProhibitedFlag"}, 41 {0x08140000, nullptr, "GetLegacyJumpProhibitedFlag"},
42 {0x08180040, nullptr, "ConfigureNew3DSCPU"}, 42 {0x08180040, nullptr, "ConfigureNew3DSCPU"},
43}; 43};
44 44
45PTM_Sysm_Interface::PTM_Sysm_Interface() { 45PTM_Sysm_Interface::PTM_Sysm_Interface() {
diff --git a/src/core/hle/service/ptm/ptm_u.cpp b/src/core/hle/service/ptm/ptm_u.cpp
index 17e764866..65e868393 100644
--- a/src/core/hle/service/ptm/ptm_u.cpp
+++ b/src/core/hle/service/ptm/ptm_u.cpp
@@ -9,21 +9,21 @@ namespace Service {
9namespace PTM { 9namespace PTM {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x00010002, nullptr, "RegisterAlarmClient"}, 12 {0x00010002, nullptr, "RegisterAlarmClient"},
13 {0x00020080, nullptr, "SetRtcAlarm"}, 13 {0x00020080, nullptr, "SetRtcAlarm"},
14 {0x00030000, nullptr, "GetRtcAlarm"}, 14 {0x00030000, nullptr, "GetRtcAlarm"},
15 {0x00040000, nullptr, "CancelRtcAlarm"}, 15 {0x00040000, nullptr, "CancelRtcAlarm"},
16 {0x00050000, GetAdapterState, "GetAdapterState"}, 16 {0x00050000, GetAdapterState, "GetAdapterState"},
17 {0x00060000, GetShellState, "GetShellState"}, 17 {0x00060000, GetShellState, "GetShellState"},
18 {0x00070000, GetBatteryLevel, "GetBatteryLevel"}, 18 {0x00070000, GetBatteryLevel, "GetBatteryLevel"},
19 {0x00080000, GetBatteryChargeState, "GetBatteryChargeState"}, 19 {0x00080000, GetBatteryChargeState, "GetBatteryChargeState"},
20 {0x00090000, nullptr, "GetPedometerState"}, 20 {0x00090000, nullptr, "GetPedometerState"},
21 {0x000A0042, nullptr, "GetStepHistoryEntry"}, 21 {0x000A0042, nullptr, "GetStepHistoryEntry"},
22 {0x000B00C2, nullptr, "GetStepHistory"}, 22 {0x000B00C2, nullptr, "GetStepHistory"},
23 {0x000C0000, GetTotalStepCount, "GetTotalStepCount"}, 23 {0x000C0000, GetTotalStepCount, "GetTotalStepCount"},
24 {0x000D0040, nullptr, "SetPedometerRecordingMode"}, 24 {0x000D0040, nullptr, "SetPedometerRecordingMode"},
25 {0x000E0000, nullptr, "GetPedometerRecordingMode"}, 25 {0x000E0000, nullptr, "GetPedometerRecordingMode"},
26 {0x000F0084, nullptr, "GetStepHistoryAll"}, 26 {0x000F0084, nullptr, "GetStepHistoryAll"},
27}; 27};
28 28
29PTM_U_Interface::PTM_U_Interface() { 29PTM_U_Interface::PTM_U_Interface() {
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 5b8440b77..a531aad87 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -5,7 +5,6 @@
5#include "common/logging/log.h" 5#include "common/logging/log.h"
6#include "common/string_util.h" 6#include "common/string_util.h"
7 7
8#include "core/hle/service/service.h"
9#include "core/hle/service/ac_u.h" 8#include "core/hle/service/ac_u.h"
10#include "core/hle/service/act_a.h" 9#include "core/hle/service/act_a.h"
11#include "core/hle/service/act_u.h" 10#include "core/hle/service/act_u.h"
@@ -19,6 +18,7 @@
19#include "core/hle/service/ns_s.h" 18#include "core/hle/service/ns_s.h"
20#include "core/hle/service/nwm_uds.h" 19#include "core/hle/service/nwm_uds.h"
21#include "core/hle/service/pm_app.h" 20#include "core/hle/service/pm_app.h"
21#include "core/hle/service/service.h"
22#include "core/hle/service/soc_u.h" 22#include "core/hle/service/soc_u.h"
23#include "core/hle/service/srv.h" 23#include "core/hle/service/srv.h"
24#include "core/hle/service/ssl_c.h" 24#include "core/hle/service/ssl_c.h"
@@ -29,10 +29,10 @@
29#include "core/hle/service/boss/boss.h" 29#include "core/hle/service/boss/boss.h"
30#include "core/hle/service/cam/cam.h" 30#include "core/hle/service/cam/cam.h"
31#include "core/hle/service/cecd/cecd.h" 31#include "core/hle/service/cecd/cecd.h"
32#include "core/hle/service/cfg/cfg.h"
32#include "core/hle/service/dlp/dlp.h" 33#include "core/hle/service/dlp/dlp.h"
33#include "core/hle/service/frd/frd.h" 34#include "core/hle/service/frd/frd.h"
34#include "core/hle/service/fs/archive.h" 35#include "core/hle/service/fs/archive.h"
35#include "core/hle/service/cfg/cfg.h"
36#include "core/hle/service/hid/hid.h" 36#include "core/hle/service/hid/hid.h"
37#include "core/hle/service/ir/ir.h" 37#include "core/hle/service/ir/ir.h"
38#include "core/hle/service/ldr_ro/ldr_ro.h" 38#include "core/hle/service/ldr_ro/ldr_ro.h"
@@ -50,11 +50,13 @@ std::unordered_map<std::string, Kernel::SharedPtr<Interface>> g_srv_services;
50 * Creates a function string for logging, complete with the name (or header code, depending 50 * Creates a function string for logging, complete with the name (or header code, depending
51 * on what's passed in) the port name, and all the cmd_buff arguments. 51 * on what's passed in) the port name, and all the cmd_buff arguments.
52 */ 52 */
53static std::string MakeFunctionString(const char* name, const char* port_name, const u32* cmd_buff) { 53static std::string MakeFunctionString(const char* name, const char* port_name,
54 const u32* cmd_buff) {
54 // Number of params == bits 0-5 + bits 6-11 55 // Number of params == bits 0-5 + bits 6-11
55 int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F); 56 int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F);
56 57
57 std::string function_string = Common::StringFromFormat("function '%s': port=%s", name, port_name); 58 std::string function_string =
59 Common::StringFromFormat("function '%s': port=%s", name, port_name);
58 for (int i = 1; i <= num_params; ++i) { 60 for (int i = 1; i <= num_params; ++i) {
59 function_string += Common::StringFromFormat(", cmd_buff[%i]=0x%X", i, cmd_buff[i]); 61 function_string += Common::StringFromFormat(", cmd_buff[%i]=0x%X", i, cmd_buff[i]);
60 } 62 }
@@ -66,14 +68,19 @@ ResultVal<bool> Interface::SyncRequest() {
66 auto itr = m_functions.find(cmd_buff[0]); 68 auto itr = m_functions.find(cmd_buff[0]);
67 69
68 if (itr == m_functions.end() || itr->second.func == nullptr) { 70 if (itr == m_functions.end() || itr->second.func == nullptr) {
69 std::string function_name = (itr == m_functions.end()) ? Common::StringFromFormat("0x%08X", cmd_buff[0]) : itr->second.name; 71 std::string function_name = (itr == m_functions.end())
70 LOG_ERROR(Service, "unknown / unimplemented %s", MakeFunctionString(function_name.c_str(), GetPortName().c_str(), cmd_buff).c_str()); 72 ? Common::StringFromFormat("0x%08X", cmd_buff[0])
73 : itr->second.name;
74 LOG_ERROR(
75 Service, "unknown / unimplemented %s",
76 MakeFunctionString(function_name.c_str(), GetPortName().c_str(), cmd_buff).c_str());
71 77
72 // TODO(bunnei): Hack - ignore error 78 // TODO(bunnei): Hack - ignore error
73 cmd_buff[1] = 0; 79 cmd_buff[1] = 0;
74 return MakeResult<bool>(false); 80 return MakeResult<bool>(false);
75 } 81 }
76 LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str()); 82 LOG_TRACE(Service, "%s",
83 MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str());
77 84
78 itr->second.func(this); 85 itr->second.func(this);
79 86
@@ -163,6 +170,4 @@ void Shutdown() {
163 g_kernel_named_ports.clear(); 170 g_kernel_named_ports.clear();
164 LOG_DEBUG(Service, "shutdown OK"); 171 LOG_DEBUG(Service, "shutdown OK");
165} 172}
166
167
168} 173}
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index f31135212..cd216f27e 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -28,13 +28,15 @@ class Interface : public Kernel::Session {
28 // just something that encapsulates a session and acts as a helper to implement service 28 // just something that encapsulates a session and acts as a helper to implement service
29 // processes. 29 // processes.
30public: 30public:
31 std::string GetName() const override { return GetPortName(); } 31 std::string GetName() const override {
32 return GetPortName();
33 }
32 34
33 typedef void (*Function)(Interface*); 35 typedef void (*Function)(Interface*);
34 36
35 struct FunctionInfo { 37 struct FunctionInfo {
36 u32 id; 38 u32 id;
37 Function func; 39 Function func;
38 const char* name; 40 const char* name;
39 }; 41 };
40 42
@@ -49,7 +51,6 @@ public:
49 ResultVal<bool> SyncRequest() override; 51 ResultVal<bool> SyncRequest() override;
50 52
51protected: 53protected:
52
53 /** 54 /**
54 * Registers the functions in the service 55 * Registers the functions in the service
55 */ 56 */
@@ -62,7 +63,6 @@ protected:
62 63
63private: 64private:
64 boost::container::flat_map<u32, FunctionInfo> m_functions; 65 boost::container::flat_map<u32, FunctionInfo> m_functions;
65
66}; 66};
67 67
68/// Initialize ServiceManager 68/// Initialize ServiceManager
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp
index 9b285567b..695b286c0 100644
--- a/src/core/hle/service/soc_u.cpp
+++ b/src/core/hle/service/soc_u.cpp
@@ -19,40 +19,40 @@
19#include "core/memory.h" 19#include "core/memory.h"
20 20
21#ifdef _WIN32 21#ifdef _WIN32
22 #include <winsock2.h> 22#include <winsock2.h>
23 #include <ws2tcpip.h> 23#include <ws2tcpip.h>
24 24
25 // MinGW does not define several errno constants 25// MinGW does not define several errno constants
26 #ifndef _MSC_VER 26#ifndef _MSC_VER
27 #define EBADMSG 104 27#define EBADMSG 104
28 #define ENODATA 120 28#define ENODATA 120
29 #define ENOMSG 122 29#define ENOMSG 122
30 #define ENOSR 124 30#define ENOSR 124
31 #define ENOSTR 125 31#define ENOSTR 125
32 #define ETIME 137 32#define ETIME 137
33 #define EIDRM 2001 33#define EIDRM 2001
34 #define ENOLINK 2002 34#define ENOLINK 2002
35 #endif // _MSC_VER 35#endif // _MSC_VER
36#else 36#else
37 #include <cerrno> 37#include <cerrno>
38 #include <fcntl.h> 38#include <fcntl.h>
39 #include <netinet/in.h> 39#include <netdb.h>
40 #include <netdb.h> 40#include <netinet/in.h>
41 #include <poll.h> 41#include <poll.h>
42 #include <sys/socket.h> 42#include <sys/socket.h>
43 #include <unistd.h> 43#include <unistd.h>
44#endif 44#endif
45 45
46#ifdef _WIN32 46#ifdef _WIN32
47# define WSAEAGAIN WSAEWOULDBLOCK 47#define WSAEAGAIN WSAEWOULDBLOCK
48# define WSAEMULTIHOP -1 // Invalid dummy value 48#define WSAEMULTIHOP -1 // Invalid dummy value
49# define ERRNO(x) WSA##x 49#define ERRNO(x) WSA##x
50# define GET_ERRNO WSAGetLastError() 50#define GET_ERRNO WSAGetLastError()
51# define poll(x, y, z) WSAPoll(x, y, z); 51#define poll(x, y, z) WSAPoll(x, y, z);
52#else 52#else
53# define ERRNO(x) x 53#define ERRNO(x) x
54# define GET_ERRNO errno 54#define GET_ERRNO errno
55# define closesocket(x) close(x) 55#define closesocket(x) close(x)
56#endif 56#endif
57 57
58static const s32 SOCKET_ERROR_VALUE = -1; 58static const s32 SOCKET_ERROR_VALUE = -1;
@@ -63,84 +63,82 @@ static const s32 SOCKET_ERROR_VALUE = -1;
63namespace SOC_U { 63namespace SOC_U {
64 64
65/// Holds the translation from system network errors to 3DS network errors 65/// Holds the translation from system network errors to 3DS network errors
66static const std::unordered_map<int, int> error_map = { { 66static const std::unordered_map<int, int> error_map = {{{E2BIG, 1},
67 { E2BIG, 1 }, 67 {ERRNO(EACCES), 2},
68 { ERRNO(EACCES), 2 }, 68 {ERRNO(EADDRINUSE), 3},
69 { ERRNO(EADDRINUSE), 3 }, 69 {ERRNO(EADDRNOTAVAIL), 4},
70 { ERRNO(EADDRNOTAVAIL), 4 }, 70 {ERRNO(EAFNOSUPPORT), 5},
71 { ERRNO(EAFNOSUPPORT), 5 }, 71 {ERRNO(EAGAIN), 6},
72 { ERRNO(EAGAIN), 6 }, 72 {ERRNO(EALREADY), 7},
73 { ERRNO(EALREADY), 7 }, 73 {ERRNO(EBADF), 8},
74 { ERRNO(EBADF), 8 }, 74 {EBADMSG, 9},
75 { EBADMSG, 9 }, 75 {EBUSY, 10},
76 { EBUSY, 10 }, 76 {ECANCELED, 11},
77 { ECANCELED, 11 }, 77 {ECHILD, 12},
78 { ECHILD, 12 }, 78 {ERRNO(ECONNABORTED), 13},
79 { ERRNO(ECONNABORTED), 13 }, 79 {ERRNO(ECONNREFUSED), 14},
80 { ERRNO(ECONNREFUSED), 14 }, 80 {ERRNO(ECONNRESET), 15},
81 { ERRNO(ECONNRESET), 15 }, 81 {EDEADLK, 16},
82 { EDEADLK, 16 }, 82 {ERRNO(EDESTADDRREQ), 17},
83 { ERRNO(EDESTADDRREQ), 17 }, 83 {EDOM, 18},
84 { EDOM, 18 }, 84 {ERRNO(EDQUOT), 19},
85 { ERRNO(EDQUOT), 19 }, 85 {EEXIST, 20},
86 { EEXIST, 20 }, 86 {ERRNO(EFAULT), 21},
87 { ERRNO(EFAULT), 21 }, 87 {EFBIG, 22},
88 { EFBIG, 22 }, 88 {ERRNO(EHOSTUNREACH), 23},
89 { ERRNO(EHOSTUNREACH), 23 }, 89 {EIDRM, 24},
90 { EIDRM, 24 }, 90 {EILSEQ, 25},
91 { EILSEQ, 25 }, 91 {ERRNO(EINPROGRESS), 26},
92 { ERRNO(EINPROGRESS), 26 }, 92 {ERRNO(EINTR), 27},
93 { ERRNO(EINTR), 27 }, 93 {ERRNO(EINVAL), 28},
94 { ERRNO(EINVAL), 28 }, 94 {EIO, 29},
95 { EIO, 29 }, 95 {ERRNO(EISCONN), 30},
96 { ERRNO(EISCONN), 30 }, 96 {EISDIR, 31},
97 { EISDIR, 31 }, 97 {ERRNO(ELOOP), 32},
98 { ERRNO(ELOOP), 32 }, 98 {ERRNO(EMFILE), 33},
99 { ERRNO(EMFILE), 33 }, 99 {EMLINK, 34},
100 { EMLINK, 34 }, 100 {ERRNO(EMSGSIZE), 35},
101 { ERRNO(EMSGSIZE), 35 }, 101 {ERRNO(EMULTIHOP), 36},
102 { ERRNO(EMULTIHOP), 36 }, 102 {ERRNO(ENAMETOOLONG), 37},
103 { ERRNO(ENAMETOOLONG), 37 }, 103 {ERRNO(ENETDOWN), 38},
104 { ERRNO(ENETDOWN), 38 }, 104 {ERRNO(ENETRESET), 39},
105 { ERRNO(ENETRESET), 39 }, 105 {ERRNO(ENETUNREACH), 40},
106 { ERRNO(ENETUNREACH), 40 }, 106 {ENFILE, 41},
107 { ENFILE, 41 }, 107 {ERRNO(ENOBUFS), 42},
108 { ERRNO(ENOBUFS), 42 }, 108 {ENODATA, 43},
109 { ENODATA, 43 }, 109 {ENODEV, 44},
110 { ENODEV, 44 }, 110 {ENOENT, 45},
111 { ENOENT, 45 }, 111 {ENOEXEC, 46},
112 { ENOEXEC, 46 }, 112 {ENOLCK, 47},
113 { ENOLCK, 47 }, 113 {ENOLINK, 48},
114 { ENOLINK, 48 }, 114 {ENOMEM, 49},
115 { ENOMEM, 49 }, 115 {ENOMSG, 50},
116 { ENOMSG, 50 }, 116 {ERRNO(ENOPROTOOPT), 51},
117 { ERRNO(ENOPROTOOPT), 51 }, 117 {ENOSPC, 52},
118 { ENOSPC, 52 }, 118 {ENOSR, 53},
119 { ENOSR, 53 }, 119 {ENOSTR, 54},
120 { ENOSTR, 54 }, 120 {ENOSYS, 55},
121 { ENOSYS, 55 }, 121 {ERRNO(ENOTCONN), 56},
122 { ERRNO(ENOTCONN), 56 }, 122 {ENOTDIR, 57},
123 { ENOTDIR, 57 }, 123 {ERRNO(ENOTEMPTY), 58},
124 { ERRNO(ENOTEMPTY), 58 }, 124 {ERRNO(ENOTSOCK), 59},
125 { ERRNO(ENOTSOCK), 59 }, 125 {ENOTSUP, 60},
126 { ENOTSUP, 60 }, 126 {ENOTTY, 61},
127 { ENOTTY, 61 }, 127 {ENXIO, 62},
128 { ENXIO, 62 }, 128 {ERRNO(EOPNOTSUPP), 63},
129 { ERRNO(EOPNOTSUPP), 63 }, 129 {EOVERFLOW, 64},
130 { EOVERFLOW, 64 }, 130 {EPERM, 65},
131 { EPERM, 65 }, 131 {EPIPE, 66},
132 { EPIPE, 66 }, 132 {EPROTO, 67},
133 { EPROTO, 67 }, 133 {ERRNO(EPROTONOSUPPORT), 68},
134 { ERRNO(EPROTONOSUPPORT), 68 }, 134 {ERRNO(EPROTOTYPE), 69},
135 { ERRNO(EPROTOTYPE), 69 }, 135 {ERANGE, 70},
136 { ERANGE, 70 }, 136 {EROFS, 71},
137 { EROFS, 71 }, 137 {ESPIPE, 72},
138 { ESPIPE, 72 }, 138 {ESRCH, 73},
139 { ESRCH, 73 }, 139 {ERRNO(ESTALE), 74},
140 { ERRNO(ESTALE), 74 }, 140 {ETIME, 75},
141 { ETIME, 75 }, 141 {ERRNO(ETIMEDOUT), 76}}};
142 { ERRNO(ETIMEDOUT), 76 }
143}};
144 142
145/// Converts a network error from platform-specific to 3ds-specific 143/// Converts a network error from platform-specific to 3ds-specific
146static int TranslateError(int error) { 144static int TranslateError(int error) {
@@ -153,21 +151,21 @@ static int TranslateError(int error) {
153 151
154/// Holds the translation from system network socket options to 3DS network socket options 152/// Holds the translation from system network socket options to 3DS network socket options
155/// Note: -1 = No effect/unavailable 153/// Note: -1 = No effect/unavailable
156static const std::unordered_map<int, int> sockopt_map = { { 154static const std::unordered_map<int, int> sockopt_map = {{
157 { 0x0004, SO_REUSEADDR }, 155 {0x0004, SO_REUSEADDR},
158 { 0x0080, -1 }, 156 {0x0080, -1},
159 { 0x0100, -1 }, 157 {0x0100, -1},
160 { 0x1001, SO_SNDBUF }, 158 {0x1001, SO_SNDBUF},
161 { 0x1002, SO_RCVBUF }, 159 {0x1002, SO_RCVBUF},
162 { 0x1003, -1 }, 160 {0x1003, -1},
163#ifdef _WIN32 161#ifdef _WIN32
164 /// Unsupported in WinSock2 162 /// Unsupported in WinSock2
165 { 0x1004, -1 }, 163 {0x1004, -1},
166#else 164#else
167 { 0x1004, SO_RCVLOWAT }, 165 {0x1004, SO_RCVLOWAT},
168#endif 166#endif
169 { 0x1008, SO_TYPE }, 167 {0x1008, SO_TYPE},
170 { 0x1009, SO_ERROR }, 168 {0x1009, SO_ERROR},
171}}; 169}};
172 170
173/// Converts a socket option from 3ds-specific to platform-specific 171/// Converts a socket option from 3ds-specific to platform-specific
@@ -203,7 +201,8 @@ struct CTRPollFD {
203 return *this; 201 return *this;
204 } 202 }
205 203
206 /// Translates the resulting events of a Poll operation from platform-specific to 3ds specific 204 /// Translates the resulting events of a Poll operation from platform-specific to 3ds
205 /// specific
207 static Events TranslateTo3DS(u32 input_event) { 206 static Events TranslateTo3DS(u32 input_event) {
208 Events ev = {}; 207 Events ev = {};
209 if (input_event & POLLIN) 208 if (input_event & POLLIN)
@@ -221,7 +220,8 @@ struct CTRPollFD {
221 return ev; 220 return ev;
222 } 221 }
223 222
224 /// Translates the resulting events of a Poll operation from 3ds specific to platform specific 223 /// Translates the resulting events of a Poll operation from 3ds specific to platform
224 /// specific
225 static u32 TranslateToPlatform(Events input_event) { 225 static u32 TranslateToPlatform(Events input_event) {
226 u32 ret = 0; 226 u32 ret = 0;
227 if (input_event.pollin) 227 if (input_event.pollin)
@@ -239,7 +239,7 @@ struct CTRPollFD {
239 return ret; 239 return ret;
240 } 240 }
241 }; 241 };
242 Events events; ///< Events to poll for (input) 242 Events events; ///< Events to poll for (input)
243 Events revents; ///< Events received (output) 243 Events revents; ///< Events received (output)
244 244
245 /// Converts a platform-specific pollfd to a 3ds specific structure 245 /// Converts a platform-specific pollfd to a 3ds specific structure
@@ -265,17 +265,17 @@ struct CTRPollFD {
265union CTRSockAddr { 265union CTRSockAddr {
266 /// Structure to represent a raw sockaddr 266 /// Structure to represent a raw sockaddr
267 struct { 267 struct {
268 u8 len; ///< The length of the entire structure, only the set fields count 268 u8 len; ///< The length of the entire structure, only the set fields count
269 u8 sa_family; ///< The address family of the sockaddr 269 u8 sa_family; ///< The address family of the sockaddr
270 u8 sa_data[0x1A]; ///< The extra data, this varies, depending on the address family 270 u8 sa_data[0x1A]; ///< The extra data, this varies, depending on the address family
271 } raw; 271 } raw;
272 272
273 /// Structure to represent the 3ds' sockaddr_in structure 273 /// Structure to represent the 3ds' sockaddr_in structure
274 struct CTRSockAddrIn { 274 struct CTRSockAddrIn {
275 u8 len; ///< The length of the entire structure 275 u8 len; ///< The length of the entire structure
276 u8 sin_family; ///< The address family of the sockaddr_in 276 u8 sin_family; ///< The address family of the sockaddr_in
277 u16 sin_port; ///< The port associated with this sockaddr_in 277 u16 sin_port; ///< The port associated with this sockaddr_in
278 u32 sin_addr; ///< The actual address of the sockaddr_in 278 u32 sin_addr; ///< The actual address of the sockaddr_in
279 } in; 279 } in;
280 280
281 /// Convert a 3DS CTRSockAddr to a platform-specific sockaddr 281 /// Convert a 3DS CTRSockAddr to a platform-specific sockaddr
@@ -286,8 +286,7 @@ union CTRSockAddr {
286 286
287 // We can not guarantee ABI compatibility between platforms so we copy the fields manually 287 // We can not guarantee ABI compatibility between platforms so we copy the fields manually
288 switch (result.sa_family) { 288 switch (result.sa_family) {
289 case AF_INET: 289 case AF_INET: {
290 {
291 sockaddr_in* result_in = reinterpret_cast<sockaddr_in*>(&result); 290 sockaddr_in* result_in = reinterpret_cast<sockaddr_in*>(&result);
292 result_in->sin_port = ctr_addr.in.sin_port; 291 result_in->sin_port = ctr_addr.in.sin_port;
293 result_in->sin_addr.s_addr = ctr_addr.in.sin_addr; 292 result_in->sin_addr.s_addr = ctr_addr.in.sin_addr;
@@ -307,8 +306,7 @@ union CTRSockAddr {
307 result.raw.sa_family = static_cast<u8>(addr.sa_family); 306 result.raw.sa_family = static_cast<u8>(addr.sa_family);
308 // We can not guarantee ABI compatibility between platforms so we copy the fields manually 307 // We can not guarantee ABI compatibility between platforms so we copy the fields manually
309 switch (result.raw.sa_family) { 308 switch (result.raw.sa_family) {
310 case AF_INET: 309 case AF_INET: {
311 {
312 sockaddr_in const* addr_in = reinterpret_cast<sockaddr_in const*>(&addr); 310 sockaddr_in const* addr_in = reinterpret_cast<sockaddr_in const*>(&addr);
313 result.raw.len = sizeof(CTRSockAddrIn); 311 result.raw.len = sizeof(CTRSockAddrIn);
314 result.in.sin_port = addr_in->sin_port; 312 result.in.sin_port = addr_in->sin_port;
@@ -341,24 +339,27 @@ static void Socket(Service::Interface* self) {
341 339
342 // Only 0 is allowed according to 3dbrew, using 0 will let the OS decide which protocol to use 340 // Only 0 is allowed according to 3dbrew, using 0 will let the OS decide which protocol to use
343 if (protocol != 0) { 341 if (protocol != 0) {
344 cmd_buffer[1] = UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code 342 cmd_buffer[1] =
343 UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code
345 return; 344 return;
346 } 345 }
347 346
348 if (domain != AF_INET) { 347 if (domain != AF_INET) {
349 cmd_buffer[1] = UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code 348 cmd_buffer[1] =
349 UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code
350 return; 350 return;
351 } 351 }
352 352
353 if (type != SOCK_DGRAM && type != SOCK_STREAM) { 353 if (type != SOCK_DGRAM && type != SOCK_STREAM) {
354 cmd_buffer[1] = UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code 354 cmd_buffer[1] =
355 UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code
355 return; 356 return;
356 } 357 }
357 358
358 u32 socket_handle = static_cast<u32>(::socket(domain, type, protocol)); 359 u32 socket_handle = static_cast<u32>(::socket(domain, type, protocol));
359 360
360 if ((s32)socket_handle != SOCKET_ERROR_VALUE) 361 if ((s32)socket_handle != SOCKET_ERROR_VALUE)
361 open_sockets[socket_handle] = { socket_handle, true }; 362 open_sockets[socket_handle] = {socket_handle, true};
362 363
363 int result = 0; 364 int result = 0;
364 if ((s32)socket_handle == SOCKET_ERROR_VALUE) 365 if ((s32)socket_handle == SOCKET_ERROR_VALUE)
@@ -406,8 +407,8 @@ static void Fcntl(Service::Interface* self) {
406 int result = 0; 407 int result = 0;
407 u32 posix_ret = 0; // TODO: Check what hardware returns for F_SETFL (unspecified by POSIX) 408 u32 posix_ret = 0; // TODO: Check what hardware returns for F_SETFL (unspecified by POSIX)
408 SCOPE_EXIT({ 409 SCOPE_EXIT({
409 cmd_buffer[1] = result; 410 cmd_buffer[1] = result;
410 cmd_buffer[2] = posix_ret; 411 cmd_buffer[2] = posix_ret;
411 }); 412 });
412 413
413 if (ctr_cmd == 3) { // F_GETFL 414 if (ctr_cmd == 3) { // F_GETFL
@@ -493,7 +494,7 @@ static void Accept(Service::Interface* self) {
493 u32 ret = static_cast<u32>(::accept(socket_handle, &addr, &addr_len)); 494 u32 ret = static_cast<u32>(::accept(socket_handle, &addr, &addr_len));
494 495
495 if ((s32)ret != SOCKET_ERROR_VALUE) 496 if ((s32)ret != SOCKET_ERROR_VALUE)
496 open_sockets[ret] = { ret, true }; 497 open_sockets[ret] = {ret, true};
497 498
498 int result = 0; 499 int result = 0;
499 if ((s32)ret == SOCKET_ERROR_VALUE) { 500 if ((s32)ret == SOCKET_ERROR_VALUE) {
@@ -573,9 +574,11 @@ static void SendTo(Service::Interface* self) {
573 int ret = -1; 574 int ret = -1;
574 if (addr_len > 0) { 575 if (addr_len > 0) {
575 sockaddr dest_addr = CTRSockAddr::ToPlatform(ctr_dest_addr); 576 sockaddr dest_addr = CTRSockAddr::ToPlatform(ctr_dest_addr);
576 ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags, &dest_addr, sizeof(dest_addr)); 577 ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags,
578 &dest_addr, sizeof(dest_addr));
577 } else { 579 } else {
578 ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags, nullptr, 0); 580 ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags,
581 nullptr, 0);
579 } 582 }
580 583
581 int result = 0; 584 int result = 0;
@@ -596,8 +599,7 @@ static void RecvFrom(Service::Interface* self) {
596 u32 flags = cmd_buffer[3]; 599 u32 flags = cmd_buffer[3];
597 socklen_t addr_len = static_cast<socklen_t>(cmd_buffer[4]); 600 socklen_t addr_len = static_cast<socklen_t>(cmd_buffer[4]);
598 601
599 struct 602 struct {
600 {
601 u32 output_buffer_descriptor; 603 u32 output_buffer_descriptor;
602 u32 output_buffer_addr; 604 u32 output_buffer_addr;
603 u32 address_buffer_descriptor; 605 u32 address_buffer_descriptor;
@@ -619,11 +621,13 @@ static void RecvFrom(Service::Interface* self) {
619 std::vector<u8> output_buff(len); 621 std::vector<u8> output_buff(len);
620 sockaddr src_addr; 622 sockaddr src_addr;
621 socklen_t src_addr_len = sizeof(src_addr); 623 socklen_t src_addr_len = sizeof(src_addr);
622 int ret = ::recvfrom(socket_handle, reinterpret_cast<char*>(output_buff.data()), len, flags, &src_addr, &src_addr_len); 624 int ret = ::recvfrom(socket_handle, reinterpret_cast<char*>(output_buff.data()), len, flags,
625 &src_addr, &src_addr_len);
623 626
624 if (ret >= 0 && buffer_parameters.output_src_address_buffer != 0 && src_addr_len > 0) { 627 if (ret >= 0 && buffer_parameters.output_src_address_buffer != 0 && src_addr_len > 0) {
625 CTRSockAddr ctr_src_addr = CTRSockAddr::FromPlatform(src_addr); 628 CTRSockAddr ctr_src_addr = CTRSockAddr::FromPlatform(src_addr);
626 Memory::WriteBlock(buffer_parameters.output_src_address_buffer, &ctr_src_addr, sizeof(ctr_src_addr)); 629 Memory::WriteBlock(buffer_parameters.output_src_address_buffer, &ctr_src_addr,
630 sizeof(ctr_src_addr));
627 } 631 }
628 632
629 int result = 0; 633 int result = 0;
@@ -633,7 +637,8 @@ static void RecvFrom(Service::Interface* self) {
633 total_received = 0; 637 total_received = 0;
634 } else { 638 } else {
635 // Write only the data we received to avoid overwriting parts of the buffer with zeros 639 // Write only the data we received to avoid overwriting parts of the buffer with zeros
636 Memory::WriteBlock(buffer_parameters.output_buffer_addr, output_buff.data(), total_received); 640 Memory::WriteBlock(buffer_parameters.output_buffer_addr, output_buff.data(),
641 total_received);
637 } 642 }
638 643
639 cmd_buffer[1] = result; 644 cmd_buffer[1] = result;
@@ -648,7 +653,8 @@ static void Poll(Service::Interface* self) {
648 653
649 VAddr input_fds_addr = cmd_buffer[6]; 654 VAddr input_fds_addr = cmd_buffer[6];
650 VAddr output_fds_addr = cmd_buffer[0x104 >> 2]; 655 VAddr output_fds_addr = cmd_buffer[0x104 >> 2];
651 if (!Memory::IsValidVirtualAddress(input_fds_addr) || !Memory::IsValidVirtualAddress(output_fds_addr)) { 656 if (!Memory::IsValidVirtualAddress(input_fds_addr) ||
657 !Memory::IsValidVirtualAddress(output_fds_addr)) {
652 cmd_buffer[1] = -1; // TODO(Subv): Find correct error code. 658 cmd_buffer[1] = -1; // TODO(Subv): Find correct error code.
653 return; 659 return;
654 } 660 }
@@ -656,7 +662,8 @@ static void Poll(Service::Interface* self) {
656 std::vector<CTRPollFD> ctr_fds(nfds); 662 std::vector<CTRPollFD> ctr_fds(nfds);
657 Memory::ReadBlock(input_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD)); 663 Memory::ReadBlock(input_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD));
658 664
659 // The 3ds_pollfd and the pollfd structures may be different (Windows/Linux have different sizes) 665 // The 3ds_pollfd and the pollfd structures may be different (Windows/Linux have different
666 // sizes)
660 // so we have to copy the data 667 // so we have to copy the data
661 std::vector<pollfd> platform_pollfd(nfds); 668 std::vector<pollfd> platform_pollfd(nfds);
662 std::transform(ctr_fds.begin(), ctr_fds.end(), platform_pollfd.begin(), CTRPollFD::ToPlatform); 669 std::transform(ctr_fds.begin(), ctr_fds.end(), platform_pollfd.begin(), CTRPollFD::ToPlatform);
@@ -664,7 +671,8 @@ static void Poll(Service::Interface* self) {
664 const int ret = ::poll(platform_pollfd.data(), nfds, timeout); 671 const int ret = ::poll(platform_pollfd.data(), nfds, timeout);
665 672
666 // Now update the output pollfd structure 673 // Now update the output pollfd structure
667 std::transform(platform_pollfd.begin(), platform_pollfd.end(), ctr_fds.begin(), CTRPollFD::FromPlatform); 674 std::transform(platform_pollfd.begin(), platform_pollfd.end(), ctr_fds.begin(),
675 CTRPollFD::FromPlatform);
668 676
669 Memory::WriteBlock(output_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD)); 677 Memory::WriteBlock(output_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD));
670 678
@@ -775,7 +783,7 @@ static void Connect(Service::Interface* self) {
775} 783}
776 784
777static void InitializeSockets(Service::Interface* self) { 785static void InitializeSockets(Service::Interface* self) {
778 // TODO(Subv): Implement 786// TODO(Subv): Implement
779#ifdef _WIN32 787#ifdef _WIN32
780 WSADATA data; 788 WSADATA data;
781 WSAStartup(MAKEWORD(2, 2), &data); 789 WSAStartup(MAKEWORD(2, 2), &data);
@@ -808,7 +816,7 @@ static void GetSockOpt(Service::Interface* self) {
808 int ret = -1; 816 int ret = -1;
809 int err = 0; 817 int err = 0;
810 818
811 if(optname < 0) { 819 if (optname < 0) {
812#ifdef _WIN32 820#ifdef _WIN32
813 err = WSAEINVAL; 821 err = WSAEINVAL;
814#else 822#else
@@ -818,7 +826,7 @@ static void GetSockOpt(Service::Interface* self) {
818 // 0x100 = static buffer offset (bytes) 826 // 0x100 = static buffer offset (bytes)
819 // + 0x4 = 2nd pointer (u32) position 827 // + 0x4 = 2nd pointer (u32) position
820 // >> 2 = convert to u32 offset instead of byte offset (cmd_buffer = u32*) 828 // >> 2 = convert to u32 offset instead of byte offset (cmd_buffer = u32*)
821 char* optval = reinterpret_cast<char *>(Memory::GetPointer(cmd_buffer[0x104 >> 2])); 829 char* optval = reinterpret_cast<char*>(Memory::GetPointer(cmd_buffer[0x104 >> 2]));
822 830
823 ret = ::getsockopt(socket_handle, level, optname, optval, &optlen); 831 ret = ::getsockopt(socket_handle, level, optname, optval, &optlen);
824 err = 0; 832 err = 0;
@@ -842,7 +850,7 @@ static void SetSockOpt(Service::Interface* self) {
842 int ret = -1; 850 int ret = -1;
843 int err = 0; 851 int err = 0;
844 852
845 if(optname < 0) { 853 if (optname < 0) {
846#ifdef _WIN32 854#ifdef _WIN32
847 err = WSAEINVAL; 855 err = WSAEINVAL;
848#else 856#else
@@ -850,7 +858,7 @@ static void SetSockOpt(Service::Interface* self) {
850#endif 858#endif
851 } else { 859 } else {
852 socklen_t optlen = static_cast<socklen_t>(cmd_buffer[4]); 860 socklen_t optlen = static_cast<socklen_t>(cmd_buffer[4]);
853 const char* optval = reinterpret_cast<const char *>(Memory::GetPointer(cmd_buffer[8])); 861 const char* optval = reinterpret_cast<const char*>(Memory::GetPointer(cmd_buffer[8]));
854 862
855 ret = static_cast<u32>(::setsockopt(socket_handle, level, optname, optval, optlen)); 863 ret = static_cast<u32>(::setsockopt(socket_handle, level, optname, optval, optlen));
856 err = 0; 864 err = 0;
@@ -865,39 +873,39 @@ static void SetSockOpt(Service::Interface* self) {
865} 873}
866 874
867const Interface::FunctionInfo FunctionTable[] = { 875const Interface::FunctionInfo FunctionTable[] = {
868 {0x00010044, InitializeSockets, "InitializeSockets"}, 876 {0x00010044, InitializeSockets, "InitializeSockets"},
869 {0x000200C2, Socket, "Socket"}, 877 {0x000200C2, Socket, "Socket"},
870 {0x00030082, Listen, "Listen"}, 878 {0x00030082, Listen, "Listen"},
871 {0x00040082, Accept, "Accept"}, 879 {0x00040082, Accept, "Accept"},
872 {0x00050084, Bind, "Bind"}, 880 {0x00050084, Bind, "Bind"},
873 {0x00060084, Connect, "Connect"}, 881 {0x00060084, Connect, "Connect"},
874 {0x00070104, nullptr, "recvfrom_other"}, 882 {0x00070104, nullptr, "recvfrom_other"},
875 {0x00080102, RecvFrom, "RecvFrom"}, 883 {0x00080102, RecvFrom, "RecvFrom"},
876 {0x00090106, nullptr, "sendto_other"}, 884 {0x00090106, nullptr, "sendto_other"},
877 {0x000A0106, SendTo, "SendTo"}, 885 {0x000A0106, SendTo, "SendTo"},
878 {0x000B0042, Close, "Close"}, 886 {0x000B0042, Close, "Close"},
879 {0x000C0082, Shutdown, "Shutdown"}, 887 {0x000C0082, Shutdown, "Shutdown"},
880 {0x000D0082, nullptr, "GetHostByName"}, 888 {0x000D0082, nullptr, "GetHostByName"},
881 {0x000E00C2, nullptr, "GetHostByAddr"}, 889 {0x000E00C2, nullptr, "GetHostByAddr"},
882 {0x000F0106, nullptr, "GetAddrInfo"}, 890 {0x000F0106, nullptr, "GetAddrInfo"},
883 {0x00100102, nullptr, "GetNameInfo"}, 891 {0x00100102, nullptr, "GetNameInfo"},
884 {0x00110102, GetSockOpt, "GetSockOpt"}, 892 {0x00110102, GetSockOpt, "GetSockOpt"},
885 {0x00120104, SetSockOpt, "SetSockOpt"}, 893 {0x00120104, SetSockOpt, "SetSockOpt"},
886 {0x001300C2, Fcntl, "Fcntl"}, 894 {0x001300C2, Fcntl, "Fcntl"},
887 {0x00140084, Poll, "Poll"}, 895 {0x00140084, Poll, "Poll"},
888 {0x00150042, nullptr, "SockAtMark"}, 896 {0x00150042, nullptr, "SockAtMark"},
889 {0x00160000, GetHostId, "GetHostId"}, 897 {0x00160000, GetHostId, "GetHostId"},
890 {0x00170082, GetSockName, "GetSockName"}, 898 {0x00170082, GetSockName, "GetSockName"},
891 {0x00180082, GetPeerName, "GetPeerName"}, 899 {0x00180082, GetPeerName, "GetPeerName"},
892 {0x00190000, ShutdownSockets, "ShutdownSockets"}, 900 {0x00190000, ShutdownSockets, "ShutdownSockets"},
893 {0x001A00C0, nullptr, "GetNetworkOpt"}, 901 {0x001A00C0, nullptr, "GetNetworkOpt"},
894 {0x001B0040, nullptr, "ICMPSocket"}, 902 {0x001B0040, nullptr, "ICMPSocket"},
895 {0x001C0104, nullptr, "ICMPPing"}, 903 {0x001C0104, nullptr, "ICMPPing"},
896 {0x001D0040, nullptr, "ICMPCancel"}, 904 {0x001D0040, nullptr, "ICMPCancel"},
897 {0x001E0040, nullptr, "ICMPClose"}, 905 {0x001E0040, nullptr, "ICMPClose"},
898 {0x001F0040, nullptr, "GetResolverInfo"}, 906 {0x001F0040, nullptr, "GetResolverInfo"},
899 {0x00210002, nullptr, "CloseSockets"}, 907 {0x00210002, nullptr, "CloseSockets"},
900 {0x00230040, nullptr, "AddGlobalSocket"}, 908 {0x00230040, nullptr, "AddGlobalSocket"},
901}; 909};
902 910
903//////////////////////////////////////////////////////////////////////////////////////////////////// 911////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp
index 3c05f836b..fda9d8acf 100644
--- a/src/core/hle/service/srv.cpp
+++ b/src/core/hle/service/srv.cpp
@@ -5,8 +5,8 @@
5#include "common/common_types.h" 5#include "common/common_types.h"
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7 7
8#include "core/hle/service/srv.h"
9#include "core/hle/kernel/event.h" 8#include "core/hle/kernel/event.h"
9#include "core/hle/service/srv.h"
10 10
11//////////////////////////////////////////////////////////////////////////////////////////////////// 11////////////////////////////////////////////////////////////////////////////////////////////////////
12// Namespace SRV 12// Namespace SRV
@@ -28,13 +28,14 @@ static void RegisterClient(Service::Interface* self) {
28 u32* cmd_buff = Kernel::GetCommandBuffer(); 28 u32* cmd_buff = Kernel::GetCommandBuffer();
29 29
30 if (cmd_buff[1] != IPC::CallingPidDesc()) { 30 if (cmd_buff[1] != IPC::CallingPidDesc()) {
31 cmd_buff[0] = IPC::MakeHeader(0x0, 0x1, 0); //0x40 31 cmd_buff[0] = IPC::MakeHeader(0x0, 0x1, 0); // 0x40
32 cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, 32 cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS,
33 ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; 33 ErrorSummary::WrongArgument, ErrorLevel::Permanent)
34 .raw;
34 return; 35 return;
35 } 36 }
36 cmd_buff[0] = IPC::MakeHeader(0x1, 0x1, 0); //0x10040 37 cmd_buff[0] = IPC::MakeHeader(0x1, 0x1, 0); // 0x10040
37 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 38 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
38 LOG_WARNING(Service_SRV, "(STUBBED) called"); 39 LOG_WARNING(Service_SRV, "(STUBBED) called");
39} 40}
40 41
@@ -56,7 +57,7 @@ static void EnableNotification(Service::Interface* self) {
56 event_handle->Clear(); 57 event_handle->Clear();
57 58
58 cmd_buff[0] = IPC::MakeHeader(0x2, 0x1, 0x2); // 0x20042 59 cmd_buff[0] = IPC::MakeHeader(0x2, 0x1, 0x2); // 0x20042
59 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 60 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
60 cmd_buff[2] = IPC::CopyHandleDesc(1); 61 cmd_buff[2] = IPC::CopyHandleDesc(1);
61 cmd_buff[3] = Kernel::g_handle_table.Create(event_handle).MoveFrom(); 62 cmd_buff[3] = Kernel::g_handle_table.Create(event_handle).MoveFrom();
62 LOG_WARNING(Service_SRV, "(STUBBED) called"); 63 LOG_WARNING(Service_SRV, "(STUBBED) called");
@@ -105,7 +106,7 @@ static void Subscribe(Service::Interface* self) {
105 u32 notification_id = cmd_buff[1]; 106 u32 notification_id = cmd_buff[1];
106 107
107 cmd_buff[0] = IPC::MakeHeader(0x9, 0x1, 0); // 0x90040 108 cmd_buff[0] = IPC::MakeHeader(0x9, 0x1, 0); // 0x90040
108 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 109 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
109 LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id); 110 LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id);
110} 111}
111 112
@@ -124,7 +125,7 @@ static void Unsubscribe(Service::Interface* self) {
124 u32 notification_id = cmd_buff[1]; 125 u32 notification_id = cmd_buff[1];
125 126
126 cmd_buff[0] = IPC::MakeHeader(0xA, 0x1, 0); // 0xA0040 127 cmd_buff[0] = IPC::MakeHeader(0xA, 0x1, 0); // 0xA0040
127 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 128 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
128 LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id); 129 LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X", notification_id);
129} 130}
130 131
@@ -145,25 +146,26 @@ static void PublishToSubscriber(Service::Interface* self) {
145 u8 flags = cmd_buff[2] & 0xFF; 146 u8 flags = cmd_buff[2] & 0xFF;
146 147
147 cmd_buff[0] = IPC::MakeHeader(0xC, 0x1, 0); // 0xC0040 148 cmd_buff[0] = IPC::MakeHeader(0xC, 0x1, 0); // 0xC0040
148 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 149 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
149 LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X, flags=%u", notification_id, flags); 150 LOG_WARNING(Service_SRV, "(STUBBED) called, notification_id=0x%X, flags=%u", notification_id,
151 flags);
150} 152}
151 153
152const Interface::FunctionInfo FunctionTable[] = { 154const Interface::FunctionInfo FunctionTable[] = {
153 {0x00010002, RegisterClient, "RegisterClient"}, 155 {0x00010002, RegisterClient, "RegisterClient"},
154 {0x00020000, EnableNotification, "EnableNotification"}, 156 {0x00020000, EnableNotification, "EnableNotification"},
155 {0x00030100, nullptr, "RegisterService"}, 157 {0x00030100, nullptr, "RegisterService"},
156 {0x000400C0, nullptr, "UnregisterService"}, 158 {0x000400C0, nullptr, "UnregisterService"},
157 {0x00050100, GetServiceHandle, "GetServiceHandle"}, 159 {0x00050100, GetServiceHandle, "GetServiceHandle"},
158 {0x000600C2, nullptr, "RegisterPort"}, 160 {0x000600C2, nullptr, "RegisterPort"},
159 {0x000700C0, nullptr, "UnregisterPort"}, 161 {0x000700C0, nullptr, "UnregisterPort"},
160 {0x00080100, nullptr, "GetPort"}, 162 {0x00080100, nullptr, "GetPort"},
161 {0x00090040, Subscribe, "Subscribe"}, 163 {0x00090040, Subscribe, "Subscribe"},
162 {0x000A0040, Unsubscribe, "Unsubscribe"}, 164 {0x000A0040, Unsubscribe, "Unsubscribe"},
163 {0x000B0000, nullptr, "ReceiveNotification"}, 165 {0x000B0000, nullptr, "ReceiveNotification"},
164 {0x000C0080, PublishToSubscriber, "PublishToSubscriber"}, 166 {0x000C0080, PublishToSubscriber, "PublishToSubscriber"},
165 {0x000D0040, nullptr, "PublishAndGetSubscriber"}, 167 {0x000D0040, nullptr, "PublishAndGetSubscriber"},
166 {0x000E00C0, nullptr, "IsServiceRegistered"}, 168 {0x000E00C0, nullptr, "IsServiceRegistered"},
167}; 169};
168 170
169//////////////////////////////////////////////////////////////////////////////////////////////////// 171////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/ssl_c.cpp b/src/core/hle/service/ssl_c.cpp
index a8aff1abf..47c4a8cb0 100644
--- a/src/core/hle/service/ssl_c.cpp
+++ b/src/core/hle/service/ssl_c.cpp
@@ -37,7 +37,8 @@ static void GenerateRandomData(Service::Interface* self) {
37 u32 i = 0; 37 u32 i = 0;
38 while (i < size) { 38 while (i < size) {
39 if ((i % 4) == 0) { 39 if ((i % 4) == 0) {
40 // The random number generator returns 4 bytes worth of data, so generate new random data when i == 0 and when i is divisible by 4 40 // The random number generator returns 4 bytes worth of data, so generate new random
41 // data when i == 0 and when i is divisible by 4
41 data = rand_gen(); 42 data = rand_gen();
42 } 43 }
43 44
@@ -59,27 +60,26 @@ static void GenerateRandomData(Service::Interface* self) {
59} 60}
60 61
61const Interface::FunctionInfo FunctionTable[] = { 62const Interface::FunctionInfo FunctionTable[] = {
62 {0x00010002, Initialize, "Initialize"}, 63 {0x00010002, Initialize, "Initialize"},
63 {0x000200C2, nullptr, "CreateContext"}, 64 {0x000200C2, nullptr, "CreateContext"},
64 {0x00030000, nullptr, "CreateRootCertChain"}, 65 {0x00030000, nullptr, "CreateRootCertChain"},
65 {0x00040040, nullptr, "DestroyRootCertChain"}, 66 {0x00040040, nullptr, "DestroyRootCertChain"},
66 {0x00050082, nullptr, "AddTrustedRootCA"}, 67 {0x00050082, nullptr, "AddTrustedRootCA"},
67 {0x00060080, nullptr, "RootCertChainAddDefaultCert"}, 68 {0x00060080, nullptr, "RootCertChainAddDefaultCert"},
68 {0x00070080, nullptr, "RootCertChainRemoveCert"}, 69 {0x00070080, nullptr, "RootCertChainRemoveCert"},
69 {0x000E0040, nullptr, "OpenDefaultClientCertContext"}, 70 {0x000E0040, nullptr, "OpenDefaultClientCertContext"},
70 {0x000F0040, nullptr, "CloseClientCertContext"}, 71 {0x000F0040, nullptr, "CloseClientCertContext"},
71 {0x00110042, GenerateRandomData, "GenerateRandomData"}, 72 {0x00110042, GenerateRandomData, "GenerateRandomData"},
72 {0x00120042, nullptr, "InitializeConnectionSession"}, 73 {0x00120042, nullptr, "InitializeConnectionSession"},
73 {0x00130040, nullptr, "StartConnection"}, 74 {0x00130040, nullptr, "StartConnection"},
74 {0x00140040, nullptr, "StartConnectionGetOut"}, 75 {0x00140040, nullptr, "StartConnectionGetOut"},
75 {0x00150082, nullptr, "Read"}, 76 {0x00150082, nullptr, "Read"},
76 {0x00170082, nullptr, "Write"}, 77 {0x00170082, nullptr, "Write"},
77 {0x00180080, nullptr, "ContextSetRootCertChain"}, 78 {0x00180080, nullptr, "ContextSetRootCertChain"},
78 {0x00190080, nullptr, "ContextSetClientCert"}, 79 {0x00190080, nullptr, "ContextSetClientCert"},
79 {0x001B0080, nullptr, "ContextClearOpt"}, 80 {0x001B0080, nullptr, "ContextClearOpt"},
80 {0x001E0040, nullptr, "DestroyContext"}, 81 {0x001E0040, nullptr, "DestroyContext"},
81 {0x001F0082, nullptr, "ContextInitSharedmem"} 82 {0x001F0082, nullptr, "ContextInitSharedmem"}};
82};
83 83
84//////////////////////////////////////////////////////////////////////////////////////////////////// 84////////////////////////////////////////////////////////////////////////////////////////////////////
85// Interface class 85// Interface class
diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp
index d16578f87..278548e0e 100644
--- a/src/core/hle/service/y2r_u.cpp
+++ b/src/core/hle/service/y2r_u.cpp
@@ -39,16 +39,16 @@ static u32 transfer_end_interrupt_enabled = 0;
39static u32 spacial_dithering_enabled = 0; 39static u32 spacial_dithering_enabled = 0;
40 40
41static const CoefficientSet standard_coefficients[4] = { 41static const CoefficientSet standard_coefficients[4] = {
42 {{ 0x100, 0x166, 0xB6, 0x58, 0x1C5, -0x166F, 0x10EE, -0x1C5B }}, // ITU_Rec601 42 {{0x100, 0x166, 0xB6, 0x58, 0x1C5, -0x166F, 0x10EE, -0x1C5B}}, // ITU_Rec601
43 {{ 0x100, 0x193, 0x77, 0x2F, 0x1DB, -0x1933, 0xA7C, -0x1D51 }}, // ITU_Rec709 43 {{0x100, 0x193, 0x77, 0x2F, 0x1DB, -0x1933, 0xA7C, -0x1D51}}, // ITU_Rec709
44 {{ 0x12A, 0x198, 0xD0, 0x64, 0x204, -0x1BDE, 0x10F2, -0x229B }}, // ITU_Rec601_Scaling 44 {{0x12A, 0x198, 0xD0, 0x64, 0x204, -0x1BDE, 0x10F2, -0x229B}}, // ITU_Rec601_Scaling
45 {{ 0x12A, 0x1CA, 0x88, 0x36, 0x21C, -0x1F04, 0x99C, -0x2421 }}, // ITU_Rec709_Scaling 45 {{0x12A, 0x1CA, 0x88, 0x36, 0x21C, -0x1F04, 0x99C, -0x2421}}, // ITU_Rec709_Scaling
46}; 46};
47 47
48ResultCode ConversionConfiguration::SetInputLineWidth(u16 width) { 48ResultCode ConversionConfiguration::SetInputLineWidth(u16 width) {
49 if (width == 0 || width > 1024 || width % 8 != 0) { 49 if (width == 0 || width > 1024 || width % 8 != 0) {
50 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM, 50 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM,
51 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD 51 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD
52 } 52 }
53 53
54 // Note: The hardware uses the register value 0 to represent a width of 1024, so for a width of 54 // Note: The hardware uses the register value 0 to represent a width of 1024, so for a width of
@@ -61,7 +61,7 @@ ResultCode ConversionConfiguration::SetInputLineWidth(u16 width) {
61ResultCode ConversionConfiguration::SetInputLines(u16 lines) { 61ResultCode ConversionConfiguration::SetInputLines(u16 lines) {
62 if (lines == 0 || lines > 1024) { 62 if (lines == 0 || lines > 1024) {
63 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM, 63 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::CAM,
64 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD 64 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053FD
65 } 65 }
66 66
67 // Note: In what appears to be a bug, the `camera` module does not set the hardware register at 67 // Note: In what appears to be a bug, the `camera` module does not set the hardware register at
@@ -73,11 +73,12 @@ ResultCode ConversionConfiguration::SetInputLines(u16 lines) {
73 return RESULT_SUCCESS; 73 return RESULT_SUCCESS;
74} 74}
75 75
76ResultCode ConversionConfiguration::SetStandardCoefficient(StandardCoefficient standard_coefficient) { 76ResultCode
77ConversionConfiguration::SetStandardCoefficient(StandardCoefficient standard_coefficient) {
77 size_t index = static_cast<size_t>(standard_coefficient); 78 size_t index = static_cast<size_t>(standard_coefficient);
78 if (index >= ARRAY_SIZE(standard_coefficients)) { 79 if (index >= ARRAY_SIZE(standard_coefficients)) {
79 return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::CAM, 80 return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::CAM,
80 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053ED 81 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E053ED
81 } 82 }
82 83
83 std::memcpy(coefficients.data(), standard_coefficients[index].data(), sizeof(coefficients)); 84 std::memcpy(coefficients.data(), standard_coefficients[index].data(), sizeof(coefficients));
@@ -294,8 +295,10 @@ static void SetSendingY(Service::Interface* self) {
294 cmd_buff[0] = IPC::MakeHeader(0x10, 1, 0); 295 cmd_buff[0] = IPC::MakeHeader(0x10, 1, 0);
295 cmd_buff[1] = RESULT_SUCCESS.raw; 296 cmd_buff[1] = RESULT_SUCCESS.raw;
296 297
297 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, src_process_handle=0x%08X", 298 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, "
298 conversion.src_Y.image_size, conversion.src_Y.transfer_unit, conversion.src_Y.gap, cmd_buff[6]); 299 "src_process_handle=0x%08X",
300 conversion.src_Y.image_size, conversion.src_Y.transfer_unit, conversion.src_Y.gap,
301 cmd_buff[6]);
299} 302}
300 303
301static void SetSendingU(Service::Interface* self) { 304static void SetSendingU(Service::Interface* self) {
@@ -309,8 +312,10 @@ static void SetSendingU(Service::Interface* self) {
309 cmd_buff[0] = IPC::MakeHeader(0x11, 1, 0); 312 cmd_buff[0] = IPC::MakeHeader(0x11, 1, 0);
310 cmd_buff[1] = RESULT_SUCCESS.raw; 313 cmd_buff[1] = RESULT_SUCCESS.raw;
311 314
312 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, src_process_handle=0x%08X", 315 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, "
313 conversion.src_U.image_size, conversion.src_U.transfer_unit, conversion.src_U.gap, cmd_buff[6]); 316 "src_process_handle=0x%08X",
317 conversion.src_U.image_size, conversion.src_U.transfer_unit, conversion.src_U.gap,
318 cmd_buff[6]);
314} 319}
315 320
316static void SetSendingV(Service::Interface* self) { 321static void SetSendingV(Service::Interface* self) {
@@ -324,8 +329,10 @@ static void SetSendingV(Service::Interface* self) {
324 cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0); 329 cmd_buff[0] = IPC::MakeHeader(0x12, 1, 0);
325 cmd_buff[1] = RESULT_SUCCESS.raw; 330 cmd_buff[1] = RESULT_SUCCESS.raw;
326 331
327 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, src_process_handle=0x%08X", 332 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, "
328 conversion.src_V.image_size, conversion.src_V.transfer_unit, conversion.src_V.gap, cmd_buff[6]); 333 "src_process_handle=0x%08X",
334 conversion.src_V.image_size, conversion.src_V.transfer_unit, conversion.src_V.gap,
335 cmd_buff[6]);
329} 336}
330 337
331static void SetSendingYUYV(Service::Interface* self) { 338static void SetSendingYUYV(Service::Interface* self) {
@@ -339,8 +346,10 @@ static void SetSendingYUYV(Service::Interface* self) {
339 cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0); 346 cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0);
340 cmd_buff[1] = RESULT_SUCCESS.raw; 347 cmd_buff[1] = RESULT_SUCCESS.raw;
341 348
342 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, src_process_handle=0x%08X", 349 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, "
343 conversion.src_YUYV.image_size, conversion.src_YUYV.transfer_unit, conversion.src_YUYV.gap, cmd_buff[6]); 350 "src_process_handle=0x%08X",
351 conversion.src_YUYV.image_size, conversion.src_YUYV.transfer_unit,
352 conversion.src_YUYV.gap, cmd_buff[6]);
344} 353}
345 354
346/** 355/**
@@ -418,8 +427,10 @@ static void SetReceiving(Service::Interface* self) {
418 cmd_buff[0] = IPC::MakeHeader(0x18, 1, 0); 427 cmd_buff[0] = IPC::MakeHeader(0x18, 1, 0);
419 cmd_buff[1] = RESULT_SUCCESS.raw; 428 cmd_buff[1] = RESULT_SUCCESS.raw;
420 429
421 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, dst_process_handle=0x%08X", 430 LOG_DEBUG(Service_Y2R, "called image_size=0x%08X, transfer_unit=%hu, transfer_stride=%hu, "
422 conversion.dst.image_size, conversion.dst.transfer_unit, conversion.dst.gap, cmd_buff[6]); 431 "dst_process_handle=0x%08X",
432 conversion.dst.image_size, conversion.dst.transfer_unit, conversion.dst.gap,
433 cmd_buff[6]);
423} 434}
424 435
425/** 436/**
@@ -486,8 +497,8 @@ static void SetCoefficient(Service::Interface* self) {
486 cmd_buff[1] = RESULT_SUCCESS.raw; 497 cmd_buff[1] = RESULT_SUCCESS.raw;
487 498
488 LOG_DEBUG(Service_Y2R, "called coefficients=[%hX, %hX, %hX, %hX, %hX, %hX, %hX, %hX]", 499 LOG_DEBUG(Service_Y2R, "called coefficients=[%hX, %hX, %hX, %hX, %hX, %hX, %hX, %hX]",
489 coefficients[0], coefficients[1], coefficients[2], coefficients[3], 500 coefficients[0], coefficients[1], coefficients[2], coefficients[3], coefficients[4],
490 coefficients[4], coefficients[5], coefficients[6], coefficients[7]); 501 coefficients[5], coefficients[6], coefficients[7]);
491} 502}
492 503
493static void GetCoefficient(Service::Interface* self) { 504static void GetCoefficient(Service::Interface* self) {
@@ -575,8 +586,10 @@ static void StartConversion(Service::Interface* self) {
575 u32* cmd_buff = Kernel::GetCommandBuffer(); 586 u32* cmd_buff = Kernel::GetCommandBuffer();
576 587
577 // dst_image_size would seem to be perfect for this, but it doesn't include the gap :( 588 // dst_image_size would seem to be perfect for this, but it doesn't include the gap :(
578 u32 total_output_size = conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap); 589 u32 total_output_size =
579 Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(conversion.dst.address), total_output_size); 590 conversion.input_lines * (conversion.dst.transfer_unit + conversion.dst.gap);
591 Memory::RasterizerFlushAndInvalidateRegion(
592 Memory::VirtualToPhysicalAddress(conversion.dst.address), total_output_size);
580 593
581 HW::Y2R::PerformConversion(conversion); 594 HW::Y2R::PerformConversion(conversion);
582 595
@@ -648,10 +661,13 @@ cleanup:
648 cmd_buff[0] = IPC::MakeHeader(0x29, 1, 0); 661 cmd_buff[0] = IPC::MakeHeader(0x29, 1, 0);
649 cmd_buff[1] = result.raw; 662 cmd_buff[1] = result.raw;
650 663
651 LOG_DEBUG(Service_Y2R, "called input_format=%hhu output_format=%hhu rotation=%hhu block_alignment=%hhu " 664 LOG_DEBUG(
652 "input_line_width=%hu input_lines=%hu standard_coefficient=%hhu reserved=%hhu alpha=%hX", 665 Service_Y2R,
653 params->input_format, params->output_format, params->rotation, params->block_alignment, 666 "called input_format=%hhu output_format=%hhu rotation=%hhu block_alignment=%hhu "
654 params->input_line_width, params->input_lines, params->standard_coefficient, params->padding, params->alpha); 667 "input_line_width=%hu input_lines=%hu standard_coefficient=%hhu reserved=%hhu alpha=%hX",
668 params->input_format, params->output_format, params->rotation, params->block_alignment,
669 params->input_line_width, params->input_lines, params->standard_coefficient,
670 params->padding, params->alpha);
655} 671}
656 672
657static void PingProcess(Service::Interface* self) { 673static void PingProcess(Service::Interface* self) {
@@ -699,7 +715,6 @@ static void DriverFinalize(Service::Interface* self) {
699 LOG_DEBUG(Service_Y2R, "called"); 715 LOG_DEBUG(Service_Y2R, "called");
700} 716}
701 717
702
703static void GetPackageParameter(Service::Interface* self) { 718static void GetPackageParameter(Service::Interface* self) {
704 u32* cmd_buff = Kernel::GetCommandBuffer(); 719 u32* cmd_buff = Kernel::GetCommandBuffer();
705 720
@@ -711,51 +726,51 @@ static void GetPackageParameter(Service::Interface* self) {
711} 726}
712 727
713const Interface::FunctionInfo FunctionTable[] = { 728const Interface::FunctionInfo FunctionTable[] = {
714 {0x00010040, SetInputFormat, "SetInputFormat"}, 729 {0x00010040, SetInputFormat, "SetInputFormat"},
715 {0x00020000, GetInputFormat, "GetInputFormat"}, 730 {0x00020000, GetInputFormat, "GetInputFormat"},
716 {0x00030040, SetOutputFormat, "SetOutputFormat"}, 731 {0x00030040, SetOutputFormat, "SetOutputFormat"},
717 {0x00040000, GetOutputFormat, "GetOutputFormat"}, 732 {0x00040000, GetOutputFormat, "GetOutputFormat"},
718 {0x00050040, SetRotation, "SetRotation"}, 733 {0x00050040, SetRotation, "SetRotation"},
719 {0x00060000, GetRotation, "GetRotation"}, 734 {0x00060000, GetRotation, "GetRotation"},
720 {0x00070040, SetBlockAlignment, "SetBlockAlignment"}, 735 {0x00070040, SetBlockAlignment, "SetBlockAlignment"},
721 {0x00080000, GetBlockAlignment, "GetBlockAlignment"}, 736 {0x00080000, GetBlockAlignment, "GetBlockAlignment"},
722 {0x00090040, SetSpacialDithering, "SetSpacialDithering"}, 737 {0x00090040, SetSpacialDithering, "SetSpacialDithering"},
723 {0x000A0000, GetSpacialDithering, "GetSpacialDithering"}, 738 {0x000A0000, GetSpacialDithering, "GetSpacialDithering"},
724 {0x000B0040, SetTemporalDithering, "SetTemporalDithering"}, 739 {0x000B0040, SetTemporalDithering, "SetTemporalDithering"},
725 {0x000C0000, GetTemporalDithering, "GetTemporalDithering"}, 740 {0x000C0000, GetTemporalDithering, "GetTemporalDithering"},
726 {0x000D0040, SetTransferEndInterrupt, "SetTransferEndInterrupt"}, 741 {0x000D0040, SetTransferEndInterrupt, "SetTransferEndInterrupt"},
727 {0x000E0000, GetTransferEndInterrupt, "GetTransferEndInterrupt"}, 742 {0x000E0000, GetTransferEndInterrupt, "GetTransferEndInterrupt"},
728 {0x000F0000, GetTransferEndEvent, "GetTransferEndEvent"}, 743 {0x000F0000, GetTransferEndEvent, "GetTransferEndEvent"},
729 {0x00100102, SetSendingY, "SetSendingY"}, 744 {0x00100102, SetSendingY, "SetSendingY"},
730 {0x00110102, SetSendingU, "SetSendingU"}, 745 {0x00110102, SetSendingU, "SetSendingU"},
731 {0x00120102, SetSendingV, "SetSendingV"}, 746 {0x00120102, SetSendingV, "SetSendingV"},
732 {0x00130102, SetSendingYUYV, "SetSendingYUYV"}, 747 {0x00130102, SetSendingYUYV, "SetSendingYUYV"},
733 {0x00140000, IsFinishedSendingYuv, "IsFinishedSendingYuv"}, 748 {0x00140000, IsFinishedSendingYuv, "IsFinishedSendingYuv"},
734 {0x00150000, IsFinishedSendingY, "IsFinishedSendingY"}, 749 {0x00150000, IsFinishedSendingY, "IsFinishedSendingY"},
735 {0x00160000, IsFinishedSendingU, "IsFinishedSendingU"}, 750 {0x00160000, IsFinishedSendingU, "IsFinishedSendingU"},
736 {0x00170000, IsFinishedSendingV, "IsFinishedSendingV"}, 751 {0x00170000, IsFinishedSendingV, "IsFinishedSendingV"},
737 {0x00180102, SetReceiving, "SetReceiving"}, 752 {0x00180102, SetReceiving, "SetReceiving"},
738 {0x00190000, IsFinishedReceiving, "IsFinishedReceiving"}, 753 {0x00190000, IsFinishedReceiving, "IsFinishedReceiving"},
739 {0x001A0040, SetInputLineWidth, "SetInputLineWidth"}, 754 {0x001A0040, SetInputLineWidth, "SetInputLineWidth"},
740 {0x001B0000, GetInputLineWidth, "GetInputLineWidth"}, 755 {0x001B0000, GetInputLineWidth, "GetInputLineWidth"},
741 {0x001C0040, SetInputLines, "SetInputLines"}, 756 {0x001C0040, SetInputLines, "SetInputLines"},
742 {0x001D0000, GetInputLines, "GetInputLines"}, 757 {0x001D0000, GetInputLines, "GetInputLines"},
743 {0x001E0100, SetCoefficient, "SetCoefficient"}, 758 {0x001E0100, SetCoefficient, "SetCoefficient"},
744 {0x001F0000, GetCoefficient, "GetCoefficient"}, 759 {0x001F0000, GetCoefficient, "GetCoefficient"},
745 {0x00200040, SetStandardCoefficient, "SetStandardCoefficient"}, 760 {0x00200040, SetStandardCoefficient, "SetStandardCoefficient"},
746 {0x00210040, GetStandardCoefficient, "GetStandardCoefficient"}, 761 {0x00210040, GetStandardCoefficient, "GetStandardCoefficient"},
747 {0x00220040, SetAlpha, "SetAlpha"}, 762 {0x00220040, SetAlpha, "SetAlpha"},
748 {0x00230000, GetAlpha, "GetAlpha"}, 763 {0x00230000, GetAlpha, "GetAlpha"},
749 {0x00240200, SetDitheringWeightParams,"SetDitheringWeightParams"}, 764 {0x00240200, SetDitheringWeightParams, "SetDitheringWeightParams"},
750 {0x00250000, GetDitheringWeightParams,"GetDitheringWeightParams"}, 765 {0x00250000, GetDitheringWeightParams, "GetDitheringWeightParams"},
751 {0x00260000, StartConversion, "StartConversion"}, 766 {0x00260000, StartConversion, "StartConversion"},
752 {0x00270000, StopConversion, "StopConversion"}, 767 {0x00270000, StopConversion, "StopConversion"},
753 {0x00280000, IsBusyConversion, "IsBusyConversion"}, 768 {0x00280000, IsBusyConversion, "IsBusyConversion"},
754 {0x002901C0, SetPackageParameter, "SetPackageParameter"}, 769 {0x002901C0, SetPackageParameter, "SetPackageParameter"},
755 {0x002A0000, PingProcess, "PingProcess"}, 770 {0x002A0000, PingProcess, "PingProcess"},
756 {0x002B0000, DriverInitialize, "DriverInitialize"}, 771 {0x002B0000, DriverInitialize, "DriverInitialize"},
757 {0x002C0000, DriverFinalize, "DriverFinalize"}, 772 {0x002C0000, DriverFinalize, "DriverFinalize"},
758 {0x002D0000, GetPackageParameter, "GetPackageParameter"}, 773 {0x002D0000, GetPackageParameter, "GetPackageParameter"},
759}; 774};
760 775
761//////////////////////////////////////////////////////////////////////////////////////////////////// 776////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/shared_page.cpp b/src/core/hle/shared_page.cpp
index 4d9272923..453fcf7ec 100644
--- a/src/core/hle/shared_page.cpp
+++ b/src/core/hle/shared_page.cpp
@@ -52,8 +52,8 @@ static u64 GetSystemTime() {
52} 52}
53 53
54static void UpdateTimeCallback(u64 userdata, int cycles_late) { 54static void UpdateTimeCallback(u64 userdata, int cycles_late) {
55 DateTime& date_time = shared_page.date_time_counter % 2 ? 55 DateTime& date_time =
56 shared_page.date_time_0 : shared_page.date_time_1; 56 shared_page.date_time_counter % 2 ? shared_page.date_time_0 : shared_page.date_time_1;
57 57
58 date_time.date_time = GetSystemTime(); 58 date_time.date_time = GetSystemTime();
59 date_time.update_tick = CoreTiming::GetTicks(); 59 date_time.update_tick = CoreTiming::GetTicks();
@@ -74,7 +74,8 @@ void Init() {
74 // Some games wait until this value becomes 0x1, before asking running_hw 74 // Some games wait until this value becomes 0x1, before asking running_hw
75 shared_page.unknown_value = 0x1; 75 shared_page.unknown_value = 0x1;
76 76
77 update_time_event = CoreTiming::RegisterEvent("SharedPage::UpdateTimeCallback", UpdateTimeCallback); 77 update_time_event =
78 CoreTiming::RegisterEvent("SharedPage::UpdateTimeCallback", UpdateTimeCallback);
78 CoreTiming::ScheduleEvent(0, update_time_event); 79 CoreTiming::ScheduleEvent(0, update_time_event);
79} 80}
80 81
diff --git a/src/core/hle/shared_page.h b/src/core/hle/shared_page.h
index cd9246726..b3b10be31 100644
--- a/src/core/hle/shared_page.h
+++ b/src/core/hle/shared_page.h
@@ -32,27 +32,28 @@ static_assert(sizeof(DateTime) == 0x20, "Datetime size is wrong");
32 32
33struct SharedPageDef { 33struct SharedPageDef {
34 // Most of these names are taken from the 3dbrew page linked above. 34 // Most of these names are taken from the 3dbrew page linked above.
35 u32_le date_time_counter; // 0 35 u32_le date_time_counter; // 0
36 u8 running_hw; // 4 36 u8 running_hw; // 4
37 /// "Microcontroller hardware info" 37 /// "Microcontroller hardware info"
38 u8 mcu_hw_info; // 5 38 u8 mcu_hw_info; // 5
39 INSERT_PADDING_BYTES(0x20 - 0x6); // 6 39 INSERT_PADDING_BYTES(0x20 - 0x6); // 6
40 DateTime date_time_0; // 20 40 DateTime date_time_0; // 20
41 DateTime date_time_1; // 40 41 DateTime date_time_1; // 40
42 u8 wifi_macaddr[6]; // 60 42 u8 wifi_macaddr[6]; // 60
43 u8 wifi_link_level; // 66 43 u8 wifi_link_level; // 66
44 u8 wifi_unknown2; // 67 44 u8 wifi_unknown2; // 67
45 INSERT_PADDING_BYTES(0x80 - 0x68); // 68 45 INSERT_PADDING_BYTES(0x80 - 0x68); // 68
46 float_le sliderstate_3d; // 80 46 float_le sliderstate_3d; // 80
47 u8 ledstate_3d; // 84 47 u8 ledstate_3d; // 84
48 INSERT_PADDING_BYTES(1); // 85 48 INSERT_PADDING_BYTES(1); // 85
49 u8 unknown_value; // 86 49 u8 unknown_value; // 86
50 INSERT_PADDING_BYTES(0xA0 - 0x87); // 87 50 INSERT_PADDING_BYTES(0xA0 - 0x87); // 87
51 u64_le menu_title_id; // A0 51 u64_le menu_title_id; // A0
52 u64_le active_menu_title_id; // A8 52 u64_le active_menu_title_id; // A8
53 INSERT_PADDING_BYTES(0x1000 - 0xB0); // B0 53 INSERT_PADDING_BYTES(0x1000 - 0xB0); // B0
54}; 54};
55static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE, "Shared page structure size is wrong"); 55static_assert(sizeof(SharedPageDef) == Memory::SHARED_PAGE_SIZE,
56 "Shared page structure size is wrong");
56 57
57extern SharedPageDef shared_page; 58extern SharedPageDef shared_page;
58 59
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 5d71d5619..9d0a9c54c 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -10,8 +10,8 @@
10#include "common/string_util.h" 10#include "common/string_util.h"
11#include "common/symbols.h" 11#include "common/symbols.h"
12 12
13#include "core/core_timing.h"
14#include "core/arm/arm_interface.h" 13#include "core/arm/arm_interface.h"
14#include "core/core_timing.h"
15 15
16#include "core/hle/kernel/address_arbiter.h" 16#include "core/hle/kernel/address_arbiter.h"
17#include "core/hle/kernel/client_port.h" 17#include "core/hle/kernel/client_port.h"
@@ -40,43 +40,46 @@ using Kernel::ERR_INVALID_HANDLE;
40namespace SVC { 40namespace SVC {
41 41
42const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel, 42const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel,
43 ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA 43 ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA
44const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS, 44const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS,
45 ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E0181E 45 ErrorSummary::InvalidArgument,
46 46 ErrorLevel::Usage); // 0xE0E0181E
47const ResultCode ERR_MISALIGNED_ADDRESS{ // 0xE0E01BF1 47
48 ErrorDescription::MisalignedAddress, ErrorModule::OS, 48const ResultCode ERR_MISALIGNED_ADDRESS{// 0xE0E01BF1
49 ErrorSummary::InvalidArgument, ErrorLevel::Usage}; 49 ErrorDescription::MisalignedAddress, ErrorModule::OS,
50const ResultCode ERR_MISALIGNED_SIZE{ // 0xE0E01BF2 50 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
51 ErrorDescription::MisalignedSize, ErrorModule::OS, 51const ResultCode ERR_MISALIGNED_SIZE{// 0xE0E01BF2
52 ErrorSummary::InvalidArgument, ErrorLevel::Usage}; 52 ErrorDescription::MisalignedSize, ErrorModule::OS,
53const ResultCode ERR_INVALID_COMBINATION{ // 0xE0E01BEE 53 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
54 ErrorDescription::InvalidCombination, ErrorModule::OS, 54const ResultCode ERR_INVALID_COMBINATION{// 0xE0E01BEE
55 ErrorSummary::InvalidArgument, ErrorLevel::Usage}; 55 ErrorDescription::InvalidCombination, ErrorModule::OS,
56 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
56 57
57enum ControlMemoryOperation { 58enum ControlMemoryOperation {
58 MEMOP_FREE = 1, 59 MEMOP_FREE = 1,
59 MEMOP_RESERVE = 2, // This operation seems to be unsupported in the kernel 60 MEMOP_RESERVE = 2, // This operation seems to be unsupported in the kernel
60 MEMOP_COMMIT = 3, 61 MEMOP_COMMIT = 3,
61 MEMOP_MAP = 4, 62 MEMOP_MAP = 4,
62 MEMOP_UNMAP = 5, 63 MEMOP_UNMAP = 5,
63 MEMOP_PROTECT = 6, 64 MEMOP_PROTECT = 6,
64 MEMOP_OPERATION_MASK = 0xFF, 65 MEMOP_OPERATION_MASK = 0xFF,
65 66
66 MEMOP_REGION_APP = 0x100, 67 MEMOP_REGION_APP = 0x100,
67 MEMOP_REGION_SYSTEM = 0x200, 68 MEMOP_REGION_SYSTEM = 0x200,
68 MEMOP_REGION_BASE = 0x300, 69 MEMOP_REGION_BASE = 0x300,
69 MEMOP_REGION_MASK = 0xF00, 70 MEMOP_REGION_MASK = 0xF00,
70 71
71 MEMOP_LINEAR = 0x10000, 72 MEMOP_LINEAR = 0x10000,
72}; 73};
73 74
74/// Map application or GSP heap memory 75/// Map application or GSP heap memory
75static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { 76static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size,
77 u32 permissions) {
76 using namespace Kernel; 78 using namespace Kernel;
77 79
78 LOG_DEBUG(Kernel_SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=0x%X, permissions=0x%08X", 80 LOG_DEBUG(Kernel_SVC,
79 operation, addr0, addr1, size, permissions); 81 "called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=0x%X, permissions=0x%08X",
82 operation, addr0, addr1, size, permissions);
80 83
81 if ((addr0 & Memory::PAGE_MASK) != 0 || (addr1 & Memory::PAGE_MASK) != 0) { 84 if ((addr0 & Memory::PAGE_MASK) != 0 || (addr1 & Memory::PAGE_MASK) != 0) {
82 return ERR_MISALIGNED_ADDRESS; 85 return ERR_MISALIGNED_ADDRESS;
@@ -89,7 +92,8 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
89 operation &= ~MEMOP_REGION_MASK; 92 operation &= ~MEMOP_REGION_MASK;
90 93
91 if (region != 0) { 94 if (region != 0) {
92 LOG_WARNING(Kernel_SVC, "ControlMemory with specified region not supported, region=%X", region); 95 LOG_WARNING(Kernel_SVC, "ControlMemory with specified region not supported, region=%X",
96 region);
93 } 97 }
94 98
95 if ((permissions & (u32)MemoryPermission::ReadWrite) != permissions) { 99 if ((permissions & (u32)MemoryPermission::ReadWrite) != permissions) {
@@ -100,15 +104,17 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
100 auto& process = *g_current_process; 104 auto& process = *g_current_process;
101 105
102 switch (operation & MEMOP_OPERATION_MASK) { 106 switch (operation & MEMOP_OPERATION_MASK) {
103 case MEMOP_FREE: 107 case MEMOP_FREE: {
104 { 108 // TODO(Subv): What happens if an application tries to FREE a block of memory that has a
105 // TODO(Subv): What happens if an application tries to FREE a block of memory that has a SharedMemory pointing to it? 109 // SharedMemory pointing to it?
106 if (addr0 >= Memory::HEAP_VADDR && addr0 < Memory::HEAP_VADDR_END) { 110 if (addr0 >= Memory::HEAP_VADDR && addr0 < Memory::HEAP_VADDR_END) {
107 ResultCode result = process.HeapFree(addr0, size); 111 ResultCode result = process.HeapFree(addr0, size);
108 if (result.IsError()) return result; 112 if (result.IsError())
113 return result;
109 } else if (addr0 >= process.GetLinearHeapBase() && addr0 < process.GetLinearHeapLimit()) { 114 } else if (addr0 >= process.GetLinearHeapBase() && addr0 < process.GetLinearHeapLimit()) {
110 ResultCode result = process.LinearFree(addr0, size); 115 ResultCode result = process.LinearFree(addr0, size);
111 if (result.IsError()) return result; 116 if (result.IsError())
117 return result;
112 } else { 118 } else {
113 return ERR_INVALID_ADDRESS; 119 return ERR_INVALID_ADDRESS;
114 } 120 }
@@ -116,8 +122,7 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
116 break; 122 break;
117 } 123 }
118 124
119 case MEMOP_COMMIT: 125 case MEMOP_COMMIT: {
120 {
121 if (operation & MEMOP_LINEAR) { 126 if (operation & MEMOP_LINEAR) {
122 CASCADE_RESULT(*out_addr, process.LinearAllocate(addr0, size, vma_permissions)); 127 CASCADE_RESULT(*out_addr, process.LinearAllocate(addr0, size, vma_permissions));
123 } else { 128 } else {
@@ -126,23 +131,26 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
126 break; 131 break;
127 } 132 }
128 133
129 case MEMOP_MAP: // TODO: This is just a hack to avoid regressions until memory aliasing is implemented 134 case MEMOP_MAP: // TODO: This is just a hack to avoid regressions until memory aliasing is
130 { 135 // implemented
131 CASCADE_RESULT(*out_addr, process.HeapAllocate(addr0, size, vma_permissions)); 136 {
132 break; 137 CASCADE_RESULT(*out_addr, process.HeapAllocate(addr0, size, vma_permissions));
133 } 138 break;
139 }
134 140
135 case MEMOP_UNMAP: // TODO: This is just a hack to avoid regressions until memory aliasing is implemented 141 case MEMOP_UNMAP: // TODO: This is just a hack to avoid regressions until memory aliasing is
136 { 142 // implemented
137 ResultCode result = process.HeapFree(addr0, size); 143 {
138 if (result.IsError()) return result; 144 ResultCode result = process.HeapFree(addr0, size);
139 break; 145 if (result.IsError())
140 } 146 return result;
147 break;
148 }
141 149
142 case MEMOP_PROTECT: 150 case MEMOP_PROTECT: {
143 {
144 ResultCode result = process.vm_manager.ReprotectRange(addr0, size, vma_permissions); 151 ResultCode result = process.vm_manager.ReprotectRange(addr0, size, vma_permissions);
145 if (result.IsError()) return result; 152 if (result.IsError())
153 return result;
146 break; 154 break;
147 } 155 }
148 156
@@ -161,8 +169,9 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
161 using Kernel::SharedMemory; 169 using Kernel::SharedMemory;
162 using Kernel::MemoryPermission; 170 using Kernel::MemoryPermission;
163 171
164 LOG_TRACE(Kernel_SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", 172 LOG_TRACE(Kernel_SVC,
165 handle, addr, permissions, other_permissions); 173 "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d",
174 handle, addr, permissions, other_permissions);
166 175
167 SharedPtr<SharedMemory> shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle); 176 SharedPtr<SharedMemory> shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle);
168 if (shared_memory == nullptr) 177 if (shared_memory == nullptr)
@@ -179,12 +188,13 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
179 case MemoryPermission::ReadWriteExecute: 188 case MemoryPermission::ReadWriteExecute:
180 case MemoryPermission::DontCare: 189 case MemoryPermission::DontCare:
181 return shared_memory->Map(Kernel::g_current_process.get(), addr, permissions_type, 190 return shared_memory->Map(Kernel::g_current_process.get(), addr, permissions_type,
182 static_cast<MemoryPermission>(other_permissions)); 191 static_cast<MemoryPermission>(other_permissions));
183 default: 192 default:
184 LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); 193 LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions);
185 } 194 }
186 195
187 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 196 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
197 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
188} 198}
189 199
190static ResultCode UnmapMemoryBlock(Handle handle, u32 addr) { 200static ResultCode UnmapMemoryBlock(Handle handle, u32 addr) {
@@ -249,7 +259,7 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
249 return ERR_INVALID_HANDLE; 259 return ERR_INVALID_HANDLE;
250 260
251 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, 261 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle,
252 object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds); 262 object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds);
253 263
254 HLE::Reschedule(__func__); 264 HLE::Reschedule(__func__);
255 265
@@ -257,7 +267,7 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
257 if (object->ShouldWait()) { 267 if (object->ShouldWait()) {
258 268
259 object->AddWaitingThread(thread); 269 object->AddWaitingThread(thread);
260 Kernel::WaitCurrentThread_WaitSynchronization({ object }, false, false); 270 Kernel::WaitCurrentThread_WaitSynchronization({object}, false, false);
261 271
262 // Create an event to wake the thread up after the specified nanosecond delay has passed 272 // Create an event to wake the thread up after the specified nanosecond delay has passed
263 thread->WakeAfterDelay(nano_seconds); 273 thread->WakeAfterDelay(nano_seconds);
@@ -272,7 +282,8 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
272} 282}
273 283
274/// Wait for the given handles to synchronize, timeout after the specified nanoseconds 284/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
275static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, s64 nano_seconds) { 285static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all,
286 s64 nano_seconds) {
276 bool wait_thread = !wait_all; 287 bool wait_thread = !wait_all;
277 int handle_index = 0; 288 int handle_index = 0;
278 Kernel::Thread* thread = Kernel::GetCurrentThread(); 289 Kernel::Thread* thread = Kernel::GetCurrentThread();
@@ -281,7 +292,8 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
281 292
282 // Check if 'handles' is invalid 293 // Check if 'handles' is invalid
283 if (handles == nullptr) 294 if (handles == nullptr)
284 return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 295 return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel,
296 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
285 297
286 // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If 298 // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If
287 // this happens, the running application will crash. 299 // this happens, the running application will crash.
@@ -289,7 +301,8 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
289 301
290 // Check if 'handle_count' is invalid 302 // Check if 'handle_count' is invalid
291 if (handle_count < 0) 303 if (handle_count < 0)
292 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 304 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS,
305 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
293 306
294 // If 'handle_count' is non-zero, iterate through each handle and wait the current thread if 307 // If 'handle_count' is non-zero, iterate through each handle and wait the current thread if
295 // necessary 308 // necessary
@@ -329,7 +342,9 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou
329 } 342 }
330 } 343 }
331 344
332 SCOPE_EXIT({HLE::Reschedule("WaitSynchronizationN");}); // Reschedule after putting the threads to sleep. 345 SCOPE_EXIT({
346 HLE::Reschedule("WaitSynchronizationN");
347 }); // Reschedule after putting the threads to sleep.
333 348
334 // If thread should wait, then set its state to waiting 349 // If thread should wait, then set its state to waiting
335 if (wait_thread) { 350 if (wait_thread) {
@@ -386,18 +401,19 @@ static ResultCode CreateAddressArbiter(Handle* out_handle) {
386} 401}
387 402
388/// Arbitrate address 403/// Arbitrate address
389static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value, s64 nanoseconds) { 404static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value,
405 s64 nanoseconds) {
390 using Kernel::AddressArbiter; 406 using Kernel::AddressArbiter;
391 407
392 LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", handle, 408 LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", handle,
393 address, type, value); 409 address, type, value);
394 410
395 SharedPtr<AddressArbiter> arbiter = Kernel::g_handle_table.Get<AddressArbiter>(handle); 411 SharedPtr<AddressArbiter> arbiter = Kernel::g_handle_table.Get<AddressArbiter>(handle);
396 if (arbiter == nullptr) 412 if (arbiter == nullptr)
397 return ERR_INVALID_HANDLE; 413 return ERR_INVALID_HANDLE;
398 414
399 auto res = arbiter->ArbitrateAddress(static_cast<Kernel::ArbitrationType>(type), 415 auto res = arbiter->ArbitrateAddress(static_cast<Kernel::ArbitrationType>(type), address, value,
400 address, value, nanoseconds); 416 nanoseconds);
401 417
402 return res; 418 return res;
403} 419}
@@ -406,10 +422,18 @@ static void Break(u8 break_reason) {
406 LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!"); 422 LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!");
407 std::string reason_str; 423 std::string reason_str;
408 switch (break_reason) { 424 switch (break_reason) {
409 case 0: reason_str = "PANIC"; break; 425 case 0:
410 case 1: reason_str = "ASSERT"; break; 426 reason_str = "PANIC";
411 case 2: reason_str = "USER"; break; 427 break;
412 default: reason_str = "UNKNOWN"; break; 428 case 1:
429 reason_str = "ASSERT";
430 break;
431 case 2:
432 reason_str = "USER";
433 break;
434 default:
435 reason_str = "UNKNOWN";
436 break;
413 } 437 }
414 LOG_CRITICAL(Debug_Emulated, "Break reason: %s", reason_str.c_str()); 438 LOG_CRITICAL(Debug_Emulated, "Break reason: %s", reason_str.c_str());
415} 439}
@@ -423,7 +447,8 @@ static void OutputDebugString(const char* string) {
423static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle) { 447static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle) {
424 LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); 448 LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle);
425 449
426 SharedPtr<Kernel::Process> process = Kernel::g_handle_table.Get<Kernel::Process>(process_handle); 450 SharedPtr<Kernel::Process> process =
451 Kernel::g_handle_table.Get<Kernel::Process>(process_handle);
427 if (process == nullptr) 452 if (process == nullptr)
428 return ERR_INVALID_HANDLE; 453 return ERR_INVALID_HANDLE;
429 454
@@ -433,12 +458,13 @@ static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle
433} 458}
434 459
435/// Get resource limit current values 460/// Get resource limit current values
436static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit_handle, u32* names, 461static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit_handle,
437 u32 name_count) { 462 u32* names, u32 name_count) {
438 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", 463 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d",
439 resource_limit_handle, names, name_count); 464 resource_limit_handle, names, name_count);
440 465
441 SharedPtr<Kernel::ResourceLimit> resource_limit = Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle); 466 SharedPtr<Kernel::ResourceLimit> resource_limit =
467 Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle);
442 if (resource_limit == nullptr) 468 if (resource_limit == nullptr)
443 return ERR_INVALID_HANDLE; 469 return ERR_INVALID_HANDLE;
444 470
@@ -450,11 +476,12 @@ static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_lim
450 476
451/// Get resource limit max values 477/// Get resource limit max values
452static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit_handle, u32* names, 478static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit_handle, u32* names,
453 u32 name_count) { 479 u32 name_count) {
454 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", 480 LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d",
455 resource_limit_handle, names, name_count); 481 resource_limit_handle, names, name_count);
456 482
457 SharedPtr<Kernel::ResourceLimit> resource_limit = Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle); 483 SharedPtr<Kernel::ResourceLimit> resource_limit =
484 Kernel::g_handle_table.Get<Kernel::ResourceLimit>(resource_limit_handle);
458 if (resource_limit == nullptr) 485 if (resource_limit == nullptr)
459 return ERR_INVALID_HANDLE; 486 return ERR_INVALID_HANDLE;
460 487
@@ -465,7 +492,8 @@ static ResultCode GetResourceLimitLimitValues(s64* values, Handle resource_limit
465} 492}
466 493
467/// Creates a new thread 494/// Creates a new thread
468static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point, u32 arg, u32 stack_top, s32 processor_id) { 495static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point, u32 arg,
496 u32 stack_top, s32 processor_id) {
469 using Kernel::Thread; 497 using Kernel::Thread;
470 498
471 std::string name; 499 std::string name;
@@ -499,20 +527,23 @@ static ResultCode CreateThread(Handle* out_handle, s32 priority, u32 entry_point
499 } 527 }
500 528
501 if (processor_id == THREADPROCESSORID_1 || processor_id == THREADPROCESSORID_ALL || 529 if (processor_id == THREADPROCESSORID_1 || processor_id == THREADPROCESSORID_ALL ||
502 (processor_id == THREADPROCESSORID_DEFAULT && Kernel::g_current_process->ideal_processor == THREADPROCESSORID_1)) { 530 (processor_id == THREADPROCESSORID_DEFAULT &&
503 LOG_WARNING(Kernel_SVC, "Newly created thread is allowed to be run in the SysCore, unimplemented."); 531 Kernel::g_current_process->ideal_processor == THREADPROCESSORID_1)) {
532 LOG_WARNING(Kernel_SVC,
533 "Newly created thread is allowed to be run in the SysCore, unimplemented.");
504 } 534 }
505 535
506 CASCADE_RESULT(SharedPtr<Thread> thread, Kernel::Thread::Create( 536 CASCADE_RESULT(SharedPtr<Thread> thread, Kernel::Thread::Create(name, entry_point, priority,
507 name, entry_point, priority, arg, processor_id, stack_top)); 537 arg, processor_id, stack_top));
508 538
509 thread->context.fpscr = FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO; // 0x03C00000 539 thread->context.fpscr =
540 FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO; // 0x03C00000
510 541
511 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread))); 542 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread)));
512 543
513 LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " 544 LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, "
514 "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, 545 "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X",
515 name.c_str(), arg, stack_top, priority, processor_id, *out_handle); 546 entry_point, name.c_str(), arg, stack_top, priority, processor_id, *out_handle);
516 547
517 return RESULT_SUCCESS; 548 return RESULT_SUCCESS;
518} 549}
@@ -552,7 +583,7 @@ static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) {
552 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex))); 583 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex)));
553 584
554 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", 585 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X",
555 initial_locked ? "true" : "false", *out_handle); 586 initial_locked ? "true" : "false", *out_handle);
556 587
557 return RESULT_SUCCESS; 588 return RESULT_SUCCESS;
558} 589}
@@ -576,7 +607,8 @@ static ResultCode ReleaseMutex(Handle handle) {
576static ResultCode GetProcessId(u32* process_id, Handle process_handle) { 607static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
577 LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle); 608 LOG_TRACE(Kernel_SVC, "called process=0x%08X", process_handle);
578 609
579 const SharedPtr<Kernel::Process> process = Kernel::g_handle_table.Get<Kernel::Process>(process_handle); 610 const SharedPtr<Kernel::Process> process =
611 Kernel::g_handle_table.Get<Kernel::Process>(process_handle);
580 if (process == nullptr) 612 if (process == nullptr)
581 return ERR_INVALID_HANDLE; 613 return ERR_INVALID_HANDLE;
582 614
@@ -588,7 +620,8 @@ static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
588static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) { 620static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) {
589 LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle); 621 LOG_TRACE(Kernel_SVC, "called thread=0x%08X", thread_handle);
590 622
591 const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(thread_handle); 623 const SharedPtr<Kernel::Thread> thread =
624 Kernel::g_handle_table.Get<Kernel::Thread>(thread_handle);
592 if (thread == nullptr) 625 if (thread == nullptr)
593 return ERR_INVALID_HANDLE; 626 return ERR_INVALID_HANDLE;
594 627
@@ -620,7 +653,7 @@ static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max
620 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(semaphore))); 653 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(semaphore)));
621 654
622 LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", 655 LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X",
623 initial_count, max_count, *out_handle); 656 initial_count, max_count, *out_handle);
624 return RESULT_SUCCESS; 657 return RESULT_SUCCESS;
625} 658}
626 659
@@ -640,7 +673,8 @@ static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count)
640} 673}
641 674
642/// Query process memory 675/// Query process memory
643static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info, Handle process_handle, u32 addr) { 676static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info,
677 Handle process_handle, u32 addr) {
644 using Kernel::Process; 678 using Kernel::Process;
645 Kernel::SharedPtr<Process> process = Kernel::g_handle_table.Get<Process>(process_handle); 679 Kernel::SharedPtr<Process> process = Kernel::g_handle_table.Get<Process>(process_handle);
646 if (process == nullptr) 680 if (process == nullptr)
@@ -649,7 +683,8 @@ static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_inf
649 auto vma = process->vm_manager.FindVMA(addr); 683 auto vma = process->vm_manager.FindVMA(addr);
650 684
651 if (vma == Kernel::g_current_process->vm_manager.vma_map.end()) 685 if (vma == Kernel::g_current_process->vm_manager.vma_map.end())
652 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 686 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS,
687 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
653 688
654 memory_info->base_address = vma->second.base; 689 memory_info->base_address = vma->second.base;
655 memory_info->permission = static_cast<u32>(vma->second.permissions); 690 memory_info->permission = static_cast<u32>(vma->second.permissions);
@@ -673,8 +708,8 @@ static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
673 SharedPtr<Event> evt = Event::Create(static_cast<Kernel::ResetType>(reset_type)); 708 SharedPtr<Event> evt = Event::Create(static_cast<Kernel::ResetType>(reset_type));
674 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt))); 709 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt)));
675 710
676 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", 711 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type,
677 reset_type, *out_handle); 712 *out_handle);
678 return RESULT_SUCCESS; 713 return RESULT_SUCCESS;
679} 714}
680 715
@@ -719,8 +754,8 @@ static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) {
719 SharedPtr<Timer> timer = Timer::Create(static_cast<Kernel::ResetType>(reset_type)); 754 SharedPtr<Timer> timer = Timer::Create(static_cast<Kernel::ResetType>(reset_type));
720 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer))); 755 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer)));
721 756
722 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", 757 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", reset_type,
723 reset_type, *out_handle); 758 *out_handle);
724 return RESULT_SUCCESS; 759 return RESULT_SUCCESS;
725} 760}
726 761
@@ -783,17 +818,19 @@ static void SleepThread(s64 nanoseconds) {
783static s64 GetSystemTick() { 818static s64 GetSystemTick() {
784 s64 result = CoreTiming::GetTicks(); 819 s64 result = CoreTiming::GetTicks();
785 // Advance time to defeat dumb games (like Cubic Ninja) that busy-wait for the frame to end. 820 // Advance time to defeat dumb games (like Cubic Ninja) that busy-wait for the frame to end.
786 Core::g_app_core->AddTicks(150); // Measured time between two calls on a 9.2 o3DS with Ninjhax 1.1b 821 Core::g_app_core->AddTicks(
822 150); // Measured time between two calls on a 9.2 o3DS with Ninjhax 1.1b
787 return result; 823 return result;
788} 824}
789 825
790/// Creates a memory block at the specified address with the specified permissions and size 826/// Creates a memory block at the specified address with the specified permissions and size
791static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission, 827static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission,
792 u32 other_permission) { 828 u32 other_permission) {
793 using Kernel::SharedMemory; 829 using Kernel::SharedMemory;
794 830
795 if (size % Memory::PAGE_SIZE != 0) 831 if (size % Memory::PAGE_SIZE != 0)
796 return ResultCode(ErrorDescription::MisalignedSize, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 832 return ResultCode(ErrorDescription::MisalignedSize, ErrorModule::OS,
833 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
797 834
798 SharedPtr<SharedMemory> shared_memory = nullptr; 835 SharedPtr<SharedMemory> shared_memory = nullptr;
799 836
@@ -818,25 +855,29 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
818 ErrorSummary::InvalidArgument, ErrorLevel::Usage); 855 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
819 856
820 if (addr < Memory::PROCESS_IMAGE_VADDR || addr + size > Memory::SHARED_MEMORY_VADDR_END) { 857 if (addr < Memory::PROCESS_IMAGE_VADDR || addr + size > Memory::SHARED_MEMORY_VADDR_END) {
821 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 858 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS,
859 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
822 } 860 }
823 861
824 // When trying to create a memory block with address = 0, 862 // When trying to create a memory block with address = 0,
825 // if the process has the Shared Device Memory flag in the exheader, 863 // if the process has the Shared Device Memory flag in the exheader,
826 // then we have to allocate from the same region as the caller process instead of the BASE region. 864 // then we have to allocate from the same region as the caller process instead of the BASE
865 // region.
827 Kernel::MemoryRegion region = Kernel::MemoryRegion::BASE; 866 Kernel::MemoryRegion region = Kernel::MemoryRegion::BASE;
828 if (addr == 0 && Kernel::g_current_process->flags.shared_device_mem) 867 if (addr == 0 && Kernel::g_current_process->flags.shared_device_mem)
829 region = Kernel::g_current_process->flags.memory_region; 868 region = Kernel::g_current_process->flags.memory_region;
830 869
831 shared_memory = SharedMemory::Create(Kernel::g_current_process, size, 870 shared_memory = SharedMemory::Create(
832 static_cast<MemoryPermission>(my_permission), static_cast<MemoryPermission>(other_permission), addr, region); 871 Kernel::g_current_process, size, static_cast<MemoryPermission>(my_permission),
872 static_cast<MemoryPermission>(other_permission), addr, region);
833 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory))); 873 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory)));
834 874
835 LOG_WARNING(Kernel_SVC, "called addr=0x%08X", addr); 875 LOG_WARNING(Kernel_SVC, "called addr=0x%08X", addr);
836 return RESULT_SUCCESS; 876 return RESULT_SUCCESS;
837} 877}
838 878
839static ResultCode CreatePort(Handle* server_port, Handle* client_port, const char* name, u32 max_sessions) { 879static ResultCode CreatePort(Handle* server_port, Handle* client_port, const char* name,
880 u32 max_sessions) {
840 // TODO(Subv): Implement named ports. 881 // TODO(Subv): Implement named ports.
841 ASSERT_MSG(name == nullptr, "Named ports are currently unimplemented"); 882 ASSERT_MSG(name == nullptr, "Named ports are currently unimplemented");
842 883
@@ -845,9 +886,12 @@ static ResultCode CreatePort(Handle* server_port, Handle* client_port, const cha
845 using Kernel::SharedPtr; 886 using Kernel::SharedPtr;
846 887
847 auto ports = ServerPort::CreatePortPair(max_sessions); 888 auto ports = ServerPort::CreatePortPair(max_sessions);
848 CASCADE_RESULT(*client_port, Kernel::g_handle_table.Create(std::move(std::get<SharedPtr<ClientPort>>(ports)))); 889 CASCADE_RESULT(*client_port, Kernel::g_handle_table.Create(
849 // Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be created. 890 std::move(std::get<SharedPtr<ClientPort>>(ports))));
850 CASCADE_RESULT(*server_port, Kernel::g_handle_table.Create(std::move(std::get<SharedPtr<ServerPort>>(ports)))); 891 // Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be
892 // created.
893 CASCADE_RESULT(*server_port, Kernel::g_handle_table.Create(
894 std::move(std::get<SharedPtr<ServerPort>>(ports))));
851 895
852 LOG_TRACE(Kernel_SVC, "called max_sessions=%u", max_sessions); 896 LOG_TRACE(Kernel_SVC, "called max_sessions=%u", max_sessions);
853 return RESULT_SUCCESS; 897 return RESULT_SUCCESS;
@@ -862,9 +906,9 @@ static ResultCode GetSystemInfo(s64* out, u32 type, s32 param) {
862 case SystemInfoType::REGION_MEMORY_USAGE: 906 case SystemInfoType::REGION_MEMORY_USAGE:
863 switch ((SystemInfoMemUsageRegion)param) { 907 switch ((SystemInfoMemUsageRegion)param) {
864 case SystemInfoMemUsageRegion::ALL: 908 case SystemInfoMemUsageRegion::ALL:
865 *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used 909 *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used +
866 + Kernel::GetMemoryRegion(Kernel::MemoryRegion::SYSTEM)->used 910 Kernel::GetMemoryRegion(Kernel::MemoryRegion::SYSTEM)->used +
867 + Kernel::GetMemoryRegion(Kernel::MemoryRegion::BASE)->used; 911 Kernel::GetMemoryRegion(Kernel::MemoryRegion::BASE)->used;
868 break; 912 break;
869 case SystemInfoMemUsageRegion::APPLICATION: 913 case SystemInfoMemUsageRegion::APPLICATION:
870 *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used; 914 *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used;
@@ -912,7 +956,7 @@ static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) {
912 // TODO(yuriks): Type 0 returns a slightly higher number than type 2, but I'm not sure 956 // TODO(yuriks): Type 0 returns a slightly higher number than type 2, but I'm not sure
913 // what's the difference between them. 957 // what's the difference between them.
914 *out = process->heap_used + process->linear_heap_used + process->misc_memory_used; 958 *out = process->heap_used + process->linear_heap_used + process->misc_memory_used;
915 if(*out % Memory::PAGE_SIZE != 0) { 959 if (*out % Memory::PAGE_SIZE != 0) {
916 LOG_ERROR(Kernel_SVC, "called, memory size not page-aligned"); 960 LOG_ERROR(Kernel_SVC, "called, memory size not page-aligned");
917 return ERR_MISALIGNED_SIZE; 961 return ERR_MISALIGNED_SIZE;
918 } 962 }
@@ -935,12 +979,12 @@ static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) {
935 979
936 if (type >= 21 && type <= 23) { 980 if (type >= 21 && type <= 23) {
937 return ResultCode( // 0xE0E01BF4 981 return ResultCode( // 0xE0E01BF4
938 ErrorDescription::NotImplemented, ErrorModule::OS, 982 ErrorDescription::NotImplemented, ErrorModule::OS, ErrorSummary::InvalidArgument,
939 ErrorSummary::InvalidArgument, ErrorLevel::Usage); 983 ErrorLevel::Usage);
940 } else { 984 } else {
941 return ResultCode( // 0xD8E007ED 985 return ResultCode( // 0xD8E007ED
942 ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, 986 ErrorDescription::InvalidEnumValue, ErrorModule::Kernel,
943 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 987 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
944 } 988 }
945 break; 989 break;
946 } 990 }
@@ -949,142 +993,142 @@ static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) {
949} 993}
950 994
951namespace { 995namespace {
952 struct FunctionDef { 996struct FunctionDef {
953 using Func = void(); 997 using Func = void();
954 998
955 u32 id; 999 u32 id;
956 Func* func; 1000 Func* func;
957 const char* name; 1001 const char* name;
958 }; 1002};
959} 1003}
960 1004
961static const FunctionDef SVC_Table[] = { 1005static const FunctionDef SVC_Table[] = {
962 {0x00, nullptr, "Unknown"}, 1006 {0x00, nullptr, "Unknown"},
963 {0x01, HLE::Wrap<ControlMemory>, "ControlMemory"}, 1007 {0x01, HLE::Wrap<ControlMemory>, "ControlMemory"},
964 {0x02, HLE::Wrap<QueryMemory>, "QueryMemory"}, 1008 {0x02, HLE::Wrap<QueryMemory>, "QueryMemory"},
965 {0x03, nullptr, "ExitProcess"}, 1009 {0x03, nullptr, "ExitProcess"},
966 {0x04, nullptr, "GetProcessAffinityMask"}, 1010 {0x04, nullptr, "GetProcessAffinityMask"},
967 {0x05, nullptr, "SetProcessAffinityMask"}, 1011 {0x05, nullptr, "SetProcessAffinityMask"},
968 {0x06, nullptr, "GetProcessIdealProcessor"}, 1012 {0x06, nullptr, "GetProcessIdealProcessor"},
969 {0x07, nullptr, "SetProcessIdealProcessor"}, 1013 {0x07, nullptr, "SetProcessIdealProcessor"},
970 {0x08, HLE::Wrap<CreateThread>, "CreateThread"}, 1014 {0x08, HLE::Wrap<CreateThread>, "CreateThread"},
971 {0x09, ExitThread, "ExitThread"}, 1015 {0x09, ExitThread, "ExitThread"},
972 {0x0A, HLE::Wrap<SleepThread>, "SleepThread"}, 1016 {0x0A, HLE::Wrap<SleepThread>, "SleepThread"},
973 {0x0B, HLE::Wrap<GetThreadPriority>, "GetThreadPriority"}, 1017 {0x0B, HLE::Wrap<GetThreadPriority>, "GetThreadPriority"},
974 {0x0C, HLE::Wrap<SetThreadPriority>, "SetThreadPriority"}, 1018 {0x0C, HLE::Wrap<SetThreadPriority>, "SetThreadPriority"},
975 {0x0D, nullptr, "GetThreadAffinityMask"}, 1019 {0x0D, nullptr, "GetThreadAffinityMask"},
976 {0x0E, nullptr, "SetThreadAffinityMask"}, 1020 {0x0E, nullptr, "SetThreadAffinityMask"},
977 {0x0F, nullptr, "GetThreadIdealProcessor"}, 1021 {0x0F, nullptr, "GetThreadIdealProcessor"},
978 {0x10, nullptr, "SetThreadIdealProcessor"}, 1022 {0x10, nullptr, "SetThreadIdealProcessor"},
979 {0x11, nullptr, "GetCurrentProcessorNumber"}, 1023 {0x11, nullptr, "GetCurrentProcessorNumber"},
980 {0x12, nullptr, "Run"}, 1024 {0x12, nullptr, "Run"},
981 {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"}, 1025 {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"},
982 {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"}, 1026 {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"},
983 {0x15, HLE::Wrap<CreateSemaphore>, "CreateSemaphore"}, 1027 {0x15, HLE::Wrap<CreateSemaphore>, "CreateSemaphore"},
984 {0x16, HLE::Wrap<ReleaseSemaphore>, "ReleaseSemaphore"}, 1028 {0x16, HLE::Wrap<ReleaseSemaphore>, "ReleaseSemaphore"},
985 {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"}, 1029 {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"},
986 {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"}, 1030 {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"},
987 {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"}, 1031 {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"},
988 {0x1A, HLE::Wrap<CreateTimer>, "CreateTimer"}, 1032 {0x1A, HLE::Wrap<CreateTimer>, "CreateTimer"},
989 {0x1B, HLE::Wrap<SetTimer>, "SetTimer"}, 1033 {0x1B, HLE::Wrap<SetTimer>, "SetTimer"},
990 {0x1C, HLE::Wrap<CancelTimer>, "CancelTimer"}, 1034 {0x1C, HLE::Wrap<CancelTimer>, "CancelTimer"},
991 {0x1D, HLE::Wrap<ClearTimer>, "ClearTimer"}, 1035 {0x1D, HLE::Wrap<ClearTimer>, "ClearTimer"},
992 {0x1E, HLE::Wrap<CreateMemoryBlock>, "CreateMemoryBlock"}, 1036 {0x1E, HLE::Wrap<CreateMemoryBlock>, "CreateMemoryBlock"},
993 {0x1F, HLE::Wrap<MapMemoryBlock>, "MapMemoryBlock"}, 1037 {0x1F, HLE::Wrap<MapMemoryBlock>, "MapMemoryBlock"},
994 {0x20, HLE::Wrap<UnmapMemoryBlock>, "UnmapMemoryBlock"}, 1038 {0x20, HLE::Wrap<UnmapMemoryBlock>, "UnmapMemoryBlock"},
995 {0x21, HLE::Wrap<CreateAddressArbiter>, "CreateAddressArbiter"}, 1039 {0x21, HLE::Wrap<CreateAddressArbiter>, "CreateAddressArbiter"},
996 {0x22, HLE::Wrap<ArbitrateAddress>, "ArbitrateAddress"}, 1040 {0x22, HLE::Wrap<ArbitrateAddress>, "ArbitrateAddress"},
997 {0x23, HLE::Wrap<CloseHandle>, "CloseHandle"}, 1041 {0x23, HLE::Wrap<CloseHandle>, "CloseHandle"},
998 {0x24, HLE::Wrap<WaitSynchronization1>, "WaitSynchronization1"}, 1042 {0x24, HLE::Wrap<WaitSynchronization1>, "WaitSynchronization1"},
999 {0x25, HLE::Wrap<WaitSynchronizationN>, "WaitSynchronizationN"}, 1043 {0x25, HLE::Wrap<WaitSynchronizationN>, "WaitSynchronizationN"},
1000 {0x26, nullptr, "SignalAndWait"}, 1044 {0x26, nullptr, "SignalAndWait"},
1001 {0x27, HLE::Wrap<DuplicateHandle>, "DuplicateHandle"}, 1045 {0x27, HLE::Wrap<DuplicateHandle>, "DuplicateHandle"},
1002 {0x28, HLE::Wrap<GetSystemTick>, "GetSystemTick"}, 1046 {0x28, HLE::Wrap<GetSystemTick>, "GetSystemTick"},
1003 {0x29, nullptr, "GetHandleInfo"}, 1047 {0x29, nullptr, "GetHandleInfo"},
1004 {0x2A, HLE::Wrap<GetSystemInfo>, "GetSystemInfo"}, 1048 {0x2A, HLE::Wrap<GetSystemInfo>, "GetSystemInfo"},
1005 {0x2B, HLE::Wrap<GetProcessInfo>, "GetProcessInfo"}, 1049 {0x2B, HLE::Wrap<GetProcessInfo>, "GetProcessInfo"},
1006 {0x2C, nullptr, "GetThreadInfo"}, 1050 {0x2C, nullptr, "GetThreadInfo"},
1007 {0x2D, HLE::Wrap<ConnectToPort>, "ConnectToPort"}, 1051 {0x2D, HLE::Wrap<ConnectToPort>, "ConnectToPort"},
1008 {0x2E, nullptr, "SendSyncRequest1"}, 1052 {0x2E, nullptr, "SendSyncRequest1"},
1009 {0x2F, nullptr, "SendSyncRequest2"}, 1053 {0x2F, nullptr, "SendSyncRequest2"},
1010 {0x30, nullptr, "SendSyncRequest3"}, 1054 {0x30, nullptr, "SendSyncRequest3"},
1011 {0x31, nullptr, "SendSyncRequest4"}, 1055 {0x31, nullptr, "SendSyncRequest4"},
1012 {0x32, HLE::Wrap<SendSyncRequest>, "SendSyncRequest"}, 1056 {0x32, HLE::Wrap<SendSyncRequest>, "SendSyncRequest"},
1013 {0x33, nullptr, "OpenProcess"}, 1057 {0x33, nullptr, "OpenProcess"},
1014 {0x34, nullptr, "OpenThread"}, 1058 {0x34, nullptr, "OpenThread"},
1015 {0x35, HLE::Wrap<GetProcessId>, "GetProcessId"}, 1059 {0x35, HLE::Wrap<GetProcessId>, "GetProcessId"},
1016 {0x36, HLE::Wrap<GetProcessIdOfThread>, "GetProcessIdOfThread"}, 1060 {0x36, HLE::Wrap<GetProcessIdOfThread>, "GetProcessIdOfThread"},
1017 {0x37, HLE::Wrap<GetThreadId>, "GetThreadId"}, 1061 {0x37, HLE::Wrap<GetThreadId>, "GetThreadId"},
1018 {0x38, HLE::Wrap<GetResourceLimit>, "GetResourceLimit"}, 1062 {0x38, HLE::Wrap<GetResourceLimit>, "GetResourceLimit"},
1019 {0x39, HLE::Wrap<GetResourceLimitLimitValues>, "GetResourceLimitLimitValues"}, 1063 {0x39, HLE::Wrap<GetResourceLimitLimitValues>, "GetResourceLimitLimitValues"},
1020 {0x3A, HLE::Wrap<GetResourceLimitCurrentValues>, "GetResourceLimitCurrentValues"}, 1064 {0x3A, HLE::Wrap<GetResourceLimitCurrentValues>, "GetResourceLimitCurrentValues"},
1021 {0x3B, nullptr, "GetThreadContext"}, 1065 {0x3B, nullptr, "GetThreadContext"},
1022 {0x3C, HLE::Wrap<Break>, "Break"}, 1066 {0x3C, HLE::Wrap<Break>, "Break"},
1023 {0x3D, HLE::Wrap<OutputDebugString>, "OutputDebugString"}, 1067 {0x3D, HLE::Wrap<OutputDebugString>, "OutputDebugString"},
1024 {0x3E, nullptr, "ControlPerformanceCounter"}, 1068 {0x3E, nullptr, "ControlPerformanceCounter"},
1025 {0x3F, nullptr, "Unknown"}, 1069 {0x3F, nullptr, "Unknown"},
1026 {0x40, nullptr, "Unknown"}, 1070 {0x40, nullptr, "Unknown"},
1027 {0x41, nullptr, "Unknown"}, 1071 {0x41, nullptr, "Unknown"},
1028 {0x42, nullptr, "Unknown"}, 1072 {0x42, nullptr, "Unknown"},
1029 {0x43, nullptr, "Unknown"}, 1073 {0x43, nullptr, "Unknown"},
1030 {0x44, nullptr, "Unknown"}, 1074 {0x44, nullptr, "Unknown"},
1031 {0x45, nullptr, "Unknown"}, 1075 {0x45, nullptr, "Unknown"},
1032 {0x46, nullptr, "Unknown"}, 1076 {0x46, nullptr, "Unknown"},
1033 {0x47, HLE::Wrap<CreatePort>, "CreatePort"}, 1077 {0x47, HLE::Wrap<CreatePort>, "CreatePort"},
1034 {0x48, nullptr, "CreateSessionToPort"}, 1078 {0x48, nullptr, "CreateSessionToPort"},
1035 {0x49, nullptr, "CreateSession"}, 1079 {0x49, nullptr, "CreateSession"},
1036 {0x4A, nullptr, "AcceptSession"}, 1080 {0x4A, nullptr, "AcceptSession"},
1037 {0x4B, nullptr, "ReplyAndReceive1"}, 1081 {0x4B, nullptr, "ReplyAndReceive1"},
1038 {0x4C, nullptr, "ReplyAndReceive2"}, 1082 {0x4C, nullptr, "ReplyAndReceive2"},
1039 {0x4D, nullptr, "ReplyAndReceive3"}, 1083 {0x4D, nullptr, "ReplyAndReceive3"},
1040 {0x4E, nullptr, "ReplyAndReceive4"}, 1084 {0x4E, nullptr, "ReplyAndReceive4"},
1041 {0x4F, nullptr, "ReplyAndReceive"}, 1085 {0x4F, nullptr, "ReplyAndReceive"},
1042 {0x50, nullptr, "BindInterrupt"}, 1086 {0x50, nullptr, "BindInterrupt"},
1043 {0x51, nullptr, "UnbindInterrupt"}, 1087 {0x51, nullptr, "UnbindInterrupt"},
1044 {0x52, nullptr, "InvalidateProcessDataCache"}, 1088 {0x52, nullptr, "InvalidateProcessDataCache"},
1045 {0x53, nullptr, "StoreProcessDataCache"}, 1089 {0x53, nullptr, "StoreProcessDataCache"},
1046 {0x54, nullptr, "FlushProcessDataCache"}, 1090 {0x54, nullptr, "FlushProcessDataCache"},
1047 {0x55, nullptr, "StartInterProcessDma"}, 1091 {0x55, nullptr, "StartInterProcessDma"},
1048 {0x56, nullptr, "StopDma"}, 1092 {0x56, nullptr, "StopDma"},
1049 {0x57, nullptr, "GetDmaState"}, 1093 {0x57, nullptr, "GetDmaState"},
1050 {0x58, nullptr, "RestartDma"}, 1094 {0x58, nullptr, "RestartDma"},
1051 {0x59, nullptr, "Unknown"}, 1095 {0x59, nullptr, "Unknown"},
1052 {0x5A, nullptr, "Unknown"}, 1096 {0x5A, nullptr, "Unknown"},
1053 {0x5B, nullptr, "Unknown"}, 1097 {0x5B, nullptr, "Unknown"},
1054 {0x5C, nullptr, "Unknown"}, 1098 {0x5C, nullptr, "Unknown"},
1055 {0x5D, nullptr, "Unknown"}, 1099 {0x5D, nullptr, "Unknown"},
1056 {0x5E, nullptr, "Unknown"}, 1100 {0x5E, nullptr, "Unknown"},
1057 {0x5F, nullptr, "Unknown"}, 1101 {0x5F, nullptr, "Unknown"},
1058 {0x60, nullptr, "DebugActiveProcess"}, 1102 {0x60, nullptr, "DebugActiveProcess"},
1059 {0x61, nullptr, "BreakDebugProcess"}, 1103 {0x61, nullptr, "BreakDebugProcess"},
1060 {0x62, nullptr, "TerminateDebugProcess"}, 1104 {0x62, nullptr, "TerminateDebugProcess"},
1061 {0x63, nullptr, "GetProcessDebugEvent"}, 1105 {0x63, nullptr, "GetProcessDebugEvent"},
1062 {0x64, nullptr, "ContinueDebugEvent"}, 1106 {0x64, nullptr, "ContinueDebugEvent"},
1063 {0x65, nullptr, "GetProcessList"}, 1107 {0x65, nullptr, "GetProcessList"},
1064 {0x66, nullptr, "GetThreadList"}, 1108 {0x66, nullptr, "GetThreadList"},
1065 {0x67, nullptr, "GetDebugThreadContext"}, 1109 {0x67, nullptr, "GetDebugThreadContext"},
1066 {0x68, nullptr, "SetDebugThreadContext"}, 1110 {0x68, nullptr, "SetDebugThreadContext"},
1067 {0x69, nullptr, "QueryDebugProcessMemory"}, 1111 {0x69, nullptr, "QueryDebugProcessMemory"},
1068 {0x6A, nullptr, "ReadProcessMemory"}, 1112 {0x6A, nullptr, "ReadProcessMemory"},
1069 {0x6B, nullptr, "WriteProcessMemory"}, 1113 {0x6B, nullptr, "WriteProcessMemory"},
1070 {0x6C, nullptr, "SetHardwareBreakPoint"}, 1114 {0x6C, nullptr, "SetHardwareBreakPoint"},
1071 {0x6D, nullptr, "GetDebugThreadParam"}, 1115 {0x6D, nullptr, "GetDebugThreadParam"},
1072 {0x6E, nullptr, "Unknown"}, 1116 {0x6E, nullptr, "Unknown"},
1073 {0x6F, nullptr, "Unknown"}, 1117 {0x6F, nullptr, "Unknown"},
1074 {0x70, nullptr, "ControlProcessMemory"}, 1118 {0x70, nullptr, "ControlProcessMemory"},
1075 {0x71, nullptr, "MapProcessMemory"}, 1119 {0x71, nullptr, "MapProcessMemory"},
1076 {0x72, nullptr, "UnmapProcessMemory"}, 1120 {0x72, nullptr, "UnmapProcessMemory"},
1077 {0x73, nullptr, "CreateCodeSet"}, 1121 {0x73, nullptr, "CreateCodeSet"},
1078 {0x74, nullptr, "RandomStub"}, 1122 {0x74, nullptr, "RandomStub"},
1079 {0x75, nullptr, "CreateProcess"}, 1123 {0x75, nullptr, "CreateProcess"},
1080 {0x76, nullptr, "TerminateProcess"}, 1124 {0x76, nullptr, "TerminateProcess"},
1081 {0x77, nullptr, "SetProcessResourceLimits"}, 1125 {0x77, nullptr, "SetProcessResourceLimits"},
1082 {0x78, nullptr, "CreateResourceLimit"}, 1126 {0x78, nullptr, "CreateResourceLimit"},
1083 {0x79, nullptr, "SetResourceLimitValues"}, 1127 {0x79, nullptr, "SetResourceLimitValues"},
1084 {0x7A, nullptr, "AddCodeSegment"}, 1128 {0x7A, nullptr, "AddCodeSegment"},
1085 {0x7B, nullptr, "Backdoor"}, 1129 {0x7B, nullptr, "Backdoor"},
1086 {0x7C, nullptr, "KernelSetState"}, 1130 {0x7C, nullptr, "KernelSetState"},
1087 {0x7D, HLE::Wrap<QueryProcessMemory>, "QueryProcessMemory"}, 1131 {0x7D, HLE::Wrap<QueryProcessMemory>, "QueryProcessMemory"},
1088}; 1132};
1089 1133
1090static const FunctionDef* GetSVCInfo(u32 func_num) { 1134static const FunctionDef* GetSVCInfo(u32 func_num) {