mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Merge pull request #1692 from Subv/rm_getpointer2
Memory: Remove most usages of GetPointer
This commit is contained in:
		
						commit
						ab4b27f0f5
					
				
					 18 changed files with 460 additions and 141 deletions
				
			
		|  | @ -37,10 +37,13 @@ void CallstackWidget::OnDebugModeEntered() | |||
|     int counter = 0; | ||||
|     for (u32 addr = 0x10000000; addr >= sp; addr -= 4) | ||||
|     { | ||||
|         if (!Memory::IsValidVirtualAddress(addr)) | ||||
|             break; | ||||
| 
 | ||||
|         const u32 ret_addr = Memory::Read32(addr); | ||||
|         const u32 call_addr = ret_addr - 4; //get call address???
 | ||||
| 
 | ||||
|         if (Memory::GetPointer(call_addr) == nullptr) | ||||
|         if (!Memory::IsValidVirtualAddress(call_addr)) | ||||
|             break; | ||||
| 
 | ||||
|         /* TODO (mattvail) clean me, move to debugger interface */ | ||||
|  |  | |||
|  | @ -19,22 +19,22 @@ Path::Path(LowPathType type, u32 size, u32 pointer) : type(type) { | |||
|     switch (type) { | ||||
|     case Binary: | ||||
|     { | ||||
|         u8* data = Memory::GetPointer(pointer); | ||||
|         binary = std::vector<u8>(data, data + size); | ||||
|         binary.resize(size); | ||||
|         Memory::ReadBlock(pointer, binary.data(), binary.size()); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     case Char: | ||||
|     { | ||||
|         const char* data = reinterpret_cast<const char*>(Memory::GetPointer(pointer)); | ||||
|         string = std::string(data, size - 1); // Data is always null-terminated.
 | ||||
|         string.resize(size - 1); // Data is always null-terminated.
 | ||||
|         Memory::ReadBlock(pointer, &string[0], string.size()); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     case Wchar: | ||||
|     { | ||||
|         const char16_t* data = reinterpret_cast<const char16_t*>(Memory::GetPointer(pointer)); | ||||
|         u16str = std::u16string(data, size/2 - 1); // Data is always null-terminated.
 | ||||
|         u16str.resize(size / 2 - 1); // Data is always null-terminated.
 | ||||
|         Memory::ReadBlock(pointer, &u16str[0], u16str.size() * sizeof(char16_t)); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -32,9 +32,9 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p | |||
|     // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory.
 | ||||
|     // Create the SharedMemory that will hold the framebuffer data
 | ||||
|     Service::APT::CaptureBufferInfo capture_info; | ||||
|     ASSERT(sizeof(capture_info) == parameter.buffer_size); | ||||
|     ASSERT(sizeof(capture_info) == parameter.buffer.size()); | ||||
| 
 | ||||
|     memcpy(&capture_info, parameter.data, sizeof(capture_info)); | ||||
|     memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info)); | ||||
| 
 | ||||
|     using Kernel::MemoryPermission; | ||||
|     // Allocate a heap block of the required size for this applet.
 | ||||
|  | @ -47,8 +47,7 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p | |||
|     // Send the response message with the newly created SharedMemory
 | ||||
|     Service::APT::MessageParameter result; | ||||
|     result.signal = static_cast<u32>(Service::APT::SignalType::LibAppFinished); | ||||
|     result.data = nullptr; | ||||
|     result.buffer_size = 0; | ||||
|     result.buffer.clear(); | ||||
|     result.destination_id = static_cast<u32>(Service::APT::AppletId::Application); | ||||
|     result.sender_id = static_cast<u32>(id); | ||||
|     result.object = framebuffer_memory; | ||||
|  | @ -63,15 +62,17 @@ ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& pa | |||
|     // TODO(Subv): Set the expected fields in the response buffer before resending it to the application.
 | ||||
|     // TODO(Subv): Reverse the parameter format for the Mii Selector
 | ||||
| 
 | ||||
|     if(parameter.buffer_size >= sizeof(u32)) { | ||||
|         // TODO: defaults return no error, but garbage in other unknown fields
 | ||||
|         memset(parameter.data, 0, sizeof(u32)); | ||||
|     } | ||||
|     memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); | ||||
| 
 | ||||
|     // TODO(Subv): Find more about this structure, result code 0 is enough to let most games continue.
 | ||||
|     MiiResult result; | ||||
|     memset(&result, 0, sizeof(result)); | ||||
|     result.result_code = 0; | ||||
| 
 | ||||
|     // Let the application know that we're closing
 | ||||
|     Service::APT::MessageParameter message; | ||||
|     message.buffer_size = parameter.buffer_size; | ||||
|     message.data = parameter.data; | ||||
|     message.buffer.resize(sizeof(MiiResult)); | ||||
|     std::memcpy(message.buffer.data(), &result, message.buffer.size()); | ||||
|     message.signal = static_cast<u32>(Service::APT::SignalType::LibAppClosed); | ||||
|     message.destination_id = static_cast<u32>(Service::APT::AppletId::Application); | ||||
|     message.sender_id = static_cast<u32>(id); | ||||
|  |  | |||
|  | @ -24,7 +24,7 @@ struct MiiConfig { | |||
|     u8  unk_004; | ||||
|     INSERT_PADDING_BYTES(3); | ||||
|     u16 unk_008; | ||||
|     INSERT_PADDING_BYTES(0x8C - 0xA); | ||||
|     INSERT_PADDING_BYTES(0x82); | ||||
|     u8  unk_08C; | ||||
|     INSERT_PADDING_BYTES(3); | ||||
|     u16 unk_090; | ||||
|  | @ -75,6 +75,8 @@ public: | |||
| 
 | ||||
|     /// Whether this applet is currently running instead of the host application or not.
 | ||||
|     bool started; | ||||
| 
 | ||||
|     MiiConfig config; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -35,9 +35,9 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con | |||
|     // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory.
 | ||||
|     // Create the SharedMemory that will hold the framebuffer data
 | ||||
|     Service::APT::CaptureBufferInfo capture_info; | ||||
|     ASSERT(sizeof(capture_info) == parameter.buffer_size); | ||||
|     ASSERT(sizeof(capture_info) == parameter.buffer.size()); | ||||
| 
 | ||||
|     memcpy(&capture_info, parameter.data, sizeof(capture_info)); | ||||
|     memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info)); | ||||
| 
 | ||||
|     using Kernel::MemoryPermission; | ||||
|     // Allocate a heap block of the required size for this applet.
 | ||||
|  | @ -50,8 +50,7 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con | |||
|     // Send the response message with the newly created SharedMemory
 | ||||
|     Service::APT::MessageParameter result; | ||||
|     result.signal = static_cast<u32>(Service::APT::SignalType::LibAppFinished); | ||||
|     result.data = nullptr; | ||||
|     result.buffer_size = 0; | ||||
|     result.buffer.clear(); | ||||
|     result.destination_id = static_cast<u32>(Service::APT::AppletId::Application); | ||||
|     result.sender_id = static_cast<u32>(id); | ||||
|     result.object = framebuffer_memory; | ||||
|  | @ -61,9 +60,9 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con | |||
| } | ||||
| 
 | ||||
| ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter const& parameter) { | ||||
|     ASSERT_MSG(parameter.buffer_size == sizeof(config), "The size of the parameter (SoftwareKeyboardConfig) is wrong"); | ||||
|     ASSERT_MSG(parameter.buffer.size() == sizeof(config), "The size of the parameter (SoftwareKeyboardConfig) is wrong"); | ||||
| 
 | ||||
|     memcpy(&config, parameter.data, parameter.buffer_size); | ||||
|     memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); | ||||
|     text_memory = boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object); | ||||
| 
 | ||||
