IOS HLE: Deduplicate request code in DI

This commit is contained in:
Léo Lam 2017-01-15 11:47:54 +01:00
parent 469a31db32
commit 5a5985f674
2 changed files with 33 additions and 56 deletions

View file

@ -32,7 +32,7 @@ void CWII_IPC_HLE_Device_di::DoState(PointerWrap& p)
p.Do(m_commands_to_execute); p.Do(m_commands_to_execute);
} }
IPCCommandResult CWII_IPC_HLE_Device_di::IOCtl(u32 _CommandAddress) IPCCommandResult CWII_IPC_HLE_Device_di::IOCtl(const IOSIOCtlRequest& request)
{ {
// DI IOCtls are handled in a special way by Dolphin // DI IOCtls are handled in a special way by Dolphin
// compared to other WII_IPC_HLE functions. // compared to other WII_IPC_HLE functions.
@ -42,40 +42,25 @@ IPCCommandResult CWII_IPC_HLE_Device_di::IOCtl(u32 _CommandAddress)
// are queued until DVDInterface is ready to handle them. // are queued until DVDInterface is ready to handle them.
bool ready_to_execute = m_commands_to_execute.empty(); bool ready_to_execute = m_commands_to_execute.empty();
m_commands_to_execute.push_back(_CommandAddress); m_commands_to_execute.push_back(request.address);
if (ready_to_execute) if (ready_to_execute)
StartIOCtl(_CommandAddress); StartIOCtl(request);
// DVDInterface handles the timing and we handle the reply, // DVDInterface handles the timing and we handle the reply,
// so WII_IPC_HLE shouldn't handle anything. // so WII_IPC_HLE shouldn't handle anything.
return GetNoReply(); return GetNoReply();
} }
void CWII_IPC_HLE_Device_di::StartIOCtl(u32 command_address) void CWII_IPC_HLE_Device_di::StartIOCtl(const IOSIOCtlRequest& request)
{ {
u32 BufferIn = Memory::Read_U32(command_address + 0x10); const u32 command_0 = Memory::Read_U32(request.buffer_in);
u32 BufferInSize = Memory::Read_U32(command_address + 0x14); const u32 command_1 = Memory::Read_U32(request.buffer_in + 4);
u32 BufferOut = Memory::Read_U32(command_address + 0x18); const u32 command_2 = Memory::Read_U32(request.buffer_in + 8);
u32 BufferOutSize = Memory::Read_U32(command_address + 0x1C);
u32 command_0 = Memory::Read_U32(BufferIn);
u32 command_1 = Memory::Read_U32(BufferIn + 4);
u32 command_2 = Memory::Read_U32(BufferIn + 8);
DEBUG_LOG(WII_IPC_DVD, "IOCtl Command(0x%08x) BufferIn(0x%08x, 0x%x) BufferOut(0x%08x, 0x%x)",
command_0, BufferIn, BufferInSize, BufferOut, BufferOutSize);
// TATSUNOKO VS CAPCOM: Gets here with BufferOut == 0!!!
if (BufferOut != 0)
{
// Set out buffer to zeroes as a safety precaution
// to avoid answering nonsense values
Memory::Memset(BufferOut, 0, BufferOutSize);
}
// DVDInterface's ExecuteCommand handles most of the work. // DVDInterface's ExecuteCommand handles most of the work.
// The IOCtl callback is used to generate a reply afterwards. // The IOCtl callback is used to generate a reply afterwards.
DVDInterface::ExecuteCommand(command_0, command_1, command_2, BufferOut, BufferOutSize, true); DVDInterface::ExecuteCommand(command_0, command_1, command_2, request.buffer_out,
request.buffer_out_size, true);
} }
void CWII_IPC_HLE_Device_di::FinishIOCtl(DVDInterface::DIInterruptType interrupt_type) void CWII_IPC_HLE_Device_di::FinishIOCtl(DVDInterface::DIInterruptType interrupt_type)
@ -89,58 +74,50 @@ void CWII_IPC_HLE_Device_di::FinishIOCtl(DVDInterface::DIInterruptType interrupt
// This command has been executed, so it's removed from the queue // This command has been executed, so it's removed from the queue
u32 command_address = m_commands_to_execute.front(); u32 command_address = m_commands_to_execute.front();
m_commands_to_execute.pop_front(); m_commands_to_execute.pop_front();
IOSIOCtlRequest request{command_address};
// The DI interrupt type is used as a return value request.SetReturnValue(interrupt_type);
Memory::Write_U32(interrupt_type, command_address + 4); WII_IPC_HLE_Interface::EnqueueReply(request);
WII_IPC_HLE_Interface::EnqueueReply(command_address);
// DVDInterface is now ready to execute another command, // DVDInterface is now ready to execute another command,
// so we start executing a command from the queue if there is one // so we start executing a command from the queue if there is one
if (!m_commands_to_execute.empty()) if (!m_commands_to_execute.empty())
StartIOCtl(m_commands_to_execute.front()); {
IOSIOCtlRequest next_request{m_commands_to_execute.front()};
StartIOCtl(next_request);
}
} }
IPCCommandResult CWII_IPC_HLE_Device_di::IOCtlV(u32 _CommandAddress) IPCCommandResult CWII_IPC_HLE_Device_di::IOCtlV(const IOSIOCtlVRequest& request)
{ {
SIOCtlVBuffer CommandBuffer(_CommandAddress); for (const auto& vector : request.io_vectors)
Memory::Memset(vector.address, 0, vector.size);
// Prepare the out buffer(s) with zeros as a safety precaution s32 return_value = IPC_SUCCESS;
// to avoid returning bad values switch (request.request)
for (const auto& buffer : CommandBuffer.PayloadBuffer)
Memory::Memset(buffer.m_Address, 0, buffer.m_Size);
u32 ReturnValue = 0;
switch (CommandBuffer.Parameter)
{ {
case DVDInterface::DVDLowOpenPartition: case DVDInterface::DVDLowOpenPartition:
{ {
_dbg_assert_msg_(WII_IPC_DVD, CommandBuffer.InBuffer[1].m_Address == 0, _dbg_assert_msg_(WII_IPC_DVD, request.in_vectors[1].address == 0,
"DVDLowOpenPartition with ticket"); "DVDLowOpenPartition with ticket");
_dbg_assert_msg_(WII_IPC_DVD, CommandBuffer.InBuffer[2].m_Address == 0, _dbg_assert_msg_(WII_IPC_DVD, request.in_vectors[2].address == 0,
"DVDLowOpenPartition with cert chain"); "DVDLowOpenPartition with cert chain");
u64 const partition_offset = u64 const partition_offset = ((u64)Memory::Read_U32(request.in_vectors[0].address + 4) << 2);
((u64)Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address + 4) << 2);
DVDInterface::ChangePartition(partition_offset); DVDInterface::ChangePartition(partition_offset);
INFO_LOG(WII_IPC_DVD, "DVDLowOpenPartition: partition_offset 0x%016" PRIx64, partition_offset); INFO_LOG(WII_IPC_DVD, "DVDLowOpenPartition: partition_offset 0x%016" PRIx64, partition_offset);
// Read TMD to the buffer // Read TMD to the buffer
std::vector<u8> tmd_buffer = DVDInterface::GetVolume().GetTMD(); std::vector<u8> tmd_buffer = DVDInterface::GetVolume().GetTMD();
Memory::CopyToEmu(CommandBuffer.PayloadBuffer[0].m_Address, tmd_buffer.data(), Memory::CopyToEmu(request.io_vectors[0].address, tmd_buffer.data(), tmd_buffer.size());
tmd_buffer.size());
WII_IPC_HLE_Interface::ES_DIVerify(tmd_buffer); WII_IPC_HLE_Interface::ES_DIVerify(tmd_buffer);
ReturnValue = 1; return_value = 1;
}
break;
default:
ERROR_LOG(WII_IPC_DVD, "IOCtlV: %i", CommandBuffer.Parameter);
_dbg_assert_msg_(WII_IPC_DVD, 0, "IOCtlV: %i", CommandBuffer.Parameter);
break; break;
} }
default:
Memory::Write_U32(ReturnValue, _CommandAddress + 4); request.DumpUnknown(GetDeviceName(), LogTypes::WII_IPC_DVD);
}
request.SetReturnValue(return_value);
return GetDefaultReply(); return GetDefaultReply();
} }

View file

@ -27,13 +27,13 @@ public:
void DoState(PointerWrap& p) override; void DoState(PointerWrap& p) override;
IPCCommandResult IOCtl(u32 _CommandAddress) override; IPCCommandResult IOCtl(const IOSIOCtlRequest& request) override;
IPCCommandResult IOCtlV(u32 _CommandAddress) override; IPCCommandResult IOCtlV(const IOSIOCtlVRequest& request) override;
void FinishIOCtl(DVDInterface::DIInterruptType interrupt_type); void FinishIOCtl(DVDInterface::DIInterruptType interrupt_type);
private: private:
void StartIOCtl(u32 command_address); void StartIOCtl(const IOSIOCtlRequest& request);
std::deque<u32> m_commands_to_execute; std::deque<u32> m_commands_to_execute;
}; };