summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar bunnei2016-05-29 21:57:07 -0400
committerGravatar bunnei2016-05-29 21:57:07 -0400
commitab4b27f0f5760c7f378f29756d3ce631bafca1b2 (patch)
tree6340ca66710e9603db24c051da0b8173b796d3c6 /src/core
parentMerge pull request #1756 from wwylele/config-cleanup (diff)
parentMemory: Handle RasterizerCachedMemory and RasterizerCachedSpecial page types ... (diff)
downloadyuzu-ab4b27f0f5760c7f378f29756d3ce631bafca1b2.tar.gz
yuzu-ab4b27f0f5760c7f378f29756d3ce631bafca1b2.tar.xz
yuzu-ab4b27f0f5760c7f378f29756d3ce631bafca1b2.zip
Merge pull request #1692 from Subv/rm_getpointer2
Memory: Remove most usages of GetPointer
Diffstat (limited to 'src/core')
-rw-r--r--src/core/file_sys/archive_backend.cpp12
-rw-r--r--src/core/hle/applets/mii_selector.cpp21
-rw-r--r--src/core/hle/applets/mii_selector.h4
-rw-r--r--src/core/hle/applets/swkbd.cpp17
-rw-r--r--src/core/hle/kernel/thread.cpp2
-rw-r--r--src/core/hle/service/apt/apt.cpp25
-rw-r--r--src/core/hle/service/apt/apt.h6
-rw-r--r--src/core/hle/service/cfg/cfg.cpp16
-rw-r--r--src/core/hle/service/dsp_dsp.cpp17
-rw-r--r--src/core/hle/service/frd/frd.cpp10
-rw-r--r--src/core/hle/service/fs/archive.cpp22
-rw-r--r--src/core/hle/service/gsp_gpu.cpp83
-rw-r--r--src/core/hle/service/soc_u.cpp100
-rw-r--r--src/core/hle/service/ssl_c.cpp7
-rw-r--r--src/core/memory.cpp236
-rw-r--r--src/core/memory.h8
-rw-r--r--src/core/mmio.h6
17 files changed, 454 insertions, 138 deletions
diff --git a/src/core/file_sys/archive_backend.cpp b/src/core/file_sys/archive_backend.cpp
index 97adf0e12..cc0aa7022 100644
--- a/src/core/file_sys/archive_backend.cpp
+++ b/src/core/file_sys/archive_backend.cpp
@@ -19,22 +19,22 @@ Path::Path(LowPathType type, u32 size, u32 pointer) : type(type) {
19 switch (type) { 19 switch (type) {
20 case Binary: 20 case Binary:
21 { 21 {
22 u8* data = Memory::GetPointer(pointer); 22 binary.resize(size);
23 binary = std::vector<u8>(data, data + size); 23 Memory::ReadBlock(pointer, binary.data(), binary.size());
24 break; 24 break;
25 } 25 }
26 26
27 case Char: 27 case Char:
28 { 28 {
29 const char* data = reinterpret_cast<const char*>(Memory::GetPointer(pointer)); 29 string.resize(size - 1); // Data is always null-terminated.
30 string = std::string(data, size - 1); // Data is always null-terminated. 30 Memory::ReadBlock(pointer, &string[0], string.size());
31 break; 31 break;
32 } 32 }
33 33
34 case Wchar: 34 case Wchar:
35 { 35 {
36 const char16_t* data = reinterpret_cast<const char16_t*>(Memory::GetPointer(pointer)); 36 u16str.resize(size / 2 - 1); // Data is always null-terminated.
37 u16str = std::u16string(data, size/2 - 1); // Data is always null-terminated. 37 Memory::ReadBlock(pointer, &u16str[0], u16str.size() * sizeof(char16_t));
38 break; 38 break;
39 } 39 }
40 40
diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp
index bf39eca22..77f01d208 100644
--- a/src/core/hle/applets/mii_selector.cpp
+++ b/src/core/hle/applets/mii_selector.cpp
@@ -32,9 +32,9 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p
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 memory.
33 // Create the SharedMemory that will hold the framebuffer data 33 // Create the SharedMemory that will hold the framebuffer data
34 Service::APT::CaptureBufferInfo capture_info; 34 Service::APT::CaptureBufferInfo capture_info;
35 ASSERT(sizeof(capture_info) == parameter.buffer_size); 35 ASSERT(sizeof(capture_info) == parameter.buffer.size());
36 36
37 memcpy(&capture_info, parameter.data, sizeof(capture_info)); 37 memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info));
38 38
39 using Kernel::MemoryPermission; 39 using Kernel::MemoryPermission;
40 // Allocate a heap block of the required size for this applet. 40 // Allocate a heap block of the required size for this applet.
@@ -47,8 +47,7 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p
47 // Send the response message with the newly created SharedMemory 47 // Send the response message with the newly created SharedMemory
48 Service::APT::MessageParameter result; 48 Service::APT::MessageParameter result;
49 result.signal = static_cast<u32>(Service::APT::SignalType::LibAppFinished); 49 result.signal = static_cast<u32>(Service::APT::SignalType::LibAppFinished);
50 result.data = nullptr; 50 result.buffer.clear();
51 result.buffer_size = 0;
52 result.destination_id = static_cast<u32>(Service::APT::AppletId::Application); 51 result.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
53 result.sender_id = static_cast<u32>(id); 52 result.sender_id = static_cast<u32>(id);
54 result.object = framebuffer_memory; 53 result.object = framebuffer_memory;
@@ -63,15 +62,17 @@ ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& pa
63 // TODO(Subv): Set the expected fields in the response buffer before resending it to the application. 62 // TODO(Subv): Set the expected fields in the response buffer before resending it to the application.
64 // TODO(Subv): Reverse the parameter format for the Mii Selector 63 // TODO(Subv): Reverse the parameter format for the Mii Selector
65 64
66 if(parameter.buffer_size >= sizeof(u32)) { 65 memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
67 // TODO: defaults return no error, but garbage in other unknown fields 66
68 memset(parameter.data, 0, sizeof(u32)); 67 // TODO(Subv): Find more about this structure, result code 0 is enough to let most games continue.
69 } 68 MiiResult result;
69 memset(&result, 0, sizeof(result));
70 result.result_code = 0;
70 71
71 // Let the application know that we're closing 72 // Let the application know that we're closing
72 Service::APT::MessageParameter message; 73 Service::APT::MessageParameter message;
73 message.buffer_size = parameter.buffer_size; 74 message.buffer.resize(sizeof(MiiResult));
74 message.data = parameter.data; 75 std::memcpy(message.buffer.data(), &result, message.buffer.size());
75 message.signal = static_cast<u32>(Service::APT::SignalType::LibAppClosed); 76 message.signal = static_cast<u32>(Service::APT::SignalType::LibAppClosed);
76 message.destination_id = static_cast<u32>(Service::APT::AppletId::Application); 77 message.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
77 message.sender_id = static_cast<u32>(id); 78 message.sender_id = static_cast<u32>(id);
diff --git a/src/core/hle/applets/mii_selector.h b/src/core/hle/applets/mii_selector.h
index be6b04642..24e8e721d 100644
--- a/src/core/hle/applets/mii_selector.h
+++ b/src/core/hle/applets/mii_selector.h
@@ -24,7 +24,7 @@ struct MiiConfig {
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(0x8C - 0xA); 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;
@@ -75,6 +75,8 @@ public:
75 75
76 /// Whether this applet is currently running instead of the host application or not. 76 /// Whether this applet is currently running instead of the host application or not.
77 bool started; 77 bool started;
78
79 MiiConfig config;
78}; 80};
79 81
80} 82}
diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp
index 90c6adc65..d87bf3d57 100644
--- a/src/core/hle/applets/swkbd.cpp
+++ b/src/core/hle/applets/swkbd.cpp
@@ -35,9 +35,9 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con
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 memory.
36 // Create the SharedMemory that will hold the framebuffer data 36 // Create the SharedMemory that will hold the framebuffer data
37 Service::APT::CaptureBufferInfo capture_info; 37 Service::APT::CaptureBufferInfo capture_info;
38 ASSERT(sizeof(capture_info) == parameter.buffer_size); 38 ASSERT(sizeof(capture_info) == parameter.buffer.size());
39 39
40 memcpy(&capture_info, parameter.data, sizeof(capture_info)); 40 memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info));
41 41
42 using Kernel::MemoryPermission; 42 using Kernel::MemoryPermission;
43 // Allocate a heap block of the required size for this applet. 43 // Allocate a heap block of the required size for this applet.
@@ -50,8 +50,7 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con
50 // Send the response message with the newly created SharedMemory 50 // Send the response message with the newly created SharedMemory
51 Service::APT::MessageParameter result; 51 Service::APT::MessageParameter result;
52 result.signal = static_cast<u32>(Service::APT::SignalType::LibAppFinished); 52 result.signal = static_cast<u32>(Service::APT::SignalType::LibAppFinished);
53 result.data = nullptr; 53 result.buffer.clear();
54 result.buffer_size = 0;
55 result.destination_id = static_cast<u32>(Service::APT::AppletId::Application); 54 result.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
56 result.sender_id = static_cast<u32>(id); 55 result.sender_id = static_cast<u32>(id);
57 result.object = framebuffer_memory; 56 result.object = framebuffer_memory;
@@ -61,9 +60,9 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con
61} 60}
62 61
63ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter const& parameter) { 62ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter const& parameter) {
64 ASSERT_MSG(parameter.buffer_size == sizeof(config), "The size of the parameter (SoftwareKeyboardConfig) is wrong"); 63 ASSERT_MSG(parameter.buffer.size() == sizeof(config), "The size of the parameter (SoftwareKeyboardConfig) is wrong");
65 64
66 memcpy(&config, parameter.data, parameter.buffer_size); 65 memcpy(&config, parameter.buffer.data(), parameter.buffer.size());
67 text_memory = boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object); 66 text_memory = boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object);
68 67
69 // TODO(Subv): Verify if this is the correct behavior 68 // TODO(Subv): Verify if this is the correct behavior
@@ -99,7 +98,7 @@ void SoftwareKeyboard::DrawScreenKeyboard() {
99 auto info = bottom_screen->framebuffer_info[bottom_screen->index]; 98 auto info = bottom_screen->framebuffer_info[bottom_screen->index];
100 99
101 // TODO(Subv): Draw the HLE keyboard, for now just zero-fill the framebuffer 100 // TODO(Subv): Draw the HLE keyboard, for now just zero-fill the framebuffer
102 memset(Memory::GetPointer(info.address_left), 0, info.stride * 320); 101 Memory::ZeroBlock(info.address_left, info.stride * 320);
103 102
104 GSP_GPU::SetBufferSwap(1, info); 103 GSP_GPU::SetBufferSwap(1, info);
105} 104}
@@ -107,8 +106,8 @@ void SoftwareKeyboard::DrawScreenKeyboard() {
107void SoftwareKeyboard::Finalize() { 106void SoftwareKeyboard::Finalize() {
108 // Let the application know that we're closing 107 // Let the application know that we're closing
109 Service::APT::MessageParameter message; 108 Service::APT::MessageParameter message;
110 message.buffer_size = sizeof(SoftwareKeyboardConfig); 109 message.buffer.resize(sizeof(SoftwareKeyboardConfig));
111 message.data = reinterpret_cast<u8*>(&config); 110 std::memcpy(message.buffer.data(), &config, message.buffer.size());
112 message.signal = static_cast<u32>(Service::APT::SignalType::LibAppClosed); 111 message.signal = static_cast<u32>(Service::APT::SignalType::LibAppClosed);
113 message.destination_id = static_cast<u32>(Service::APT::AppletId::Application); 112 message.destination_id = static_cast<u32>(Service::APT::AppletId::Application);
114 message.sender_id = static_cast<u32>(id); 113 message.sender_id = static_cast<u32>(id);
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 43def6146..3f6bec5fa 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -403,7 +403,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
403 priority = new_priority; 403 priority = new_priority;
404 } 404 }
405 405
406 if (!Memory::GetPointer(entry_point)) { 406 if (!Memory::IsValidVirtualAddress(entry_point)) {
407 LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point); 407 LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point);
408 // TODO: Verify error 408 // TODO: Verify error
409 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, 409 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index bbf170b71..1e54a53dd 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -180,12 +180,12 @@ void SendParameter(Service::Interface* self) {
180 } 180 }
181 181
182 MessageParameter param; 182 MessageParameter param;
183 param.buffer_size = buffer_size;
184 param.destination_id = dst_app_id; 183 param.destination_id = dst_app_id;
185 param.sender_id = src_app_id; 184 param.sender_id = src_app_id;
186 param.object = Kernel::g_handle_table.GetGeneric(handle); 185 param.object = Kernel::g_handle_table.GetGeneric(handle);
187 param.signal = signal_type; 186 param.signal = signal_type;
188 param.data = Memory::GetPointer(buffer); 187 param.buffer.resize(buffer_size);
188 Memory::ReadBlock(buffer, param.buffer.data(), param.buffer.size());
189 189
190 cmd_buff[1] = dest_applet->ReceiveParameter(param).raw; 190 cmd_buff[1] = dest_applet->ReceiveParameter(param).raw;
191 191
@@ -203,16 +203,15 @@ void ReceiveParameter(Service::Interface* self) {
203 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 203 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
204 cmd_buff[2] = next_parameter.sender_id; 204 cmd_buff[2] = next_parameter.sender_id;
205 cmd_buff[3] = next_parameter.signal; // Signal type 205 cmd_buff[3] = next_parameter.signal; // Signal type
206 cmd_buff[4] = next_parameter.buffer_size; // Parameter buffer size 206 cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size
207 cmd_buff[5] = 0x10; 207 cmd_buff[5] = 0x10;
208 cmd_buff[6] = 0; 208 cmd_buff[6] = 0;
209 if (next_parameter.object != nullptr) 209 if (next_parameter.object != nullptr)
210 cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom(); 210 cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom();
211 cmd_buff[7] = (next_parameter.buffer_size << 14) | 2; 211 cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2;
212 cmd_buff[8] = buffer; 212 cmd_buff[8] = buffer;
213 213
214 if (next_parameter.data) 214 Memory::WriteBlock(buffer, next_parameter.buffer.data(), next_parameter.buffer.size());
215 memcpy(Memory::GetPointer(buffer), next_parameter.data, std::min(buffer_size, next_parameter.buffer_size));
216 215
217 LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); 216 LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size);
218} 217}
@@ -226,16 +225,15 @@ void GlanceParameter(Service::Interface* self) {
226 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 225 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
227 cmd_buff[2] = next_parameter.sender_id; 226 cmd_buff[2] = next_parameter.sender_id;
228 cmd_buff[3] = next_parameter.signal; // Signal type 227 cmd_buff[3] = next_parameter.signal; // Signal type
229 cmd_buff[4] = next_parameter.buffer_size; // Parameter buffer size 228 cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size
230 cmd_buff[5] = 0x10; 229 cmd_buff[5] = 0x10;
231 cmd_buff[6] = 0; 230 cmd_buff[6] = 0;
232 if (next_parameter.object != nullptr) 231 if (next_parameter.object != nullptr)
233 cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom(); 232 cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom();
234 cmd_buff[7] = (next_parameter.buffer_size << 14) | 2; 233 cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2;
235 cmd_buff[8] = buffer; 234 cmd_buff[8] = buffer;
236 235
237 if (next_parameter.data) 236 Memory::WriteBlock(buffer, next_parameter.buffer.data(), std::min(static_cast<size_t>(buffer_size), next_parameter.buffer.size()));
238 memcpy(Memory::GetPointer(buffer), next_parameter.data, std::min(buffer_size, next_parameter.buffer_size));
239 237
240 LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); 238 LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size);
241} 239}
@@ -373,10 +371,13 @@ void StartLibraryApplet(Service::Interface* self) {
373 return; 371 return;
374 } 372 }
375 373
374 size_t buffer_size = cmd_buff[2];
375 VAddr buffer_addr = cmd_buff[6];
376
376 AppletStartupParameter parameter; 377 AppletStartupParameter parameter;
377 parameter.buffer_size = cmd_buff[2];
378 parameter.object = Kernel::g_handle_table.GetGeneric(cmd_buff[4]); 378 parameter.object = Kernel::g_handle_table.GetGeneric(cmd_buff[4]);
379 parameter.data = Memory::GetPointer(cmd_buff[6]); 379 parameter.buffer.resize(buffer_size);
380 Memory::ReadBlock(buffer_addr, parameter.buffer.data(), parameter.buffer.size());
380 381
381 cmd_buff[1] = applet->Start(parameter).raw; 382 cmd_buff[1] = applet->Start(parameter).raw;
382} 383}
diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h
index ed7c47cca..76b3a3807 100644
--- a/src/core/hle/service/apt/apt.h
+++ b/src/core/hle/service/apt/apt.h
@@ -20,16 +20,14 @@ struct MessageParameter {
20 u32 sender_id = 0; 20 u32 sender_id = 0;
21 u32 destination_id = 0; 21 u32 destination_id = 0;
22 u32 signal = 0; 22 u32 signal = 0;
23 u32 buffer_size = 0;
24 Kernel::SharedPtr<Kernel::Object> object = nullptr; 23 Kernel::SharedPtr<Kernel::Object> object = nullptr;
25 u8* data = nullptr; 24 std::vector<u8> buffer;
26}; 25};
27 26
28/// Holds information about the parameters used in StartLibraryApplet 27/// Holds information about the parameters used in StartLibraryApplet
29struct AppletStartupParameter { 28struct AppletStartupParameter {
30 u32 buffer_size = 0;
31 Kernel::SharedPtr<Kernel::Object> object = nullptr; 29 Kernel::SharedPtr<Kernel::Object> object = nullptr;
32 u8* data = nullptr; 30 std::vector<u8> buffer;
33}; 31};
34 32
35/// Used by the application to pass information about the current framebuffer to applets. 33/// Used by the application to pass information about the current framebuffer to applets.
diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp
index acc509cb0..e067db645 100644
--- a/src/core/hle/service/cfg/cfg.cpp
+++ b/src/core/hle/service/cfg/cfg.cpp
@@ -196,28 +196,32 @@ void GetConfigInfoBlk2(Service::Interface* self) {
196 u32* cmd_buff = Kernel::GetCommandBuffer(); 196 u32* cmd_buff = Kernel::GetCommandBuffer();
197 u32 size = cmd_buff[1]; 197 u32 size = cmd_buff[1];
198 u32 block_id = cmd_buff[2]; 198 u32 block_id = cmd_buff[2];
199 u8* data_pointer = Memory::GetPointer(cmd_buff[4]); 199 VAddr data_pointer = cmd_buff[4];
200 200
201 if (data_pointer == nullptr) { 201 if (!Memory::IsValidVirtualAddress(data_pointer)) {
202 cmd_buff[1] = -1; // TODO(Subv): Find the right error code 202 cmd_buff[1] = -1; // TODO(Subv): Find the right error code
203 return; 203 return;
204 } 204 }
205 205
206 cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x2, data_pointer).raw; 206 std::vector<u8> data(size);
207 cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x2, data.data()).raw;
208 Memory::WriteBlock(data_pointer, data.data(), data.size());
207} 209}
208 210
209void GetConfigInfoBlk8(Service::Interface* self) { 211void GetConfigInfoBlk8(Service::Interface* self) {
210 u32* cmd_buff = Kernel::GetCommandBuffer(); 212 u32* cmd_buff = Kernel::GetCommandBuffer();
211 u32 size = cmd_buff[1]; 213 u32 size = cmd_buff[1];
212 u32 block_id = cmd_buff[2]; 214 u32 block_id = cmd_buff[2];
213 u8* data_pointer = Memory::GetPointer(cmd_buff[4]); 215 VAddr data_pointer = cmd_buff[4];
214 216
215 if (data_pointer == nullptr) { 217 if (!Memory::IsValidVirtualAddress(data_pointer)) {
216 cmd_buff[1] = -1; // TODO(Subv): Find the right error code 218 cmd_buff[1] = -1; // TODO(Subv): Find the right error code
217 return; 219 return;
218 } 220 }
219 221
220 cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x8, data_pointer).raw; 222 std::vector<u8> data(size);
223 cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x8, data.data()).raw;
224 Memory::WriteBlock(data_pointer, data.data(), data.size());
221} 225}
222 226
223void UpdateConfigNANDSavegame(Service::Interface* self) { 227void UpdateConfigNANDSavegame(Service::Interface* self) {
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp
index 10730d7ac..c8aadd9db 100644
--- a/src/core/hle/service/dsp_dsp.cpp
+++ b/src/core/hle/service/dsp_dsp.cpp
@@ -140,12 +140,15 @@ static void LoadComponent(Service::Interface* self) {
140 140
141 // TODO(bunnei): Implement real DSP firmware loading 141 // TODO(bunnei): Implement real DSP firmware loading
142 142
143 ASSERT(Memory::GetPointer(buffer) != nullptr); 143 ASSERT(Memory::IsValidVirtualAddress(buffer));
144 ASSERT(size > 0x37C); 144
145 std::vector<u8> component_data(size);
146 Memory::ReadBlock(buffer, component_data.data(), component_data.size());
145 147
146 LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64, Common::ComputeHash64(Memory::GetPointer(buffer), size)); 148 LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64, Common::ComputeHash64(component_data.data(), component_data.size()));
147 // Some versions of the firmware have the location of DSP structures listed here. 149 // Some versions of the firmware have the location of DSP structures listed here.
148 LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64, Common::ComputeHash64(Memory::GetPointer(buffer) + 0x340, 60)); 150 ASSERT(size > 0x37C);
151 LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64, Common::ComputeHash64(component_data.data() + 0x340, 60));
149 152
150 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, "(STUBBED) called size=0x%X, prog_mask=0x%08X, data_mask=0x%08X, buffer=0x%08X",
151 size, prog_mask, data_mask, buffer); 154 size, prog_mask, data_mask, buffer);
@@ -285,7 +288,7 @@ static void WriteProcessPipe(Service::Interface* self) {
285 return; 288 return;
286 } 289 }
287 290
288 ASSERT_MSG(Memory::GetPointer(buffer) != nullptr, "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe_index, size, buffer); 291 ASSERT_MSG(Memory::IsValidVirtualAddress(buffer), "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer);
289 292
290 std::vector<u8> message(size); 293 std::vector<u8> message(size);
291 for (u32 i = 0; i < size; i++) { 294 for (u32 i = 0; i < size; i++) {
@@ -324,7 +327,7 @@ static void ReadPipeIfPossible(Service::Interface* self) {
324 327
325 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); 328 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index);
326 329
327 ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe_index, unknown, size, addr); 330 ASSERT_MSG(Memory::IsValidVirtualAddress(addr), "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr);
328 331
329 cmd_buff[0] = IPC::MakeHeader(0x10, 1, 2); 332 cmd_buff[0] = IPC::MakeHeader(0x10, 1, 2);
330 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 333 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
@@ -364,7 +367,7 @@ static void ReadPipe(Service::Interface* self) {
364 367
365 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); 368 DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index);
366 369
367 ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe_index, unknown, size, addr); 370 ASSERT_MSG(Memory::IsValidVirtualAddress(addr), "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr);
368 371
369 if (DSP::HLE::GetPipeReadableSize(pipe) >= size) { 372 if (DSP::HLE::GetPipeReadableSize(pipe) >= size) {
370 std::vector<u8> response = DSP::HLE::PipeRead(pipe, size); 373 std::vector<u8> response = DSP::HLE::PipeRead(pipe, size);
diff --git a/src/core/hle/service/frd/frd.cpp b/src/core/hle/service/frd/frd.cpp
index 15d604bb6..29d144365 100644
--- a/src/core/hle/service/frd/frd.cpp
+++ b/src/core/hle/service/frd/frd.cpp
@@ -23,7 +23,7 @@ void GetMyPresence(Service::Interface* self) {
23 23
24 ASSERT(shifted_out_size == ((sizeof(MyPresence) << 14) | 2)); 24 ASSERT(shifted_out_size == ((sizeof(MyPresence) << 14) | 2));
25 25
26 Memory::WriteBlock(my_presence_addr, reinterpret_cast<const u8*>(&my_presence), sizeof(MyPresence)); 26 Memory::WriteBlock(my_presence_addr, &my_presence, sizeof(MyPresence));
27 27
28 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 28 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
29 29
@@ -39,8 +39,7 @@ void GetFriendKeyList(Service::Interface* self) {
39 39
40 FriendKey zero_key = {}; 40 FriendKey zero_key = {};
41 for (u32 i = 0; i < frd_count; ++i) { 41 for (u32 i = 0; i < frd_count; ++i) {
42 Memory::WriteBlock(frd_key_addr + i * sizeof(FriendKey), 42 Memory::WriteBlock(frd_key_addr + i * sizeof(FriendKey), &zero_key, sizeof(FriendKey));
43 reinterpret_cast<const u8*>(&zero_key), sizeof(FriendKey));
44 } 43 }
45 44
46 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 45 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
@@ -58,8 +57,7 @@ void GetFriendProfile(Service::Interface* self) {
58 57
59 Profile zero_profile = {}; 58 Profile zero_profile = {};
60 for (u32 i = 0; i < count; ++i) { 59 for (u32 i = 0; i < count; ++i) {
61 Memory::WriteBlock(profiles_addr + i * sizeof(Profile), 60 Memory::WriteBlock(profiles_addr + i * sizeof(Profile), &zero_profile, sizeof(Profile));
62 reinterpret_cast<const u8*>(&zero_profile), sizeof(Profile));
63 } 61 }
64 62
65 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 63 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
@@ -88,7 +86,7 @@ void GetMyFriendKey(Service::Interface* self) {
88 u32* cmd_buff = Kernel::GetCommandBuffer(); 86 u32* cmd_buff = Kernel::GetCommandBuffer();
89 87
90 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 88 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
91 Memory::WriteBlock(cmd_buff[2], reinterpret_cast<const u8*>(&my_friend_key), sizeof(FriendKey)); 89 Memory::WriteBlock(cmd_buff[2], &my_friend_key, sizeof(FriendKey));
92 LOG_WARNING(Service_FRD, "(STUBBED) called"); 90 LOG_WARNING(Service_FRD, "(STUBBED) called");
93} 91}
94 92
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index cc51ede0c..81b9abe4c 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -108,13 +108,14 @@ ResultVal<bool> File::SyncRequest() {
108 offset, length, backend->GetSize()); 108 offset, length, backend->GetSize());
109 } 109 }
110 110
111 ResultVal<size_t> read = backend->Read(offset, length, Memory::GetPointer(address)); 111 std::vector<u8> data(length);
112 ResultVal<size_t> read = backend->Read(offset, data.size(), data.data());
112 if (read.Failed()) { 113 if (read.Failed()) {
113 cmd_buff[1] = read.Code().raw; 114 cmd_buff[1] = read.Code().raw;
114 return read.Code(); 115 return read.Code();
115 } 116 }
117 Memory::WriteBlock(address, data.data(), *read);
116 cmd_buff[2] = static_cast<u32>(*read); 118 cmd_buff[2] = static_cast<u32>(*read);
117 Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(address), length);
118 break; 119 break;
119 } 120 }
120 121
@@ -128,7 +129,9 @@ ResultVal<bool> File::SyncRequest() {
128 LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x", 129 LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x",
129 GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush); 130 GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush);
130 131
131 ResultVal<size_t> written = backend->Write(offset, length, flush != 0, Memory::GetPointer(address)); 132 std::vector<u8> data(length);
133 Memory::ReadBlock(address, data.data(), data.size());
134 ResultVal<size_t> written = backend->Write(offset, data.size(), flush != 0, data.data());
132 if (written.Failed()) { 135 if (written.Failed()) {
133 cmd_buff[1] = written.Code().raw; 136 cmd_buff[1] = written.Code().raw;
134 return written.Code(); 137 return written.Code();
@@ -216,12 +219,14 @@ ResultVal<bool> Directory::SyncRequest() {
216 { 219 {
217 u32 count = cmd_buff[1]; 220 u32 count = cmd_buff[1];
218 u32 address = cmd_buff[3]; 221 u32 address = cmd_buff[3];
219 auto entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); 222 std::vector<FileSys::Entry> entries(count);
220 LOG_TRACE(Service_FS, "Read %s %s: count=%d", 223 LOG_TRACE(Service_FS, "Read %s %s: count=%d",
221 GetTypeName().c_str(), GetName().c_str(), count); 224 GetTypeName().c_str(), GetName().c_str(), count);
222 225
223 // Number of entries actually read 226 // Number of entries actually read
224 cmd_buff[2] = backend->Read(count, entries); 227 u32 read = backend->Read(entries.size(), entries.data());
228 cmd_buff[2] = read;
229 Memory::WriteBlock(address, entries.data(), read * sizeof(FileSys::Entry));
225 break; 230 break;
226 } 231 }
227 232
@@ -456,11 +461,12 @@ ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon
456 if (result.IsError()) 461 if (result.IsError())
457 return result; 462 return result;
458 463
459 u8* smdh_icon = Memory::GetPointer(icon_buffer); 464 if (!Memory::IsValidVirtualAddress(icon_buffer))
460 if (!smdh_icon)
461 return ResultCode(-1); // TODO(Subv): Find the right error code 465 return ResultCode(-1); // TODO(Subv): Find the right error code
462 466
463 ext_savedata->WriteIcon(path, smdh_icon, icon_size); 467 std::vector<u8> smdh_icon(icon_size);
468 Memory::ReadBlock(icon_buffer, smdh_icon.data(), smdh_icon.size());
469 ext_savedata->WriteIcon(path, smdh_icon.data(), smdh_icon.size());
464 return RESULT_SUCCESS; 470 return RESULT_SUCCESS;
465} 471}
466 472
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 8ded9b09b..f3c7b7df3 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -66,14 +66,26 @@ static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) {
66} 66}
67 67
68/** 68/**
69 * Writes a single GSP GPU hardware registers with a single u32 value
70 * (For internal use.)
71 *
72 * @param base_address The address of the register in question
73 * @param data Data to be written
74 */
75static 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");
77 HW::Write<u32>(base_address + REGS_BEGIN, data);
78}
79
80/**
69 * Writes sequential GSP GPU hardware registers using an array of source data 81 * Writes sequential GSP GPU hardware registers using an array of source data
70 * 82 *
71 * @param base_address The address of the first register in the sequence 83 * @param base_address The address of the first register in the sequence
72 * @param size_in_bytes The number of registers to update (size of data) 84 * @param size_in_bytes The number of registers to update (size of data)
73 * @param data A pointer to the source data 85 * @param data_vaddr A pointer to the source data
74 * @return RESULT_SUCCESS if the parameters are valid, error code otherwise 86 * @return RESULT_SUCCESS if the parameters are valid, error code otherwise
75 */ 87 */
76static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) { 88static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, VAddr data_vaddr) {
77 // This magic number is verified to be done by the gsp module 89 // This magic number is verified to be done by the gsp module
78 const u32 max_size_in_bytes = 0x80; 90 const u32 max_size_in_bytes = 0x80;
79 91
@@ -87,10 +99,10 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* da
87 return ERR_GSP_REGS_MISALIGNED; 99 return ERR_GSP_REGS_MISALIGNED;
88 } else { 100 } else {
89 while (size_in_bytes > 0) { 101 while (size_in_bytes > 0) {
90 HW::Write<u32>(base_address + REGS_BEGIN, *data); 102 WriteSingleHWReg(base_address, Memory::Read32(data_vaddr));
91 103
92 size_in_bytes -= 4; 104 size_in_bytes -= 4;
93 ++data; 105 data_vaddr += 4;
94 base_address += 4; 106 base_address += 4;
95 } 107 }
96 return RESULT_SUCCESS; 108 return RESULT_SUCCESS;
@@ -112,7 +124,7 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* da
112 * @param masks A pointer to the masks 124 * @param masks A pointer to the masks
113 * @return RESULT_SUCCESS if the parameters are valid, error code otherwise 125 * @return RESULT_SUCCESS if the parameters are valid, error code otherwise
114 */ 126 */
115static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, const u32* data, const u32* masks) { 127static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, VAddr data_vaddr, VAddr masks_vaddr) {
116 // This magic number is verified to be done by the gsp module 128 // This magic number is verified to be done by the gsp module
117 const u32 max_size_in_bytes = 0x80; 129 const u32 max_size_in_bytes = 0x80;
118 130
@@ -131,14 +143,17 @@ static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, const
131 u32 reg_value; 143 u32 reg_value;
132 HW::Read<u32>(reg_value, reg_address); 144 HW::Read<u32>(reg_value, reg_address);
133 145
146 u32 data = Memory::Read32(data_vaddr);
147 u32 mask = Memory::Read32(masks_vaddr);
148
134 // Update the current value of the register only for set mask bits 149 // Update the current value of the register only for set mask bits
135 reg_value = (reg_value & ~*masks) | (*data | *masks); 150 reg_value = (reg_value & ~mask) | (data | mask);
136 151
137 HW::Write<u32>(reg_address, reg_value); 152 WriteSingleHWReg(base_address, reg_value);
138 153
139 size_in_bytes -= 4; 154 size_in_bytes -= 4;
140 ++data; 155 data_vaddr += 4;
141 ++masks; 156 masks_vaddr += 4;
142 base_address += 4; 157 base_address += 4;
143 } 158 }
144 return RESULT_SUCCESS; 159 return RESULT_SUCCESS;
@@ -164,8 +179,7 @@ static void WriteHWRegs(Service::Interface* self) {
164 u32* cmd_buff = Kernel::GetCommandBuffer(); 179 u32* cmd_buff = Kernel::GetCommandBuffer();
165 u32 reg_addr = cmd_buff[1]; 180 u32 reg_addr = cmd_buff[1];
166 u32 size = cmd_buff[2]; 181 u32 size = cmd_buff[2];
167 182 VAddr src = cmd_buff[4];
168 u32* src = (u32*)Memory::GetPointer(cmd_buff[4]);
169 183
170 cmd_buff[1] = WriteHWRegs(reg_addr, size, src).raw; 184 cmd_buff[1] = WriteHWRegs(reg_addr, size, src).raw;
171} 185}
@@ -186,8 +200,8 @@ static void WriteHWRegsWithMask(Service::Interface* self) {
186 u32 reg_addr = cmd_buff[1]; 200 u32 reg_addr = cmd_buff[1];
187 u32 size = cmd_buff[2]; 201 u32 size = cmd_buff[2];
188 202
189 u32* src_data = (u32*)Memory::GetPointer(cmd_buff[4]); 203 VAddr src_data = cmd_buff[4];
190 u32* mask_data = (u32*)Memory::GetPointer(cmd_buff[6]); 204 VAddr mask_data = cmd_buff[6];
191 205
192 cmd_buff[1] = WriteHWRegsWithMask(reg_addr, size, src_data, mask_data).raw; 206 cmd_buff[1] = WriteHWRegsWithMask(reg_addr, size, src_data, mask_data).raw;
193} 207}
@@ -210,13 +224,16 @@ static void ReadHWRegs(Service::Interface* self) {
210 return; 224 return;
211 } 225 }
212 226
213 u32* dst = (u32*)Memory::GetPointer(cmd_buff[0x41]); 227 VAddr dst_vaddr = cmd_buff[0x41];
214 228
215 while (size > 0) { 229 while (size > 0) {
216 HW::Read<u32>(*dst, reg_addr + REGS_BEGIN); 230 u32 value;
231 HW::Read<u32>(value, reg_addr + REGS_BEGIN);
232
233 Memory::Write32(dst_vaddr, value);
217 234
218 size -= 4; 235 size -= 4;
219 ++dst; 236 dst_vaddr += 4;
220 reg_addr += 4; 237 reg_addr += 4;
221 } 238 }
222} 239}
@@ -226,22 +243,22 @@ ResultCode SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) {
226 PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left); 243 PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left);
227 PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right); 244 PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right);
228 if (info.active_fb == 0) { 245 if (info.active_fb == 0) {
229 WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), 246 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)),
230 4, &phys_address_left); 247 phys_address_left);
231 WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), 248 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)),
232 4, &phys_address_right); 249 phys_address_right);
233 } else { 250 } else {
234 WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), 251 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)),
235 4, &phys_address_left); 252 phys_address_left);
236 WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), 253 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)),
237 4, &phys_address_right); 254 phys_address_right);
238 } 255 }
239 WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), 256 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)),
240 4, &info.stride); 257 info.stride);
241 WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), 258 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)),
242 4, &info.format); 259 info.format);
243 WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), 260 WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)),
244 4, &info.shown_fb); 261 info.shown_fb);
245 262
246 if (Pica::g_debug_context) 263 if (Pica::g_debug_context)
247 Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr); 264 Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr);
@@ -432,9 +449,9 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
432 Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(command.dma_request.dest_address), 449 Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(command.dma_request.dest_address),
433 command.dma_request.size); 450 command.dma_request.size);
434 451
435 memcpy(Memory::GetPointer(command.dma_request.dest_address), 452 // TODO(Subv): These memory accesses should not go through the application's memory mapping.
436 Memory::GetPointer(command.dma_request.source_address), 453 // They should go through the GSP module's memory mapping.
437 command.dma_request.size); 454 Memory::CopyBlock(command.dma_request.dest_address, command.dma_request.source_address, command.dma_request.size);
438 SignalInterrupt(InterruptId::DMA); 455 SignalInterrupt(InterruptId::DMA);
439 break; 456 break;
440 } 457 }
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp
index d3e5d4bca..9b285567b 100644
--- a/src/core/hle/service/soc_u.cpp
+++ b/src/core/hle/service/soc_u.cpp
@@ -373,14 +373,18 @@ static void Bind(Service::Interface* self) {
373 u32* cmd_buffer = Kernel::GetCommandBuffer(); 373 u32* cmd_buffer = Kernel::GetCommandBuffer();
374 u32 socket_handle = cmd_buffer[1]; 374 u32 socket_handle = cmd_buffer[1];
375 u32 len = cmd_buffer[2]; 375 u32 len = cmd_buffer[2];
376 CTRSockAddr* ctr_sock_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[6]));
377 376
378 if (ctr_sock_addr == nullptr) { 377 // Virtual address of the sock_addr structure
378 VAddr sock_addr_addr = cmd_buffer[6];
379 if (!Memory::IsValidVirtualAddress(sock_addr_addr)) {
379 cmd_buffer[1] = -1; // TODO(Subv): Correct code 380 cmd_buffer[1] = -1; // TODO(Subv): Correct code
380 return; 381 return;
381 } 382 }
382 383
383 sockaddr sock_addr = CTRSockAddr::ToPlatform(*ctr_sock_addr); 384 CTRSockAddr ctr_sock_addr;
385 Memory::ReadBlock(sock_addr_addr, reinterpret_cast<u8*>(&ctr_sock_addr), sizeof(CTRSockAddr));
386
387 sockaddr sock_addr = CTRSockAddr::ToPlatform(ctr_sock_addr);
384 388
385 int res = ::bind(socket_handle, &sock_addr, std::max<u32>(sizeof(sock_addr), len)); 389 int res = ::bind(socket_handle, &sock_addr, std::max<u32>(sizeof(sock_addr), len));
386 390
@@ -496,7 +500,7 @@ static void Accept(Service::Interface* self) {
496 result = TranslateError(GET_ERRNO); 500 result = TranslateError(GET_ERRNO);
497 } else { 501 } else {
498 CTRSockAddr ctr_addr = CTRSockAddr::FromPlatform(addr); 502 CTRSockAddr ctr_addr = CTRSockAddr::FromPlatform(addr);
499 Memory::WriteBlock(cmd_buffer[0x104 >> 2], (const u8*)&ctr_addr, max_addr_len); 503 Memory::WriteBlock(cmd_buffer[0x104 >> 2], &ctr_addr, sizeof(ctr_addr));
500 } 504 }
501 505
502 cmd_buffer[0] = IPC::MakeHeader(4, 2, 2); 506 cmd_buffer[0] = IPC::MakeHeader(4, 2, 2);
@@ -547,20 +551,31 @@ static void SendTo(Service::Interface* self) {
547 u32 flags = cmd_buffer[3]; 551 u32 flags = cmd_buffer[3];
548 u32 addr_len = cmd_buffer[4]; 552 u32 addr_len = cmd_buffer[4];
549 553
550 u8* input_buff = Memory::GetPointer(cmd_buffer[8]); 554 VAddr input_buff_address = cmd_buffer[8];
551 CTRSockAddr* ctr_dest_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[10])); 555 if (!Memory::IsValidVirtualAddress(input_buff_address)) {
556 cmd_buffer[1] = -1; // TODO(Subv): Find the right error code
557 return;
558 }
552 559
553 if (ctr_dest_addr == nullptr) { 560 // Memory address of the dest_addr structure
561 VAddr dest_addr_addr = cmd_buffer[10];
562 if (!Memory::IsValidVirtualAddress(dest_addr_addr)) {
554 cmd_buffer[1] = -1; // TODO(Subv): Find the right error code 563 cmd_buffer[1] = -1; // TODO(Subv): Find the right error code
555 return; 564 return;
556 } 565 }
557 566
567 std::vector<u8> input_buff(len);
568 Memory::ReadBlock(input_buff_address, input_buff.data(), input_buff.size());
569
570 CTRSockAddr ctr_dest_addr;
571 Memory::ReadBlock(dest_addr_addr, &ctr_dest_addr, sizeof(ctr_dest_addr));
572
558 int ret = -1; 573 int ret = -1;
559 if (addr_len > 0) { 574 if (addr_len > 0) {
560 sockaddr dest_addr = CTRSockAddr::ToPlatform(*ctr_dest_addr); 575 sockaddr dest_addr = CTRSockAddr::ToPlatform(ctr_dest_addr);
561 ret = ::sendto(socket_handle, (const char*)input_buff, len, flags, &dest_addr, sizeof(dest_addr)); 576 ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags, &dest_addr, sizeof(dest_addr));
562 } else { 577 } else {
563 ret = ::sendto(socket_handle, (const char*)input_buff, len, flags, nullptr, 0); 578 ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags, nullptr, 0);
564 } 579 }
565 580
566 int result = 0; 581 int result = 0;
@@ -591,14 +606,24 @@ static void RecvFrom(Service::Interface* self) {
591 606
592 std::memcpy(&buffer_parameters, &cmd_buffer[64], sizeof(buffer_parameters)); 607 std::memcpy(&buffer_parameters, &cmd_buffer[64], sizeof(buffer_parameters));
593 608
594 u8* output_buff = Memory::GetPointer(buffer_parameters.output_buffer_addr); 609 if (!Memory::IsValidVirtualAddress(buffer_parameters.output_buffer_addr)) {
610 cmd_buffer[1] = -1; // TODO(Subv): Find the right error code
611 return;
612 }
613
614 if (!Memory::IsValidVirtualAddress(buffer_parameters.output_src_address_buffer)) {
615 cmd_buffer[1] = -1; // TODO(Subv): Find the right error code
616 return;
617 }
618
619 std::vector<u8> output_buff(len);
595 sockaddr src_addr; 620 sockaddr src_addr;
596 socklen_t src_addr_len = sizeof(src_addr); 621 socklen_t src_addr_len = sizeof(src_addr);
597 int ret = ::recvfrom(socket_handle, (char*)output_buff, len, flags, &src_addr, &src_addr_len); 622 int ret = ::recvfrom(socket_handle, reinterpret_cast<char*>(output_buff.data()), len, flags, &src_addr, &src_addr_len);
598 623
599 if (ret >= 0 && buffer_parameters.output_src_address_buffer != 0 && src_addr_len > 0) { 624 if (ret >= 0 && buffer_parameters.output_src_address_buffer != 0 && src_addr_len > 0) {
600 CTRSockAddr* ctr_src_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(buffer_parameters.output_src_address_buffer)); 625 CTRSockAddr ctr_src_addr = CTRSockAddr::FromPlatform(src_addr);
601 *ctr_src_addr = CTRSockAddr::FromPlatform(src_addr); 626 Memory::WriteBlock(buffer_parameters.output_src_address_buffer, &ctr_src_addr, sizeof(ctr_src_addr));
602 } 627 }
603 628
604 int result = 0; 629 int result = 0;
@@ -606,6 +631,9 @@ static void RecvFrom(Service::Interface* self) {
606 if (ret == SOCKET_ERROR_VALUE) { 631 if (ret == SOCKET_ERROR_VALUE) {
607 result = TranslateError(GET_ERRNO); 632 result = TranslateError(GET_ERRNO);
608 total_received = 0; 633 total_received = 0;
634 } else {
635 // 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);
609 } 637 }
610 638
611 cmd_buffer[1] = result; 639 cmd_buffer[1] = result;
@@ -617,18 +645,28 @@ static void Poll(Service::Interface* self) {
617 u32* cmd_buffer = Kernel::GetCommandBuffer(); 645 u32* cmd_buffer = Kernel::GetCommandBuffer();
618 u32 nfds = cmd_buffer[1]; 646 u32 nfds = cmd_buffer[1];
619 int timeout = cmd_buffer[2]; 647 int timeout = cmd_buffer[2];
620 CTRPollFD* input_fds = reinterpret_cast<CTRPollFD*>(Memory::GetPointer(cmd_buffer[6])); 648
621 CTRPollFD* output_fds = reinterpret_cast<CTRPollFD*>(Memory::GetPointer(cmd_buffer[0x104 >> 2])); 649 VAddr input_fds_addr = cmd_buffer[6];
650 VAddr output_fds_addr = cmd_buffer[0x104 >> 2];
651 if (!Memory::IsValidVirtualAddress(input_fds_addr) || !Memory::IsValidVirtualAddress(output_fds_addr)) {
652 cmd_buffer[1] = -1; // TODO(Subv): Find correct error code.
653 return;
654 }
655
656 std::vector<CTRPollFD> ctr_fds(nfds);
657 Memory::ReadBlock(input_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD));
622 658
623 // The 3ds_pollfd and the pollfd structures may be different (Windows/Linux have different sizes) 659 // The 3ds_pollfd and the pollfd structures may be different (Windows/Linux have different sizes)
624 // so we have to copy the data 660 // so we have to copy the data
625 std::vector<pollfd> platform_pollfd(nfds); 661 std::vector<pollfd> platform_pollfd(nfds);
626 std::transform(input_fds, input_fds + nfds, platform_pollfd.begin(), CTRPollFD::ToPlatform); 662 std::transform(ctr_fds.begin(), ctr_fds.end(), platform_pollfd.begin(), CTRPollFD::ToPlatform);
627 663
628 const int ret = ::poll(platform_pollfd.data(), nfds, timeout); 664 const int ret = ::poll(platform_pollfd.data(), nfds, timeout);
629 665
630 // Now update the output pollfd structure 666 // Now update the output pollfd structure
631 std::transform(platform_pollfd.begin(), platform_pollfd.end(), output_fds, CTRPollFD::FromPlatform); 667 std::transform(platform_pollfd.begin(), platform_pollfd.end(), ctr_fds.begin(), CTRPollFD::FromPlatform);
668
669 Memory::WriteBlock(output_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD));
632 670
633 int result = 0; 671 int result = 0;
634 if (ret == SOCKET_ERROR_VALUE) 672 if (ret == SOCKET_ERROR_VALUE)
@@ -643,14 +681,16 @@ static void GetSockName(Service::Interface* self) {
643 u32 socket_handle = cmd_buffer[1]; 681 u32 socket_handle = cmd_buffer[1];
644 socklen_t ctr_len = cmd_buffer[2]; 682 socklen_t ctr_len = cmd_buffer[2];
645 683
646 CTRSockAddr* ctr_dest_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[0x104 >> 2])); 684 // Memory address of the ctr_dest_addr structure
685 VAddr ctr_dest_addr_addr = cmd_buffer[0x104 >> 2];
647 686
648 sockaddr dest_addr; 687 sockaddr dest_addr;
649 socklen_t dest_addr_len = sizeof(dest_addr); 688 socklen_t dest_addr_len = sizeof(dest_addr);
650 int ret = ::getsockname(socket_handle, &dest_addr, &dest_addr_len); 689 int ret = ::getsockname(socket_handle, &dest_addr, &dest_addr_len);
651 690
652 if (ctr_dest_addr != nullptr) { 691 if (ctr_dest_addr_addr != 0 && Memory::IsValidVirtualAddress(ctr_dest_addr_addr)) {
653 *ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); 692 CTRSockAddr ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr);
693 Memory::WriteBlock(ctr_dest_addr_addr, &ctr_dest_addr, sizeof(ctr_dest_addr));
654 } else { 694 } else {
655 cmd_buffer[1] = -1; // TODO(Subv): Verify error 695 cmd_buffer[1] = -1; // TODO(Subv): Verify error
656 return; 696 return;
@@ -682,14 +722,16 @@ static void GetPeerName(Service::Interface* self) {
682 u32 socket_handle = cmd_buffer[1]; 722 u32 socket_handle = cmd_buffer[1];
683 socklen_t len = cmd_buffer[2]; 723 socklen_t len = cmd_buffer[2];
684 724
685 CTRSockAddr* ctr_dest_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[0x104 >> 2])); 725 // Memory address of the ctr_dest_addr structure
726 VAddr ctr_dest_addr_addr = cmd_buffer[0x104 >> 2];
686 727
687 sockaddr dest_addr; 728 sockaddr dest_addr;
688 socklen_t dest_addr_len = sizeof(dest_addr); 729 socklen_t dest_addr_len = sizeof(dest_addr);
689 int ret = ::getpeername(socket_handle, &dest_addr, &dest_addr_len); 730 int ret = ::getpeername(socket_handle, &dest_addr, &dest_addr_len);
690 731
691 if (ctr_dest_addr != nullptr) { 732 if (ctr_dest_addr_addr != 0 && Memory::IsValidVirtualAddress(ctr_dest_addr_addr)) {
692 *ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); 733 CTRSockAddr ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr);
734 Memory::WriteBlock(ctr_dest_addr_addr, &ctr_dest_addr, sizeof(ctr_dest_addr));
693 } else { 735 } else {
694 cmd_buffer[1] = -1; 736 cmd_buffer[1] = -1;
695 return; 737 return;
@@ -711,13 +753,17 @@ static void Connect(Service::Interface* self) {
711 u32 socket_handle = cmd_buffer[1]; 753 u32 socket_handle = cmd_buffer[1];
712 socklen_t len = cmd_buffer[2]; 754 socklen_t len = cmd_buffer[2];
713 755
714 CTRSockAddr* ctr_input_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[6])); 756 // Memory address of the ctr_input_addr structure
715 if (ctr_input_addr == nullptr) { 757 VAddr ctr_input_addr_addr = cmd_buffer[6];
758 if (!Memory::IsValidVirtualAddress(ctr_input_addr_addr)) {
716 cmd_buffer[1] = -1; // TODO(Subv): Verify error 759 cmd_buffer[1] = -1; // TODO(Subv): Verify error
717 return; 760 return;
718 } 761 }
719 762
720 sockaddr input_addr = CTRSockAddr::ToPlatform(*ctr_input_addr); 763 CTRSockAddr ctr_input_addr;
764 Memory::ReadBlock(ctr_input_addr_addr, &ctr_input_addr, sizeof(ctr_input_addr));
765
766 sockaddr input_addr = CTRSockAddr::ToPlatform(ctr_input_addr);
721 int ret = ::connect(socket_handle, &input_addr, sizeof(input_addr)); 767 int ret = ::connect(socket_handle, &input_addr, sizeof(input_addr));
722 int result = 0; 768 int result = 0;
723 if (ret != 0) 769 if (ret != 0)
diff --git a/src/core/hle/service/ssl_c.cpp b/src/core/hle/service/ssl_c.cpp
index 14a4e98ec..a8aff1abf 100644
--- a/src/core/hle/service/ssl_c.cpp
+++ b/src/core/hle/service/ssl_c.cpp
@@ -31,7 +31,6 @@ static void GenerateRandomData(Service::Interface* self) {
31 31
32 u32 size = cmd_buff[1]; 32 u32 size = cmd_buff[1];
33 VAddr address = cmd_buff[3]; 33 VAddr address = cmd_buff[3];
34 u8* output_buff = Memory::GetPointer(address);
35 34
36 // Fill the output buffer with random data. 35 // Fill the output buffer with random data.
37 u32 data = 0; 36 u32 data = 0;
@@ -44,13 +43,13 @@ static void GenerateRandomData(Service::Interface* self) {
44 43
45 if (size > 4) { 44 if (size > 4) {
46 // Use up the entire 4 bytes of the random data for as long as possible 45 // Use up the entire 4 bytes of the random data for as long as possible
47 *(u32*)(output_buff + i) = data; 46 Memory::Write32(address + i, data);
48 i += 4; 47 i += 4;
49 } else if (size == 2) { 48 } else if (size == 2) {
50 *(u16*)(output_buff + i) = (u16)(data & 0xffff); 49 Memory::Write16(address + i, static_cast<u16>(data & 0xffff));
51 i += 2; 50 i += 2;
52 } else { 51 } else {
53 *(u8*)(output_buff + i) = (u8)(data & 0xff); 52 Memory::Write8(address + i, static_cast<u8>(data & 0xff));
54 i++; 53 i++;
55 } 54 }
56 } 55 }
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index ee9b69f81..8c9e5d46d 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -246,6 +246,26 @@ void Write(const VAddr vaddr, const T data) {
246 } 246 }
247} 247}
248 248
249bool IsValidVirtualAddress(const VAddr vaddr) {
250 const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
251 if (page_pointer)
252 return true;
253
254 if (current_page_table->attributes[vaddr >> PAGE_BITS] != PageType::Special)
255 return false;
256
257 MMIORegionPointer mmio_region = GetMMIOHandler(vaddr);
258 if (mmio_region) {
259 return mmio_region->IsValidAddress(vaddr);
260 }
261
262 return false;
263}
264
265bool IsValidPhysicalAddress(const PAddr paddr) {
266 return IsValidVirtualAddress(PhysicalToVirtualAddress(paddr));
267}
268
249u8* GetPointer(const VAddr vaddr) { 269u8* GetPointer(const VAddr vaddr) {
250 u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; 270 u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
251 if (page_pointer) { 271 if (page_pointer) {
@@ -261,6 +281,7 @@ u8* GetPointer(const VAddr vaddr) {
261} 281}
262 282
263u8* GetPhysicalPointer(PAddr address) { 283u8* GetPhysicalPointer(PAddr address) {
284 // TODO(Subv): This call should not go through the application's memory mapping.
264 return GetPointer(PhysicalToVirtualAddress(address)); 285 return GetPointer(PhysicalToVirtualAddress(address));
265} 286}
266 287
@@ -343,6 +364,59 @@ u64 Read64(const VAddr addr) {
343 return Read<u64_le>(addr); 364 return Read<u64_le>(addr);
344} 365}
345 366
367void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) {
368 size_t remaining_size = size;
369 size_t page_index = src_addr >> PAGE_BITS;
370 size_t page_offset = src_addr & PAGE_MASK;
371
372 while (remaining_size > 0) {
373 const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size);
374 const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset;
375
376 switch (current_page_table->attributes[page_index]) {
377 case PageType::Unmapped: {
378 LOG_ERROR(HW_Memory, "unmapped ReadBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size);
379 std::memset(dest_buffer, 0, copy_amount);
380 break;
381 }
382 case PageType::Memory: {
383 DEBUG_ASSERT(current_page_table->pointers[page_index]);
384
385 const u8* src_ptr = current_page_table->pointers[page_index] + page_offset;
386 std::memcpy(dest_buffer, src_ptr, copy_amount);
387 break;
388 }
389 case PageType::Special: {
390 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
391
392 GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount);
393 break;
394 }
395 case PageType::RasterizerCachedMemory: {
396 RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
397
398 std::memcpy(dest_buffer, GetPointerFromVMA(current_vaddr), copy_amount);
399 break;
400 }
401 case PageType::RasterizerCachedSpecial: {
402 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
403
404 RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
405
406 GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount);
407 break;
408 }
409 default:
410 UNREACHABLE();
411 }
412
413 page_index++;
414 page_offset = 0;
415 dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount;
416 remaining_size -= copy_amount;
417 }
418}
419
346void Write8(const VAddr addr, const u8 data) { 420void Write8(const VAddr addr, const u8 data) {
347 Write<u8>(addr, data); 421 Write<u8>(addr, data);
348} 422}
@@ -359,9 +433,165 @@ void Write64(const VAddr addr, const u64 data) {
359 Write<u64_le>(addr, data); 433 Write<u64_le>(addr, data);
360} 434}
361 435
362void WriteBlock(const VAddr addr, const u8* data, const size_t size) { 436void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size) {
363 for (u32 offset = 0; offset < size; offset++) { 437 size_t remaining_size = size;
364 Write8(addr + offset, data[offset]); 438 size_t page_index = dest_addr >> PAGE_BITS;
439 size_t page_offset = dest_addr & PAGE_MASK;
440
441 while (remaining_size > 0) {
442 const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size);
443 const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset;
444
445 switch (current_page_table->attributes[page_index]) {
446 case PageType::Unmapped: {
447 LOG_ERROR(HW_Memory, "unmapped WriteBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size);
448 break;
449 }
450 case PageType::Memory: {
451 DEBUG_ASSERT(current_page_table->pointers[page_index]);
452
453 u8* dest_ptr = current_page_table->pointers[page_index] + page_offset;
454 std::memcpy(dest_ptr, src_buffer, copy_amount);
455 break;
456 }
457 case PageType::Special: {
458 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
459
460 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount);
461 break;
462 }
463 case PageType::RasterizerCachedMemory: {
464 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
465
466 std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount);
467 break;
468 }
469 case PageType::RasterizerCachedSpecial: {
470 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
471
472 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
473
474 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount);
475 break;
476 }
477 default:
478 UNREACHABLE();
479 }
480
481 page_index++;
482 page_offset = 0;
483 src_buffer = static_cast<const u8*>(src_buffer) + copy_amount;
484 remaining_size -= copy_amount;
485 }
486}
487
488void ZeroBlock(const VAddr dest_addr, const size_t size) {
489 size_t remaining_size = size;
490 size_t page_index = dest_addr >> PAGE_BITS;
491 size_t page_offset = dest_addr & PAGE_MASK;
492
493 static const std::array<u8, PAGE_SIZE> zeros = {};
494
495 while (remaining_size > 0) {
496 const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size);
497 const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset;
498
499 switch (current_page_table->attributes[page_index]) {
500 case PageType::Unmapped: {
501 LOG_ERROR(HW_Memory, "unmapped ZeroBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size);
502 break;
503 }
504 case PageType::Memory: {
505 DEBUG_ASSERT(current_page_table->pointers[page_index]);
506
507 u8* dest_ptr = current_page_table->pointers[page_index] + page_offset;
508 std::memset(dest_ptr, 0, copy_amount);
509 break;
510 }
511 case PageType::Special: {
512 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
513
514 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount);
515 break;
516 }
517 case PageType::RasterizerCachedMemory: {
518 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
519
520 std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount);
521 break;
522 }
523 case PageType::RasterizerCachedSpecial: {
524 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
525
526 RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
527
528 GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount);
529 break;
530 }
531 default:
532 UNREACHABLE();
533 }
534
535 page_index++;
536 page_offset = 0;
537 remaining_size -= copy_amount;
538 }
539}
540
541void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) {
542 size_t remaining_size = size;
543 size_t page_index = src_addr >> PAGE_BITS;
544 size_t page_offset = src_addr & PAGE_MASK;
545
546 while (remaining_size > 0) {
547 const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size);
548 const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset;
549
550 switch (current_page_table->attributes[page_index]) {
551 case PageType::Unmapped: {
552 LOG_ERROR(HW_Memory, "unmapped CopyBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size);
553 ZeroBlock(dest_addr, copy_amount);
554 break;
555 }
556 case PageType::Memory: {
557 DEBUG_ASSERT(current_page_table->pointers[page_index]);
558 const u8* src_ptr = current_page_table->pointers[page_index] + page_offset;
559 WriteBlock(dest_addr, src_ptr, copy_amount);
560 break;
561 }
562 case PageType::Special: {
563 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
564
565 std::vector<u8> buffer(copy_amount);
566 GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, buffer.data(), buffer.size());
567 WriteBlock(dest_addr, buffer.data(), buffer.size());
568 break;
569 }
570 case PageType::RasterizerCachedMemory: {
571 RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
572
573 WriteBlock(dest_addr, GetPointerFromVMA(current_vaddr), copy_amount);
574 break;
575 }
576 case PageType::RasterizerCachedSpecial: {
577 DEBUG_ASSERT(GetMMIOHandler(current_vaddr));
578
579 RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount);
580
581 std::vector<u8> buffer(copy_amount);
582 GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, buffer.data(), buffer.size());
583 WriteBlock(dest_addr, buffer.data(), buffer.size());
584 break;
585 }
586 default:
587 UNREACHABLE();
588 }
589
590 page_index++;
591 page_offset = 0;
592 dest_addr += copy_amount;
593 src_addr += copy_amount;
594 remaining_size -= copy_amount;
365 } 595 }
366} 596}
367 597
diff --git a/src/core/memory.h b/src/core/memory.h
index 126d60471..ae5588dee 100644
--- a/src/core/memory.h
+++ b/src/core/memory.h
@@ -110,6 +110,9 @@ enum : VAddr {
110 NEW_LINEAR_HEAP_VADDR_END = NEW_LINEAR_HEAP_VADDR + NEW_LINEAR_HEAP_SIZE, 110 NEW_LINEAR_HEAP_VADDR_END = NEW_LINEAR_HEAP_VADDR + NEW_LINEAR_HEAP_SIZE,
111}; 111};
112 112
113bool IsValidVirtualAddress(const VAddr addr);
114bool IsValidPhysicalAddress(const PAddr addr);
115
113u8 Read8(VAddr addr); 116u8 Read8(VAddr addr);
114u16 Read16(VAddr addr); 117u16 Read16(VAddr addr);
115u32 Read32(VAddr addr); 118u32 Read32(VAddr addr);
@@ -120,7 +123,10 @@ void Write16(VAddr addr, u16 data);
120void Write32(VAddr addr, u32 data); 123void Write32(VAddr addr, u32 data);
121void Write64(VAddr addr, u64 data); 124void Write64(VAddr addr, u64 data);
122 125
123void WriteBlock(VAddr addr, const u8* data, size_t size); 126void ReadBlock(const VAddr src_addr, void* dest_buffer, size_t size);
127void WriteBlock(const VAddr dest_addr, const void* src_buffer, size_t size);
128void ZeroBlock(const VAddr dest_addr, const size_t size);
129void CopyBlock(VAddr dest_addr, VAddr src_addr, size_t size);
124 130
125u8* GetPointer(VAddr virtual_address); 131u8* GetPointer(VAddr virtual_address);
126 132
diff --git a/src/core/mmio.h b/src/core/mmio.h
index 06b555e98..d76f005d8 100644
--- a/src/core/mmio.h
+++ b/src/core/mmio.h
@@ -18,15 +18,21 @@ class MMIORegion {
18public: 18public:
19 virtual ~MMIORegion() = default; 19 virtual ~MMIORegion() = default;
20 20
21 virtual bool IsValidAddress(VAddr addr) = 0;
22
21 virtual u8 Read8(VAddr addr) = 0; 23 virtual u8 Read8(VAddr addr) = 0;
22 virtual u16 Read16(VAddr addr) = 0; 24 virtual u16 Read16(VAddr addr) = 0;
23 virtual u32 Read32(VAddr addr) = 0; 25 virtual u32 Read32(VAddr addr) = 0;
24 virtual u64 Read64(VAddr addr) = 0; 26 virtual u64 Read64(VAddr addr) = 0;
25 27
28 virtual bool ReadBlock(VAddr src_addr, void* dest_buffer, size_t size) = 0;
29
26 virtual void Write8(VAddr addr, u8 data) = 0; 30 virtual void Write8(VAddr addr, u8 data) = 0;
27 virtual void Write16(VAddr addr, u16 data) = 0; 31 virtual void Write16(VAddr addr, u16 data) = 0;
28 virtual void Write32(VAddr addr, u32 data) = 0; 32 virtual void Write32(VAddr addr, u32 data) = 0;
29 virtual void Write64(VAddr addr, u64 data) = 0; 33 virtual void Write64(VAddr addr, u64 data) = 0;
34
35 virtual bool WriteBlock(VAddr dest_addr, const void* src_buffer, size_t size) = 0;
30}; 36};
31 37
32using MMIORegionPointer = std::shared_ptr<MMIORegion>; 38using MMIORegionPointer = std::shared_ptr<MMIORegion>;