|     // TODO(Subv): Verify if this is the correct behavior
 | ||||
|  | @ -99,7 +98,7 @@ void SoftwareKeyboard::DrawScreenKeyboard() { | |||
|     auto info = bottom_screen->framebuffer_info[bottom_screen->index]; | ||||
| 
 | ||||
|     // TODO(Subv): Draw the HLE keyboard, for now just zero-fill the framebuffer
 | ||||
|     memset(Memory::GetPointer(info.address_left), 0, info.stride * 320); | ||||
|     Memory::ZeroBlock(info.address_left, info.stride * 320); | ||||
| 
 | ||||
|     GSP_GPU::SetBufferSwap(1, info); | ||||
| } | ||||
|  | @ -107,8 +106,8 @@ void SoftwareKeyboard::DrawScreenKeyboard() { | |||
| void SoftwareKeyboard::Finalize() { | ||||
|     // Let the application know that we're closing
 | ||||
|     Service::APT::MessageParameter message; | ||||
|     message.buffer_size = sizeof(SoftwareKeyboardConfig); | ||||
|     message.data = reinterpret_cast<u8*>(&config); | ||||
|     message.buffer.resize(sizeof(SoftwareKeyboardConfig)); | ||||
|     std::memcpy(message.buffer.data(), &config, message.buffer.size()); | ||||
|     message.signal = static_cast<u32>(Service::APT::SignalType::LibAppClosed); | ||||
|     message.destination_id = static_cast<u32>(Service::APT::AppletId::Application); | ||||
|     message.sender_id = static_cast<u32>(id); | ||||
|  |  | |||
|  | @ -403,7 +403,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | |||
|         priority = new_priority; | ||||
|     } | ||||
| 
 | ||||
|     if (!Memory::GetPointer(entry_point)) { | ||||
|     if (!Memory::IsValidVirtualAddress(entry_point)) { | ||||
|         LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point); | ||||
|         // TODO: Verify error
 | ||||
|         return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, | ||||
|  |  | |||
|  | @ -180,12 +180,12 @@ void SendParameter(Service::Interface* self) { | |||
|     } | ||||
| 
 | ||||
|     MessageParameter param; | ||||
|     param.buffer_size = buffer_size; | ||||
|     param.destination_id = dst_app_id; | ||||
|     param.sender_id = src_app_id; | ||||
|     param.object = Kernel::g_handle_table.GetGeneric(handle); | ||||
|     param.signal = signal_type; | ||||
|     param.data = Memory::GetPointer(buffer); | ||||
|     param.buffer.resize(buffer_size); | ||||
|     Memory::ReadBlock(buffer, param.buffer.data(), param.buffer.size()); | ||||
| 
 | ||||
|     cmd_buff[1] = dest_applet->ReceiveParameter(param).raw; | ||||
| 
 | ||||
|  | @ -203,16 +203,15 @@ void ReceiveParameter(Service::Interface* self) { | |||
|     cmd_buff[1] = RESULT_SUCCESS.raw; // No error
 | ||||
|     cmd_buff[2] = next_parameter.sender_id; | ||||
|     cmd_buff[3] = next_parameter.signal; // Signal type
 | ||||
|     cmd_buff[4] = next_parameter.buffer_size; // Parameter buffer size
 | ||||
|     cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size
 | ||||
|     cmd_buff[5] = 0x10; | ||||
|     cmd_buff[6] = 0; | ||||
|     if (next_parameter.object != nullptr) | ||||
|         cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom(); | ||||
|     cmd_buff[7] = (next_parameter.buffer_size << 14) | 2; | ||||
|     cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2; | ||||
|     cmd_buff[8] = buffer; | ||||
| 
 | ||||
|     if (next_parameter.data) | ||||
|         memcpy(Memory::GetPointer(buffer), next_parameter.data, std::min(buffer_size, next_parameter.buffer_size)); | ||||
|     Memory::WriteBlock(buffer, next_parameter.buffer.data(), next_parameter.buffer.size()); | ||||
| 
 | ||||
|     LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); | ||||
| } | ||||
|  | @ -226,16 +225,15 @@ void GlanceParameter(Service::Interface* self) { | |||
|     cmd_buff[1] = RESULT_SUCCESS.raw; // No error
 | ||||
|     cmd_buff[2] = next_parameter.sender_id; | ||||
|     cmd_buff[3] = next_parameter.signal; // Signal type
 | ||||
|     cmd_buff[4] = next_parameter.buffer_size; // Parameter buffer size
 | ||||
|     cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size
 | ||||
|     cmd_buff[5] = 0x10; | ||||
|     cmd_buff[6] = 0; | ||||
|     if (next_parameter.object != nullptr) | ||||
|         cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom(); | ||||
|     cmd_buff[7] = (next_parameter.buffer_size << 14) | 2; | ||||
|     cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2; | ||||
|     cmd_buff[8] = buffer; | ||||
| 
 | ||||
|     if (next_parameter.data) | ||||
|         memcpy(Memory::GetPointer(buffer), next_parameter.data, std::min(buffer_size, next_parameter.buffer_size)); | ||||
|     Memory::WriteBlock(buffer, next_parameter.buffer.data(), std::min(static_cast<size_t>(buffer_size), next_parameter.buffer.size())); | ||||
| 
 | ||||
|     LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); | ||||
| } | ||||
|  | @ -373,10 +371,13 @@ void StartLibraryApplet(Service::Interface* self) { | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     size_t buffer_size = cmd_buff[2]; | ||||
|     VAddr buffer_addr = cmd_buff[6]; | ||||
| 
 | ||||
|     AppletStartupParameter parameter; | ||||
|     parameter.buffer_size = cmd_buff[2]; | ||||
|     parameter.object = Kernel::g_handle_table.GetGeneric(cmd_buff[4]); | ||||
|     parameter.data = Memory::GetPointer(cmd_buff[6]); | ||||
|     parameter.buffer.resize(buffer_size); | ||||
|     Memory::ReadBlock(buffer_addr, parameter.buffer.data(), parameter.buffer.size()); | ||||
| 
 | ||||
|     cmd_buff[1] = applet->Start(parameter).raw; | ||||
| } | ||||
|  |  | |||
|  | @ -20,16 +20,14 @@ struct MessageParameter { | |||
|     u32 sender_id = 0; | ||||
|     u32 destination_id = 0; | ||||
|     u32 signal = 0; | ||||
|     u32 buffer_size = 0; | ||||
|     Kernel::SharedPtr<Kernel::Object> object = nullptr; | ||||
|     u8* data = nullptr; | ||||
|     std::vector<u8> buffer; | ||||
| }; | ||||
| 
 | ||||
| /// Holds information about the parameters used in StartLibraryApplet
 | ||||
| struct AppletStartupParameter { | ||||
|     u32 buffer_size = 0; | ||||
|     Kernel::SharedPtr<Kernel::Object> object = nullptr; | ||||
|     u8* data = nullptr; | ||||
|     std::vector<u8> buffer; | ||||
| }; | ||||
| 
 | ||||
| /// Used by the application to pass information about the current framebuffer to applets.
 | ||||
