mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-24 23:11:14 +01:00
Handle partitions in /dev/di, not DVDInterface
Partitions are Wii-exclusive, and don't happen at the DVDInterface level in IOS. This isn't quite the cleanest fix, but it gets rid of the assumption that a partition is open on starting the game at least.
This commit is contained in:
parent
71e8fb278f
commit
6c0399103f
@ -22,6 +22,7 @@
|
||||
#include "Core/HW/DVD/DVDInterface.h"
|
||||
#include "Core/HW/EXI/EXI_DeviceIPL.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/IOS/DI/DI.h"
|
||||
#include "Core/IOS/ES/ES.h"
|
||||
#include "Core/IOS/ES/Formats.h"
|
||||
#include "Core/IOS/FS/FileSystem.h"
|
||||
@ -421,6 +422,12 @@ bool CBoot::EmulatedBS2_Wii(const DiscIO::VolumeDisc& volume)
|
||||
if (!SetupWiiMemory(console_type) || !IOS::HLE::GetIOS()->BootIOS(tmd.GetIOSId()))
|
||||
return false;
|
||||
|
||||
auto di = std::static_pointer_cast<IOS::HLE::Device::DI>(
|
||||
IOS::HLE::GetIOS()->GetDeviceByName("/dev/di"));
|
||||
|
||||
di->InitializeIfFirstTime();
|
||||
di->ChangePartition(data_partition);
|
||||
|
||||
DVDReadDiscID(volume, 0x00000000);
|
||||
|
||||
// This is some kind of consistency check that is compared to the 0x00
|
||||
|
@ -161,7 +161,6 @@ static u8 s_dtk_buffer_length = 0; // TODO: figure out how this affects the reg
|
||||
|
||||
// Disc drive state
|
||||
static u32 s_error_code = 0;
|
||||
static DiscIO::Partition s_current_partition;
|
||||
|
||||
// Disc drive timing
|
||||
static u64 s_read_buffer_start_time;
|
||||
@ -223,7 +222,6 @@ void DoState(PointerWrap& p)
|
||||
p.Do(s_dtk_buffer_length);
|
||||
|
||||
p.Do(s_error_code);
|
||||
p.Do(s_current_partition);
|
||||
|
||||
p.Do(s_read_buffer_start_time);
|
||||
p.Do(s_read_buffer_end_time);
|
||||
@ -426,8 +424,6 @@ void SetDisc(std::unique_ptr<DiscIO::VolumeDisc> disc,
|
||||
{
|
||||
bool had_disc = IsDiscInside();
|
||||
bool has_disc = static_cast<bool>(disc);
|
||||
if (has_disc)
|
||||
s_current_partition = disc->GetGamePartition();
|
||||
|
||||
if (auto_disc_change_paths)
|
||||
{
|
||||
@ -548,12 +544,8 @@ bool UpdateRunningGameMetadata(std::optional<u64> title_id)
|
||||
if (!DVDThread::HasDisc())
|
||||
return false;
|
||||
|
||||
return DVDThread::UpdateRunningGameMetadata(s_current_partition, title_id);
|
||||
}
|
||||
|
||||
void ChangePartition(const DiscIO::Partition& partition)
|
||||
{
|
||||
s_current_partition = partition;
|
||||
return DVDThread::UpdateRunningGameMetadata(IOS::HLE::Device::DI::GetCurrentPartition(),
|
||||
title_id);
|
||||
}
|
||||
|
||||
void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||
@ -1125,14 +1117,15 @@ void ExecuteCommand(ReplyType reply_type)
|
||||
}
|
||||
}
|
||||
|
||||
void PerformDecryptingRead(u32 position, u32 length, u32 output_address, ReplyType reply_type)
|
||||
void PerformDecryptingRead(u32 position, u32 length, u32 output_address,
|
||||
const DiscIO::Partition& partition, ReplyType reply_type)
|
||||
{
|
||||
DIInterruptType interrupt_type = DIInterruptType::TCINT;
|
||||
s_can_configure_dtk = false;
|
||||
|
||||
const bool command_handled_by_thread =
|
||||
ExecuteReadCommand(static_cast<u64>(position) << 2, output_address, length, length,
|
||||
s_current_partition, reply_type, &interrupt_type);
|
||||
ExecuteReadCommand(static_cast<u64>(position) << 2, output_address, length, length, partition,
|
||||
reply_type, &interrupt_type);
|
||||
|
||||
if (!command_handled_by_thread)
|
||||
{
|
||||
|
@ -124,9 +124,9 @@ bool UpdateRunningGameMetadata(std::optional<u64> title_id = {});
|
||||
|
||||
// Direct access to DI for IOS HLE (simpler to implement than how real IOS accesses DI,
|
||||
// and lets us skip encrypting/decrypting in some cases)
|
||||
void ChangePartition(const DiscIO::Partition& partition);
|
||||
void ExecuteCommand(ReplyType reply_type);
|
||||
void PerformDecryptingRead(u32 position, u32 length, u32 output_address, ReplyType reply_type);
|
||||
void PerformDecryptingRead(u32 position, u32 length, u32 output_address,
|
||||
const DiscIO::Partition& partition, ReplyType reply_type);
|
||||
// Exposed for use by emulated BS2; does not perform any checks on drive state
|
||||
void AudioBufferConfig(bool enable_dtk, u8 dtk_buffer_length);
|
||||
|
||||
|
@ -52,6 +52,7 @@ void DI::DoState(PointerWrap& p)
|
||||
DoStateShared(p);
|
||||
p.Do(m_commands_to_execute);
|
||||
p.Do(m_executing_command);
|
||||
p.Do(m_current_partition);
|
||||
p.Do(m_has_initialized);
|
||||
p.Do(m_last_length);
|
||||
}
|
||||
@ -162,11 +163,15 @@ std::optional<DI::DIResult> DI::StartIOCtl(const IOCtlRequest& request)
|
||||
// }
|
||||
case DIIoctl::DVDLowRead:
|
||||
{
|
||||
// TODO. Needs to include decryption.
|
||||
const u32 length = Memory::Read_U32(request.buffer_in + 4);
|
||||
const u32 position = Memory::Read_U32(request.buffer_in + 8);
|
||||
INFO_LOG(IOS_DI, "DVDLowRead: offset 0x%08x (byte 0x%09" PRIx64 "), length 0x%x", position,
|
||||
static_cast<u64>(position) << 2, length);
|
||||
if (m_current_partition == DiscIO::PARTITION_NONE)
|
||||
{
|
||||
ERROR_LOG(IOS_DI, "Attempted to perform a decrypting read when no partition is open!");
|
||||
return DIResult::SecurityError;
|
||||
}
|
||||
if (request.buffer_out_size < length)
|
||||
{
|
||||
WARN_LOG(IOS_DI,
|
||||
@ -176,7 +181,7 @@ std::optional<DI::DIResult> DI::StartIOCtl(const IOCtlRequest& request)
|
||||
return DIResult::SecurityError;
|
||||
}
|
||||
m_last_length = position; // An actual mistake in IOS
|
||||
DVDInterface::PerformDecryptingRead(position, length, request.buffer_out,
|
||||
DVDInterface::PerformDecryptingRead(position, length, request.buffer_out, m_current_partition,
|
||||
DVDInterface::ReplyType::IOS);
|
||||
return {};
|
||||
}
|
||||
@ -194,7 +199,6 @@ std::optional<DI::DIResult> DI::StartIOCtl(const IOCtlRequest& request)
|
||||
case DIIoctl::DVDLowNotifyReset:
|
||||
INFO_LOG(IOS_DI, "DVDLowNotifyReset");
|
||||
ResetDIRegisters();
|
||||
// Should also reset current partition and such
|
||||
return DIResult::Success;
|
||||
case DIIoctl::DVDLowSetSpinupFlag:
|
||||
ERROR_LOG(IOS_DI, "DVDLowSetSpinupFlag - not a valid command, rejecting");
|
||||
@ -258,7 +262,6 @@ std::optional<DI::DIResult> DI::StartIOCtl(const IOCtlRequest& request)
|
||||
INFO_LOG(IOS_DI, "DVDLowReset %s spinup", spinup ? "with" : "without");
|
||||
DVDInterface::Reset(spinup);
|
||||
ResetDIRegisters();
|
||||
// Should also reset current partition and such
|
||||
return DIResult::Success;
|
||||
}
|
||||
case DIIoctl::DVDLowOpenPartition:
|
||||
@ -266,7 +269,7 @@ std::optional<DI::DIResult> DI::StartIOCtl(const IOCtlRequest& request)
|
||||
return DIResult::SecurityError;
|
||||
case DIIoctl::DVDLowClosePartition:
|
||||
INFO_LOG(IOS_DI, "DVDLowClosePartition");
|
||||
DVDInterface::ChangePartition(DiscIO::PARTITION_NONE);
|
||||
ChangePartition(DiscIO::PARTITION_NONE);
|
||||
return DIResult::Success;
|
||||
case DIIoctl::DVDLowUnencryptedRead:
|
||||
{
|
||||
@ -614,23 +617,29 @@ IPCCommandResult DI::IOCtlV(const IOCtlVRequest& request)
|
||||
request.in_vectors.size(), request.io_vectors.size());
|
||||
break;
|
||||
}
|
||||
DEBUG_ASSERT_MSG(IOS_DI, request.in_vectors[1].address == 0, "DVDLowOpenPartition with ticket");
|
||||
DEBUG_ASSERT_MSG(IOS_DI, request.in_vectors[2].address == 0,
|
||||
"DVDLowOpenPartition with cert chain");
|
||||
if (request.in_vectors[1].address != 0)
|
||||
{
|
||||
ERROR_LOG(IOS_DI,
|
||||
"DVDLowOpenPartition with ticket - not implemented, ignoring ticket parameter");
|
||||
}
|
||||
if (request.in_vectors[2].address != 0)
|
||||
{
|
||||
ERROR_LOG(IOS_DI,
|
||||
"DVDLowOpenPartition with cert chain - not implemented, ignoring certs parameter");
|
||||
}
|
||||
|
||||
const u64 partition_offset =
|
||||
static_cast<u64>(Memory::Read_U32(request.in_vectors[0].address + 4)) << 2;
|
||||
const DiscIO::Partition partition(partition_offset);
|
||||
DVDInterface::ChangePartition(partition);
|
||||
ChangePartition(DiscIO::Partition(partition_offset));
|
||||
|
||||
INFO_LOG(IOS_DI, "DVDLowOpenPartition: partition_offset 0x%09" PRIx64, partition_offset);
|
||||
|
||||
// Read TMD to the buffer
|
||||
const IOS::ES::TMDReader tmd = DVDThread::GetTMD(partition);
|
||||
const IOS::ES::TMDReader tmd = DVDThread::GetTMD(m_current_partition);
|
||||
const std::vector<u8>& raw_tmd = tmd.GetBytes();
|
||||
Memory::CopyToEmu(request.io_vectors[0].address, raw_tmd.data(), raw_tmd.size());
|
||||
|
||||
ReturnCode es_result = m_ios.GetES()->DIVerify(tmd, DVDThread::GetTicket(partition));
|
||||
ReturnCode es_result = m_ios.GetES()->DIVerify(tmd, DVDThread::GetTicket(m_current_partition));
|
||||
Memory::Write_U32(es_result, request.io_vectors[1].address);
|
||||
|
||||
return_value = DIResult::Success;
|
||||
@ -661,6 +670,21 @@ IPCCommandResult DI::IOCtlV(const IOCtlVRequest& request)
|
||||
return GetDefaultReply(static_cast<s32>(return_value));
|
||||
}
|
||||
|
||||
void DI::ChangePartition(const DiscIO::Partition partition)
|
||||
{
|
||||
m_current_partition = partition;
|
||||
}
|
||||
|
||||
DiscIO::Partition DI::GetCurrentPartition()
|
||||
{
|
||||
auto di = IOS::HLE::GetIOS()->GetDeviceByName("/dev/di");
|
||||
// Note that this function is called in Gamecube mode for UpdateRunningGameMetadata,
|
||||
// so both cases are hit in normal circumstances.
|
||||
if (!di)
|
||||
return DiscIO::PARTITION_NONE;
|
||||
return std::static_pointer_cast<DI>(di)->m_current_partition;
|
||||
}
|
||||
|
||||
void DI::InitializeIfFirstTime()
|
||||
{
|
||||
// Match the behavior of Nintendo's initDvdDriverStage2, which is called the first time
|
||||
@ -687,5 +711,7 @@ void DI::ResetDIRegisters()
|
||||
DVDInterface::SetInterruptEnabled(DVDInterface::DIInterruptType::TCINT, true);
|
||||
DVDInterface::SetInterruptEnabled(DVDInterface::DIInterruptType::DEINT, true);
|
||||
DVDInterface::SetInterruptEnabled(DVDInterface::DIInterruptType::CVRINT, false);
|
||||
// Close the current partition, if there is one
|
||||
ChangePartition(DiscIO::PARTITION_NONE);
|
||||
}
|
||||
} // namespace IOS::HLE::Device
|
||||
|
@ -11,7 +11,9 @@
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Core/IOS/Device.h"
|
||||
#include "Core/IOS/IOS.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
|
||||
class CBoot;
|
||||
class PointerWrap;
|
||||
|
||||
namespace DVDInterface
|
||||
@ -36,6 +38,7 @@ public:
|
||||
DI(Kernel& ios, const std::string& device_name);
|
||||
|
||||
static void InterruptFromDVDInterface(DVDInterface::DIInterruptType interrupt_type);
|
||||
static DiscIO::Partition GetCurrentPartition();
|
||||
|
||||
void DoState(PointerWrap& p) override;
|
||||
|
||||
@ -116,6 +119,7 @@ private:
|
||||
bool m_copy_diimmbuf;
|
||||
};
|
||||
|
||||
friend class ::CBoot;
|
||||
friend void ::IOS::HLE::Init();
|
||||
|
||||
void ProcessQueuedIOCtl();
|
||||
@ -125,6 +129,7 @@ private:
|
||||
std::optional<DIResult> StartImmediateTransfer(const IOCtlRequest& request,
|
||||
bool write_to_buf = true);
|
||||
|
||||
void ChangePartition(const DiscIO::Partition partition);
|
||||
void InitializeIfFirstTime();
|
||||
void ResetDIRegisters();
|
||||
static void FinishDICommandCallback(u64 userdata, s64 ticksbehind);
|
||||
@ -135,6 +140,8 @@ private:
|
||||
std::optional<ExecutingCommandInfo> m_executing_command;
|
||||
std::deque<u32> m_commands_to_execute;
|
||||
|
||||
DiscIO::Partition m_current_partition = DiscIO::PARTITION_NONE;
|
||||
|
||||
bool m_has_initialized = false;
|
||||
u32 m_last_length = 0;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user