|  |  | |||
|  | @ -196,28 +196,32 @@ void GetConfigInfoBlk2(Service::Interface* self) { | |||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|     u32 size = cmd_buff[1]; | ||||
|     u32 block_id = cmd_buff[2]; | ||||
|     u8* data_pointer = Memory::GetPointer(cmd_buff[4]); | ||||
|     VAddr data_pointer = cmd_buff[4]; | ||||
| 
 | ||||
|     if (data_pointer == nullptr) { | ||||
|     if (!Memory::IsValidVirtualAddress(data_pointer)) { | ||||
|         cmd_buff[1] = -1; // TODO(Subv): Find the right error code
 | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x2, data_pointer).raw; | ||||
|     std::vector<u8> data(size); | ||||
|     cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x2, data.data()).raw; | ||||
|     Memory::WriteBlock(data_pointer, data.data(), data.size()); | ||||
| } | ||||
| 
 | ||||
| void GetConfigInfoBlk8(Service::Interface* self) { | ||||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|     u32 size = cmd_buff[1]; | ||||
|     u32 block_id = cmd_buff[2]; | ||||
|     u8* data_pointer = Memory::GetPointer(cmd_buff[4]); | ||||
|     VAddr data_pointer = cmd_buff[4]; | ||||
| 
 | ||||
|     if (data_pointer == nullptr) { | ||||
|     if (!Memory::IsValidVirtualAddress(data_pointer)) { | ||||
|         cmd_buff[1] = -1; // TODO(Subv): Find the right error code
 | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x8, data_pointer).raw; | ||||
|     std::vector<u8> data(size); | ||||
|     cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x8, data.data()).raw; | ||||
|     Memory::WriteBlock(data_pointer, data.data(), data.size()); | ||||
| } | ||||
| 
 | ||||
| void UpdateConfigNANDSavegame(Service::Interface* self) { | ||||
|  |  | |||
|  | @ -140,12 +140,15 @@ static void LoadComponent(Service::Interface* self) { | |||
| 
 | ||||
|     // TODO(bunnei): Implement real DSP firmware loading
 | ||||
| 
 | ||||
|     ASSERT(Memory::GetPointer(buffer) != nullptr); | ||||
|     ASSERT(size > 0x37C); | ||||
|     ASSERT(Memory::IsValidVirtualAddress(buffer)); | ||||
| 
 | ||||
|     LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64, Common::ComputeHash64(Memory::GetPointer(buffer), size)); | ||||
|     std::vector<u8> component_data(size); | ||||
|     Memory::ReadBlock(buffer, component_data.data(), component_data.size()); | ||||
| 
 | ||||
|     LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64, Common::ComputeHash64(component_data.data(), component_data.size())); | ||||
|     // Some versions of the firmware have the location of DSP structures listed here.
 | ||||
|     LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64, Common::ComputeHash64(Memory::GetPointer(buffer) + 0x340, 60)); | ||||
|     ASSERT(size > 0x37C); | ||||
|     LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64, Common::ComputeHash64(component_data.data() + 0x340, 60)); | ||||
| 
 | ||||
|     LOG_WARNING(Service_DSP, "(STUBBED) called size=0x%X, prog_mask=0x%08X, data_mask=0x%08X, buffer=0x%08X", | ||||
|                 size, prog_mask, data_mask, buffer); | ||||
|  | @ -285,7 +288,7 @@ static void WriteProcessPipe(Service::Interface* self) { | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     ASSERT_MSG(Memory::GetPointer(buffer) != nullptr, "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe_index, size, buffer); | ||||
|     ASSERT_MSG(Memory::IsValidVirtualAddress(buffer), "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer); | ||||
| 
 | ||||
|     std::vector<u8> message(size); | ||||
|     for (u32 i = 0; i < size; i++) { | ||||
|  | @ -324,7 +327,7 @@ static void ReadPipeIfPossible(Service::Interface* self) { | |||
| 
 | ||||
|     DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); | ||||
| 
 | ||||
|     ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe_index, unknown, size, addr); | ||||
|     ASSERT_MSG(Memory::IsValidVirtualAddress(addr), "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr); | ||||
| 
 | ||||
|     cmd_buff[0] = IPC::MakeHeader(0x10, 1, 2); | ||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; // No error
 | ||||
|  | @ -364,7 +367,7 @@ static void ReadPipe(Service::Interface* self) { | |||
| 
 | ||||
|     DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); | ||||
| 
 | ||||
|     ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe_index, unknown, size, addr); | ||||
|     ASSERT_MSG(Memory::IsValidVirtualAddress(addr), "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr); | ||||
| 
 | ||||
|     if (DSP::HLE::GetPipeReadableSize(pipe) >= size) { | ||||
|         std::vector<u8> response = DSP::HLE::PipeRead(pipe, size); | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ void GetMyPresence(Service::Interface* self) { | |||
| 
 | ||||
|     ASSERT(shifted_out_size == ((sizeof(MyPresence) << 14) | 2)); | ||||
| 
 | ||||
|     Memory::WriteBlock(my_presence_addr, reinterpret_cast<const u8*>(&my_presence), sizeof(MyPresence)); | ||||
|     Memory::WriteBlock(my_presence_addr, &my_presence, sizeof(MyPresence)); | ||||
| 
 | ||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; // No error
 | ||||
| 
 | ||||
|  | @ -39,8 +39,7 @@ void GetFriendKeyList(Service::Interface* self) { | |||
| 
 | ||||
|     FriendKey zero_key = {}; | ||||
|     for (u32 i = 0; i < frd_count; ++i) { | ||||
|         Memory::WriteBlock(frd_key_addr + i * sizeof(FriendKey), | ||||
|                            reinterpret_cast<const u8*>(&zero_key), sizeof(FriendKey)); | ||||
|         Memory::WriteBlock(frd_key_addr + i * sizeof(FriendKey), &zero_key, sizeof(FriendKey)); | ||||
|     } | ||||
| 
 | ||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; // No error
 | ||||
|  | @ -58,8 +57,7 @@ void GetFriendProfile(Service::Interface* self) { | |||
| 
 | ||||
|     Profile zero_profile = {}; | ||||
|     for (u32 i = 0; i < count; ++i) { | ||||
|         Memory::WriteBlock(profiles_addr + i * sizeof(Profile), | ||||
|             reinterpret_cast<const u8*>(&zero_profile), sizeof(Profile)); | ||||
|         Memory::WriteBlock(profiles_addr + i * sizeof(Profile), &zero_profile, sizeof(Profile)); | ||||
|     } | ||||
| 
 | ||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; // No error
 | ||||
|  | @ -88,7 +86,7 @@ void GetMyFriendKey(Service::Interface* self) { | |||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
| 
 | ||||
|     cmd_buff[1] = RESULT_SUCCESS.raw; // No error
 | ||||
|     Memory::WriteBlock(cmd_buff[2], reinterpret_cast<const u8*>(&my_friend_key), sizeof(FriendKey)); | ||||
|     Memory::WriteBlock(cmd_buff[2], &my_friend_key, sizeof(FriendKey)); | ||||
|     LOG_WARNING(Service_FRD, "(STUBBED) called"); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -108,13 +108,14 @@ ResultVal<bool> File::SyncRequest() { | |||
|                           offset, length, backend->GetSize()); | ||||
|             } | ||||
| 
 | ||||
|             ResultVal<size_t> read = backend->Read(offset, length, Memory::GetPointer(address)); | ||||
|             std::vector<u8> data(length); | ||||
|             ResultVal<size_t> read = backend->Read(offset, data.size(), data.data()); | ||||
|             if (read.Failed()) { | ||||
|                 cmd_buff[1] = read.Code().raw; | ||||
|                 return read.Code(); | ||||
|             } | ||||
|             Memory::WriteBlock(address, data.data(), *read); | ||||
|             cmd_buff[2] = static_cast<u32>(*read); | ||||
|             Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(address), length); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|  | @ -128,7 +129,9 @@ ResultVal<bool> File::SyncRequest() { | |||
|             LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x", | ||||
|                       GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush); | ||||
| 
 | ||||
|             ResultVal<size_t> written = backend->Write(offset, length, flush != 0, Memory::GetPointer(address)); | ||||
|             std::vector<u8> data(length); | ||||
|             Memory::ReadBlock(address, data.data(), data.size()); | ||||
|             ResultVal<size_t> written = backend->Write(offset, data.size(), flush != 0, data.data()); | ||||
|             if (written.Failed()) { | ||||
|                 cmd_buff[1] = written.Code().raw; | ||||
|                 return written.Code(); | ||||
|  | @ -216,12 +219,14 @@ ResultVal<bool> Directory::SyncRequest() { | |||
|         { | ||||
|             u32 count = cmd_buff[1]; | ||||
|             u32 address = cmd_buff[3]; | ||||
|             auto entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); | ||||
|             std::vector<FileSys::Entry> entries(count); | ||||
|             LOG_TRACE(Service_FS, "Read %s %s: count=%d", | ||||
|                 GetTypeName().c_str(), GetName().c_str(), count); | ||||
| 
 | ||||
|             // Number of entries actually read
 | ||||
|             cmd_buff[2] = backend->Read(count, entries); | ||||
|             u32 read = backend->Read(entries.size(), entries.data()); | ||||
|             cmd_buff[2] = read; | ||||
|             Memory::WriteBlock(address, entries.data(), read * sizeof(FileSys::Entry)); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|  | @ -456,11 +461,12 @@ ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon | |||
|     if (result.IsError()) | ||||
|         return result; | ||||
| 
 | ||||
|     u8* smdh_icon = Memory::GetPointer(icon_buffer); | ||||
|     if (!smdh_icon) | ||||
|     if (!Memory::IsValidVirtualAddress(icon_buffer)) | ||||
|         return ResultCode(-1); // TODO(Subv): Find the right error code
 | ||||
| 
 | ||||
|     ext_savedata->WriteIcon(path, smdh_icon, icon_size); | ||||
|     std::vector<u8> smdh_icon(icon_size); | ||||
|     Memory::ReadBlock(icon_buffer, smdh_icon.data(), smdh_icon.size()); | ||||
|     ext_savedata->WriteIcon(path, smdh_icon.data(), smdh_icon.size()); | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -65,15 +65,27 @@ static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) { | |||
|     return reinterpret_cast<InterruptRelayQueue*>(ptr); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Writes a single GSP GPU hardware registers with a single u32 value | ||||
|  * (For internal use.) | ||||
|  * | ||||
|  * @param base_address The address of the register in question | ||||
|  * @param data Data to be written | ||||
|  */ | ||||
| static void WriteSingleHWReg(u32 base_address, u32 data) { | ||||
|     DEBUG_ASSERT_MSG((base_address & 3) == 0 && base_address < 0x420000, "Write address out of range or misaligned"); | ||||
|     HW::Write<u32>(base_address + REGS_BEGIN, data); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Writes sequential GSP GPU hardware registers using an array of source data | ||||
|  * | ||||
|  * @param base_address The address of the first register in the sequence | ||||
|  * @param size_in_bytes The number of registers to update (size of data) | ||||
|  * @param data A pointer to the source data | ||||
|  * @param data_vaddr A pointer to the source data | ||||
|  * @return RESULT_SUCCESS if the parameters are valid, error code otherwise | ||||
|  */ | ||||
| static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) { | ||||
| static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, VAddr data_vaddr) { | ||||
|     // This magic number is verified to be done by the gsp module
 | ||||
|     const u32 max_size_in_bytes = 0x80; | ||||
| 
 | ||||
|  | @ -87,10 +99,10 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* da | |||
|             return ERR_GSP_REGS_MISALIGNED; | ||||
|         } else { | ||||
|             while (size_in_bytes > 0) { | ||||
|                 HW::Write<u32>(base_address + REGS_BEGIN, *data); | ||||
|                 WriteSingleHWReg(base_address, Memory::Read32(data_vaddr)); | ||||
| 
 | ||||
|                 size_in_bytes -= 4; | ||||
|                 ++data; | ||||
|                 data_vaddr += 4; | ||||
|                 base_address += 4; | ||||
|             } | ||||
|             return RESULT_SUCCESS; | ||||
|  | @ -112,7 +124,7 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* da | |||
|  * @param masks A pointer to the masks | ||||
|  * @return RESULT_SUCCESS if the parameters are valid, error code otherwise | ||||
|  */ | ||||
| static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, const u32* data, const u32* masks) { | ||||
| static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, VAddr data_vaddr, VAddr masks_vaddr) { | ||||
|     // This magic number is verified to be done by the gsp module
 | ||||
|     const u32 max_size_in_bytes = 0x80; | ||||
| 
 | ||||
|  | @ -131,14 +143,17 @@ static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, const | |||
|                 u32 reg_value; | ||||
|                 HW::Read<u32>(reg_value, reg_address); | ||||
| 
 | ||||
|                 // Update the current value of the register only for set mask bits
 | ||||
|                 reg_value = (reg_value & ~*masks) | (*data | *masks); | ||||
|                 u32 data = Memory::Read32(data_vaddr); | ||||
|                 u32 mask = Memory::Read32(masks_vaddr); | ||||
| 
 | ||||
|                 HW::Write<u32>(reg_address, reg_value); | ||||
|                 // Update the current value of the register only for set mask bits
 | ||||
|                 reg_value = (reg_value & ~mask) | (data | mask); | ||||
| 
 | ||||
|                 WriteSingleHWReg(base_address, reg_value); | ||||
| 
 | ||||
|                 size_in_bytes -= 4; | ||||
|                 ++data; | ||||
|                 ++masks; | ||||
|                 data_vaddr += 4; | ||||
|                 masks_vaddr += 4; | ||||
|                 base_address += 4; | ||||
|             } | ||||
|             return RESULT_SUCCESS; | ||||
|  | @ -164,8 +179,7 @@ static void WriteHWRegs(Service::Interface* self) { | |||
|     u32* cmd_buff = Kernel::GetCommandBuffer(); | ||||
|     u32 reg_addr = cmd_buff[1]; | ||||
|     u32 size = cmd_buff[2]; | ||||
| 
 | ||||
|     u32* src = (u32*)Memory::GetPointer(cmd_buff[4]); | ||||
|     VAddr src = cmd_buff[4]; | ||||
| 
 | ||||
|     cmd_buff[1] = WriteHWRegs(reg_addr, size, src).raw; | ||||
| } | ||||
|  | @ -186,8 +200,8 @@ static void WriteHWRegsWithMask(Service::Interface* self) { | |||
|     u32 reg_addr = cmd_buff[1]; | ||||
|     u32 size = cmd_buff[2]; | ||||
| 
 | ||||
|     u32* src_data = (u32*)Memory::GetPointer(cmd_buff[4]); | ||||
|     u32* mask_data = (u32*)Memory::GetPointer(cmd_buff[6]); | ||||
|     VAddr src_data = cmd_buff[4]; | ||||
|     VAddr mask_data = cmd_buff[6]; | ||||
| 
 | ||||
|     cmd_buff[1] = WriteHWRegsWithMask(reg_addr, size, src_data, mask_data).raw; | ||||
| } | ||||
|  | @ -210,13 +224,16 @@ static void ReadHWRegs(Service::Interface* self) { | |||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     u32* dst = (u32*)Memory::GetPointer(cmd_buff[0x41]); | ||||
|     VAddr dst_vaddr = cmd_buff[0x41]; | ||||
| 
 | ||||
|     while (size > 0) { | ||||
|         HW::Read<u32>(*dst, reg_addr + REGS_BEGIN); | ||||
|         u32 value; | ||||
|         HW::Read<u32>(value, reg_addr + REGS_BEGIN); | ||||
| 
 | ||||
|         Memory::Write32(dst_vaddr, value); | ||||
| 
 | ||||
|         size -= 4; | ||||
|         ++dst; | ||||
|         dst_vaddr += 4; | ||||
|         reg_addr += 4; | ||||
|     } | ||||
| } | ||||
|  | @ -226,22 +243,22 @@ ResultCode SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) { | |||
|     PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left); | ||||
|     PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right); | ||||
|     if (info.active_fb == 0) { | ||||
|         WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), | ||||
|                     4, &phys_address_left); | ||||
|         WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), | ||||
|                     4, &phys_address_right); | ||||
|         WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), | ||||
|                          phys_address_left); | ||||
|         WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), | ||||
|                          phys_address_right); | ||||
|     } else { | ||||
|         WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), | ||||
|                     4, &phys_address_left); | ||||
|         WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), | ||||
|                     4, &phys_address_right); | ||||
|         WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), | ||||
|                          phys_address_left); | ||||
|         WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), | ||||
|                          phys_address_right); | ||||
|     } | ||||
|     WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), | ||||
|                 4, &info.stride); | ||||
|     WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), | ||||
|                 4, &info.format); | ||||
|     WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), | ||||
|                 4, &info.shown_fb); | ||||
|     WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), | ||||
|                      info.stride); | ||||
|     WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), | ||||
|                      info.format); | ||||
|     WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), | ||||
|                      info.shown_fb); | ||||
| 
 | ||||
|     if (Pica::g_debug_context) | ||||
|         Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr); | ||||
|  | @ -432,9 +449,9 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | |||
|         Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(command.dma_request.dest_address), | ||||
|                             command.dma_request.size); | ||||
| 
 | ||||
|         memcpy(Memory::GetPointer(command.dma_request.dest_address), | ||||
|                Memory::GetPointer(command.dma_request.source_address), | ||||
|                command.dma_request.size); | ||||
|         // TODO(Subv): These memory accesses should not go through the application's memory mapping.
 | ||||
|         // They should go through the GSP module's memory mapping.
 | ||||
|         Memory::CopyBlock(command.dma_request.dest_address, command.dma_request.source_address, command.dma_request.size); | ||||
|         SignalInterrupt(InterruptId::DMA); | ||||
|         break; | ||||
|     } | ||||
|  |  | |||
|  | @ -373,14 +373,18 @@ static void Bind(Service::Interface* self) { | |||
|     u32* cmd_buffer = Kernel::GetCommandBuffer(); | ||||
|     u32 socket_handle = cmd_buffer[1]; | ||||
|     u32 len = cmd_buffer[2]; | ||||
|     CTRSockAddr* ctr_sock_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[6])); | ||||
| 
 | ||||
|     if (ctr_sock_addr == nullptr) { | ||||
|     // Virtual address of the sock_addr structure
 | ||||
|     VAddr sock_addr_addr = cmd_buffer[6]; | ||||
|     if (!Memory::IsValidVirtualAddress(sock_addr_addr)) { | ||||
|         cmd_buffer[1] = -1; // TODO(Subv): Correct code
 | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     sockaddr sock_addr = CTRSockAddr::ToPlatform(*ctr_sock_addr); | ||||
|     CTRSockAddr ctr_sock_addr; | ||||
|     Memory::ReadBlock(sock_addr_addr, reinterpret_cast<u8*>(&ctr_sock_addr), sizeof(CTRSockAddr)); | ||||
| 
 | ||||
|     sockaddr sock_addr = CTRSockAddr::ToPlatform(ctr_sock_addr); | ||||
| 
 | ||||
|     int res = ::bind(socket_handle, &sock_addr, std::max<u32>(sizeof(sock_addr), len)); | ||||
| 
 | ||||
|  | @ -496,7 +500,7 @@ static void Accept(Service::Interface* self) { | |||
|         result = TranslateError(GET_ERRNO); | ||||
|     } else { | ||||
|         CTRSockAddr ctr_addr = CTRSockAddr::FromPlatform(addr); | ||||
|         Memory::WriteBlock(cmd_buffer[0x104 >> 2], (const u8*)&ctr_addr, max_addr_len); | ||||
|         Memory::WriteBlock(cmd_buffer[0x104 >> 2], &ctr_addr, sizeof(ctr_addr)); | ||||
|     } | ||||
| 
 | ||||
|     cmd_buffer[0] = IPC::MakeHeader(4, 2, 2); | ||||
|  | @ -547,20 +551,31 @@ static void SendTo(Service::Interface* self) { | |||
|     u32 flags = cmd_buffer[3]; | ||||
|     u32 addr_len = cmd_buffer[4]; | ||||
| 
 | ||||
|     u8* input_buff = Memory::GetPointer(cmd_buffer[8]); | ||||
|     CTRSockAddr* ctr_dest_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[10])); | ||||
| 
 | ||||
|     if (ctr_dest_addr == nullptr) { | ||||
|     VAddr input_buff_address = cmd_buffer[8]; | ||||
|     if (!Memory::IsValidVirtualAddress(input_buff_address)) { | ||||
|         cmd_buffer[1] = -1; // TODO(Subv): Find the right error code
 | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     // Memory address of the dest_addr structure
 | ||||
|     VAddr dest_addr_addr = cmd_buffer[10]; | ||||
|     if (!Memory::IsValidVirtualAddress(dest_addr_addr)) { | ||||
|         cmd_buffer[1] = -1; // TODO(Subv): Find the right error code
 | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     std::vector<u8> input_buff(len); | ||||
|     Memory::ReadBlock(input_buff_address, input_buff.data(), input_buff.size()); | ||||
| 
 | ||||
|     CTRSockAddr ctr_dest_addr; | ||||
|     Memory::ReadBlock(dest_addr_addr, &ctr_dest_addr, sizeof(ctr_dest_addr)); | ||||
| 
 | ||||
|     int ret = -1; | ||||
|     if (addr_len > 0) { | ||||
|         sockaddr dest_addr = CTRSockAddr::ToPlatform(*ctr_dest_addr); | ||||
|         ret = ::sendto(socket_handle, (const char*)input_buff, len, flags, &dest_addr, sizeof(dest_addr)); | ||||
|         sockaddr dest_addr = CTRSockAddr::ToPlatform(ctr_dest_addr); | ||||
|         ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags, &dest_addr, sizeof(dest_addr)); | ||||
|     } else { | ||||
|         ret = ::sendto(socket_handle, (const char*)input_buff, len, flags, nullptr, 0); | ||||
|         ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags, nullptr, 0); | ||||
|     } | ||||
| 
 | ||||
|     int result = 0; | ||||
|  | @ -591,14 +606,24 @@ static void RecvFrom(Service::Interface* self) { | |||
| 
 | ||||
|     std::memcpy(&buffer_parameters, &cmd_buffer[64], sizeof(buffer_parameters)); | ||||
| 
 | ||||
|     u8* output_buff = Memory::GetPointer(buffer_parameters.output_buffer_addr); | ||||
|     if (!Memory::IsValidVirtualAddress(buffer_parameters.output_buffer_addr)) { | ||||
|         cmd_buffer[1] = -1; // TODO(Subv): Find the right error code
 | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (!Memory::IsValidVirtualAddress(buffer_parameters.output_src_address_buffer)) { | ||||
|         cmd_buffer[1] = -1; // TODO(Subv): Find the right error code
 | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     std::vector<u8> output_buff(len); | ||||
|     sockaddr src_addr; | ||||
|     socklen_t src_addr_len = sizeof(src_addr); | ||||
|     int ret = ::recvfrom(socket_handle, (char*)output_buff, len, flags, &src_addr, &src_addr_len); | ||||
|     int ret = ::recvfrom(socket_handle, reinterpret_cast<char*>(output_buff.data()), len, flags, &src_addr, &src_addr_len); | ||||
| 
 | ||||
|     if (ret >= 0 && buffer_parameters.output_src_address_buffer != 0 && src_addr_len > 0) { | ||||
|         CTRSockAddr* ctr_src_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(buffer_parameters.output_src_address_buffer)); | ||||
|         *ctr_src_addr = CTRSockAddr::FromPlatform(src_addr); | ||||
|         CTRSockAddr ctr_src_addr = CTRSockAddr::FromPlatform(src_addr); | ||||
|         Memory::WriteBlock(buffer_parameters.output_src_address_buffer, &ctr_src_addr, sizeof(ctr_src_addr)); | ||||
|     } | ||||
| 
 | ||||
|     int result = 0; | ||||
|  | @ -606,6 +631,9 @@ static void RecvFrom(Service::Interface* self) { | |||
|     if (ret == SOCKET_ERROR_VALUE) { | ||||
|         result = TranslateError(GET_ERRNO); | ||||
|         total_received = 0; | ||||
|     } else { | ||||
|         // Write only the data we received to avoid overwriting parts of the buffer with zeros
 | ||||
|         Memory::WriteBlock(buffer_parameters.output_buffer_addr, output_buff.data(), total_received); | ||||
|     } | ||||
| 
 | ||||
|     cmd_buffer[1] = result; | ||||
|  | @ -617,18 +645,28 @@ static void Poll(Service::Interface* self) { | |||
|     u32* cmd_buffer = Kernel::GetCommandBuffer(); | ||||
|     u32 nfds = cmd_buffer[1]; | ||||
|     int timeout = cmd_buffer[2]; | ||||
|     CTRPollFD* input_fds = reinterpret_cast<CTRPollFD*>(Memory::GetPointer(cmd_buffer[6])); | ||||
|     CTRPollFD* output_fds = reinterpret_cast<CTRPollFD*>(Memory::GetPointer(cmd_buffer[0x104 >> 2])); | ||||
| 
 | ||||
|     VAddr input_fds_addr = cmd_buffer[6]; | ||||
|     VAddr output_fds_addr = cmd_buffer[0x104 >> 2]; | ||||
|     if (!Memory::IsValidVirtualAddress(input_fds_addr) || !Memory::IsValidVirtualAddress(output_fds_addr)) { | ||||
|         cmd_buffer[1] = -1; // TODO(Subv): Find correct error code.
 | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     std::vector<CTRPollFD> ctr_fds(nfds); | ||||
|     Memory::ReadBlock(input_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD)); | ||||
| 
 | ||||
|     // The 3ds_pollfd and the pollfd structures may be different (Windows/Linux have different sizes)
 | ||||
|     // so we have to copy the data
 | ||||
|     std::vector<pollfd> platform_pollfd(nfds); | ||||
|     std::transform(input_fds, input_fds + nfds, platform_pollfd.begin(), CTRPollFD::ToPlatform); | ||||
|     std::transform(ctr_fds.begin(), ctr_fds.end(), platform_pollfd.begin(), CTRPollFD::ToPlatform); | ||||
| 
 | ||||
|     const int ret = ::poll(platform_pollfd.data(), nfds, timeout); | ||||
| 
 | ||||
|     // Now update the output pollfd structure
 | ||||
|     std::transform(platform_pollfd.begin(), platform_pollfd.end(), output_fds, CTRPollFD::FromPlatform); | ||||
|     std::transform(platform_pollfd.begin(), platform_pollfd.end(), ctr_fds.begin(), CTRPollFD::FromPlatform); | ||||
| 
 | ||||
|     Memory::WriteBlock(output_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD)); | ||||
| 
 | ||||
|     int result = 0; | ||||
|     if (ret == SOCKET_ERROR_VALUE) | ||||
|  | @ -643,14 +681,16 @@ static void GetSockName(Service::Interface* self) { | |||
|     u32 socket_handle = cmd_buffer[1]; | ||||
|     socklen_t ctr_len = cmd_buffer[2]; | ||||
| 
 | ||||
|     CTRSockAddr* ctr_dest_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[0x104 >> 2])); | ||||
|     // Memory address of the ctr_dest_addr structure
 | ||||
|     VAddr ctr_dest_addr_addr = cmd_buffer[0x104 >> 2]; | ||||
| 
 | ||||
|     sockaddr dest_addr; | ||||
|     socklen_t dest_addr_len = sizeof(dest_addr); | ||||
|     int ret = ::getsockname(socket_handle, &dest_addr, &dest_addr_len); | ||||
| 
 | ||||
|     if (ctr_dest_addr != nullptr) { | ||||
|         *ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); | ||||
|     if (ctr_dest_addr_addr != 0 && Memory::IsValidVirtualAddress(ctr_dest_addr_addr)) { | ||||
|         CTRSockAddr ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); | ||||
|         Memory::WriteBlock(ctr_dest_addr_addr, &ctr_dest_addr, sizeof(ctr_dest_addr)); | ||||
|     } else { | ||||
|         cmd_buffer[1] = -1; // TODO(Subv): Verify error
 | ||||
|         return; | ||||
|  | @ -682,14 +722,16 @@ static void GetPeerName(Service::Interface* self) { | |||
|     u32 socket_handle = cmd_buffer[1]; | ||||
|     socklen_t len = cmd_buffer[2]; | ||||
| 
 | ||||
|     CTRSockAddr* ctr_dest_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[0x104 >> 2])); | ||||
|     // Memory address of the ctr_dest_addr structure
 | ||||
|     VAddr ctr_dest_addr_addr = cmd_buffer[0x104 >> 2]; | ||||
| 
 | ||||
|     sockaddr dest_addr; | ||||
|     socklen_t dest_addr_len = sizeof(dest_addr); | ||||
|     int ret = ::getpeername(socket_handle, &dest_addr, &dest_addr_len); | ||||
| 
 | ||||
|     if (ctr_dest_addr != nullptr) { | ||||
|         *ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); | ||||
|     if (ctr_dest_addr_addr != 0 && Memory::IsValidVirtualAddress(ctr_dest_addr_addr)) { | ||||
|         CTRSockAddr ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); | ||||
|         Memory::WriteBlock(ctr_dest_addr_addr, &ctr_dest_addr, sizeof(ctr_dest_addr)); | ||||
|     } else { | ||||
|         cmd_buffer[1] = -1; | ||||
|         return; | ||||
|  | @ -711,13 +753,17 @@ static void Connect(Service::Interface* self) { | |||
|     u32 socket_handle = cmd_buffer[1]; | ||||
|     socklen_t len = cmd_buffer[2]; | ||||
| 
 | ||||
|     CTRSockAddr* ctr_input_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[6])); | ||||
|     if (ctr_input_addr == nullptr) { | ||||
|     // Memory address of the ctr_input_addr structure
 | ||||
|     VAddr ctr_input_addr_addr = cmd_buffer[6]; | ||||
|     if (!Memory::IsValidVirtualAddress(ctr_input_addr_addr)) { | ||||
|         cmd_buffer[1] = -1; // TODO(Subv): Verify error
 | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     sockaddr input_addr = CTRSockAddr::ToPlatform(*ctr_input_addr); | ||||
|     CTRSockAddr ctr_input_addr; | ||||
|     Memory::ReadBlock(ctr_input_addr_addr, &ctr_input_addr, sizeof(ctr_input_addr)); | ||||
| 
 | ||||
|     sockaddr input_addr = CTRSockAddr::ToPlatform(ctr_input_addr); | ||||
|     int ret = ::connect(socket_handle, &input_addr, sizeof(input_addr)); | ||||
|     int result = 0; | ||||
|     if (ret != 0) | ||||
|  |  | |||
|  | @ -31,7 +31,6 @@ static void GenerateRandomData(Service::Interface* self) { | |||
| 
 | ||||
|     u32 size = cmd_buff[1]; | ||||
|     VAddr address = cmd_buff[3]; | ||||
|     u8* output_buff = Memory::GetPointer(address); | ||||
| 
 | ||||
|     // Fill the output buffer with random data.
 | ||||
|     u32 data = 0; | ||||
|  | @ -44,13 +43,13 @@ static void GenerateRandomData(Service::Interface* self) { | |||
| 
 | ||||
|         if (size > 4) { | ||||
|             // Use up the entire 4 bytes of the random data for as long as possible
 | ||||
|             *(u32*)(output_buff + i) = data; | ||||
|             Memory::Write32(address + i, data); | ||||
|             i += 4; | ||||
|         } else if (size == 2) { | ||||
|             *(u16*)(output_buff + i) = (u16)(data & 0xffff); | ||||
|             Memory::Write16(address + i, static_cast<u16>(data & 0xffff)); | ||||
|             i += 2; | ||||
|         } else { | ||||
|             *(u8*)(output_buff + i) = (u8)(data & 0xff); | ||||
|             Memory::Write8(address + i, static_cast<u8>(data & 0xff)); | ||||
|             i++; | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -246,6 +246,26 @@ void Write(const VAddr vaddr, const T data) { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| bool IsValidVirtualAddress(const VAddr vaddr) { | ||||
|     const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; | ||||
|     if (page_pointer) | ||||
|         return true; | ||||
| 
 | ||||
|     if (current_page_table->attributes[vaddr >> PAGE_BITS] != PageType::Special) | ||||
|         return false; | ||||
| 
 | ||||
|     MMIORegionPointer mmio_region = GetMMIOHandler(vaddr); | ||||
|     if (mmio_region) { | ||||
|         return mmio_region->IsValidAddress(vaddr); | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| bool IsValidPhysicalAddress(const PAddr paddr) { | ||||
|     return IsValidVirtualAddress(PhysicalToVirtualAddress(paddr)); | ||||
| } | ||||
| 
 | ||||
| u8* GetPointer(const VAddr vaddr) { | ||||
|     u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; | ||||
|     if (page_pointer) { | ||||
|  | @ -261,6 +281,7 @@ u8* GetPointer(const VAddr vaddr) { | |||
| } | ||||
| 
 | ||||
| u8* GetPhysicalPointer(PAddr address) { | ||||
|     // TODO(Subv): This call should not go through the application's memory mapping.
 | ||||
|     return GetPointer(PhysicalToVirtualAddress(address)); | ||||
| } | ||||
| 
 | ||||
|  | @ -343,6 +364,59 @@ u64 Read64(const VAddr addr) { | |||
|     return Read<u64_le>(addr); | ||||
| } | ||||
| 
 | ||||
| void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) { | ||||
|     size_t remaining_size = size; | ||||
|     size_t page_index = src_addr >> PAGE_BITS; | ||||
|     size_t page_offset = src_addr & PAGE_MASK; | ||||
| 
 | ||||
|     while (remaining_size > 0) { | ||||
|         const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); | ||||
|         const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; | ||||
| 
 | ||||
|         switch (current_page_table->attributes[page_index]) { | ||||
|         case PageType::Unmapped: { | ||||
|             LOG_ERROR(HW_Memory, "unmapped ReadBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size); | ||||
|             std::memset(dest_buffer, 0, copy_amount); | ||||
|             break; | ||||
|         } | ||||
|         case PageType::Memory: { | ||||
|             DEBUG_ASSERT(current_page_table->pointers[page_index]); | ||||
| 
 | ||||
|             const u8* src_ptr = current_page_table->pointers[page_index] + page_offset; | ||||
|             std::memcpy(dest_buffer, src_ptr, copy_amount); | ||||
|             break; | ||||
|         } | ||||
|         case PageType::Special: { | ||||
|             DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); | ||||
| 
 | ||||
|             GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount); | ||||
|             break; | ||||
|         } | ||||
|         case PageType::RasterizerCachedMemory: { | ||||
|             RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | ||||
| 
 | ||||
|             std::memcpy(dest_buffer, GetPointerFromVMA(current_vaddr), copy_amount); | ||||
|             break; | ||||
|         } | ||||
|         case PageType::RasterizerCachedSpecial: { | ||||
|             DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); | ||||
| 
 | ||||
|             RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | ||||
| 
 | ||||
|             GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount); | ||||
|             break; | ||||
|         } | ||||
|         default: | ||||
|             UNREACHABLE(); | ||||
|         } | ||||
| 
 | ||||
|         page_index++; | ||||
|         page_offset = 0; | ||||
|         dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount; | ||||
|         remaining_size -= copy_amount; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Write8(const VAddr addr, const u8 data) { | ||||
|     Write<u8>(addr, data); | ||||
| } | ||||
|  | @ -359,9 +433,165 @@ void Write64(const VAddr addr, const u64 data) { | |||
|     Write<u64_le>(addr, data); | ||||
| } | ||||
| 
 | ||||
| void WriteBlock(const VAddr addr, const u8* data, const size_t size) { | ||||
|     for (u32 offset = 0; offset < size; offset++) { | ||||
|         Write8(addr + offset, data[offset]); | ||||
| void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size) { | ||||
|     size_t remaining_size = size; | ||||
|     size_t page_index = dest_addr >> PAGE_BITS; | ||||
|     size_t page_offset = dest_addr & PAGE_MASK; | ||||
| 
 | ||||
|     while (remaining_size > 0) { | ||||
|         const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); | ||||
|         const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; | ||||
| 
 | ||||
|         switch (current_page_table->attributes[page_index]) { | ||||
|         case PageType::Unmapped: { | ||||
|             LOG_ERROR(HW_Memory, "unmapped WriteBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size); | ||||
|             break; | ||||
|         } | ||||
|         case PageType::Memory: { | ||||
|             DEBUG_ASSERT(current_page_table->pointers[page_index]); | ||||
| 
 | ||||
|             u8* dest_ptr = current_page_table->pointers[page_index] + page_offset; | ||||
|             std::memcpy(dest_ptr, src_buffer, copy_amount); | ||||
|             break; | ||||
|         } | ||||
|         case PageType::Special: { | ||||
|             DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); | ||||
| 
 | ||||
|             GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); | ||||
|             break; | ||||
|         } | ||||
|         case PageType::RasterizerCachedMemory: { | ||||
|             RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | ||||
| 
 | ||||
|             std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount); | ||||
|             break; | ||||
|         } | ||||
|         case PageType::RasterizerCachedSpecial: { | ||||
|             DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); | ||||
| 
 | ||||
|             RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | ||||
| 
 | ||||
|             GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); | ||||
|             break; | ||||
|         } | ||||
|         default: | ||||
|             UNREACHABLE(); | ||||
|         } | ||||
| 
 | ||||
|         page_index++; | ||||
|         page_offset = 0; | ||||
|         src_buffer = static_cast<const u8*>(src_buffer) + copy_amount; | ||||
|         remaining_size -= copy_amount; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void ZeroBlock(const VAddr dest_addr, const size_t size) { | ||||
|     size_t remaining_size = size; | ||||
|     size_t page_index = dest_addr >> PAGE_BITS; | ||||
|     size_t page_offset = dest_addr & PAGE_MASK; | ||||
| 
 | ||||
|     static const std::array<u8, PAGE_SIZE> zeros = {}; | ||||
| 
 | ||||
|     while (remaining_size > 0) { | ||||
|         const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); | ||||
|         const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; | ||||
| 
 | ||||
|         switch (current_page_table->attributes[page_index]) { | ||||
|         case PageType::Unmapped: { | ||||
|             LOG_ERROR(HW_Memory, "unmapped ZeroBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size); | ||||
|             break; | ||||
|         } | ||||
|         case PageType::Memory: { | ||||
|             DEBUG_ASSERT(current_page_table->pointers[page_index]); | ||||
| 
 | ||||
|             u8* dest_ptr = current_page_table->pointers[page_index] + page_offset; | ||||
|             std::memset(dest_ptr, 0, copy_amount); | ||||
|             break; | ||||
|         } | ||||
|         case PageType::Special: { | ||||
|             DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); | ||||
| 
 | ||||
|             GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount); | ||||
|             break; | ||||
|         } | ||||
|         case PageType::RasterizerCachedMemory: { | ||||
|             RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | ||||
| 
 | ||||
|             std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount); | ||||
|             break; | ||||
|         } | ||||
|         case PageType::RasterizerCachedSpecial: { | ||||
|             DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); | ||||
| 
 | ||||
|             RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | ||||
| 
 | ||||
|             GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount); | ||||
|             break; | ||||
|         } | ||||
|         default: | ||||
|             UNREACHABLE(); | ||||
|         } | ||||
| 
 | ||||
|         page_index++; | ||||
|         page_offset = 0; | ||||
|         remaining_size -= copy_amount; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) { | ||||
|     size_t remaining_size = size; | ||||
|     size_t page_index = src_addr >> PAGE_BITS; | ||||
|     size_t page_offset = src_addr & PAGE_MASK; | ||||
| 
 | ||||
|     while (remaining_size > 0) { | ||||
|         const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); | ||||
|         const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; | ||||
| 
 | ||||
|         switch (current_page_table->attributes[page_index]) { | ||||
|         case PageType::Unmapped: { | ||||
|             LOG_ERROR(HW_Memory, "unmapped CopyBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size); | ||||
|             ZeroBlock(dest_addr, copy_amount); | ||||
|             break; | ||||
|         } | ||||
|         case PageType::Memory: { | ||||
|             DEBUG_ASSERT(current_page_table->pointers[page_index]); | ||||
|             const u8* src_ptr = current_page_table->pointers[page_index] + page_offset; | ||||
|             WriteBlock(dest_addr, src_ptr, copy_amount); | ||||
|             break; | ||||
|         } | ||||
|         case PageType::Special: { | ||||
|             DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); | ||||
| 
 | ||||
|             std::vector<u8> buffer(copy_amount); | ||||
|             GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, buffer.data(), buffer.size()); | ||||
|             WriteBlock(dest_addr, buffer.data(), buffer.size()); | ||||
|             break; | ||||
|         } | ||||
|         case PageType::RasterizerCachedMemory: { | ||||
|             RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | ||||
| 
 | ||||
|             WriteBlock(dest_addr, GetPointerFromVMA(current_vaddr), copy_amount); | ||||
|             break; | ||||
|         } | ||||
|         case PageType::RasterizerCachedSpecial: { | ||||
|             DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); | ||||
| 
 | ||||
|             RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | ||||
| 
 | ||||
|             std::vector<u8> buffer(copy_amount); | ||||
|             GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, buffer.data(), buffer.size()); | ||||
|             WriteBlock(dest_addr, buffer.data(), buffer.size()); | ||||
|             break; | ||||
|         } | ||||
|         default: | ||||
|             UNREACHABLE(); | ||||
|         } | ||||
| 
 | ||||
|         page_index++; | ||||
|         page_offset = 0; | ||||
|         dest_addr += copy_amount; | ||||
|         src_addr += copy_amount; | ||||
|         remaining_size -= copy_amount; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -110,6 +110,9 @@ enum : VAddr { | |||
|     NEW_LINEAR_HEAP_VADDR_END = NEW_LINEAR_HEAP_VADDR + NEW_LINEAR_HEAP_SIZE, | ||||
| }; | ||||
| 
 | ||||
| bool IsValidVirtualAddress(const VAddr addr); | ||||
| bool IsValidPhysicalAddress(const PAddr addr); | ||||
| 
 | ||||
| u8 Read8(VAddr addr); | ||||
| u16 Read16(VAddr addr); | ||||
| u32 Read32(VAddr addr); | ||||
|  | @ -120,7 +123,10 @@ void Write16(VAddr addr, u16 data); | |||
| void Write32(VAddr addr, u32 data); | ||||
| void Write64(VAddr addr, u64 data); | ||||
| 
 | ||||
| void WriteBlock(VAddr addr, const u8* data, size_t size); | ||||
| void ReadBlock(const VAddr src_addr, void* dest_buffer, size_t size); | ||||
| void WriteBlock(const VAddr dest_addr, const void* src_buffer, size_t size); | ||||
| void ZeroBlock(const VAddr dest_addr, const size_t size); | ||||
| void CopyBlock(VAddr dest_addr, VAddr src_addr, size_t size); | ||||
| 
 | ||||
| u8* GetPointer(VAddr virtual_address); | ||||
| 
 | ||||
|  |  | |||
|  | @ -18,15 +18,21 @@ class MMIORegion { | |||
| public: | ||||
|     virtual ~MMIORegion() = default; | ||||
| 
 | ||||
|     virtual bool IsValidAddress(VAddr addr) = 0; | ||||
| 
 | ||||
|     virtual u8 Read8(VAddr addr) = 0; | ||||
|     virtual u16 Read16(VAddr addr) = 0; | ||||
|     virtual u32 Read32(VAddr addr) = 0; | ||||
|     virtual u64 Read64(VAddr addr) = 0; | ||||
| 
 | ||||
|     virtual bool ReadBlock(VAddr src_addr, void* dest_buffer, size_t size) = 0; | ||||
| 
 | ||||
|     virtual void Write8(VAddr addr, u8 data) = 0; | ||||
|     virtual void Write16(VAddr addr, u16 data) = 0; | ||||
|     virtual void Write32(VAddr addr, u32 data) = 0; | ||||
|     virtual void Write64(VAddr addr, u64 data) = 0; | ||||
| 
 | ||||
|     virtual bool WriteBlock(VAddr dest_addr, const void* src_buffer, size_t size) = 0; | ||||
| }; | ||||
| 
 | ||||
| using MMIORegionPointer = std::shared_ptr<MMIORegion>; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue