summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorPokechu22 <Pokechu022@gmail.com>2019-09-17 13:57:57 -0700
committerPokechu22 <Pokechu022@gmail.com>2020-01-04 11:43:32 -0800
commit6c0399103fc430a663b48211fafdcef1a4f79039 (patch)
treecc9b68e5d067bbaf63a2a4ec2ea43b13d155e934 /Source/Core
parent71e8fb278f72443a098bf4bd6d900cefd54e84ec (diff)
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.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Boot/Boot_BS2Emu.cpp7
-rw-r--r--Source/Core/Core/HW/DVD/DVDInterface.cpp19
-rw-r--r--Source/Core/Core/HW/DVD/DVDInterface.h4
-rw-r--r--Source/Core/Core/IOS/DI/DI.cpp50
-rw-r--r--Source/Core/Core/IOS/DI/DI.h7
5 files changed, 60 insertions, 27 deletions
diff --git a/Source/Core/Core/Boot/Boot_BS2Emu.cpp b/Source/Core/Core/Boot/Boot_BS2Emu.cpp
index 77fb61170e..a85a939e79 100644
--- a/Source/Core/Core/Boot/Boot_BS2Emu.cpp
+++ b/Source/Core/Core/Boot/Boot_BS2Emu.cpp
@@ -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
diff --git a/Source/Core/Core/HW/DVD/DVDInterface.cpp b/Source/Core/Core/HW/DVD/DVDInterface.cpp
index ad45814fee..0e4fdc5b5f 100644
--- a/Source/Core/Core/HW/DVD/DVDInterface.cpp
+++ b/Source/Core/Core/HW/DVD/DVDInterface.cpp
@@ -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)
{
diff --git a/Source/Core/Core/HW/DVD/DVDInterface.h b/Source/Core/Core/HW/DVD/DVDInterface.h
index 0242c29b29..c0bd1bd4d0 100644
--- a/Source/Core/Core/HW/DVD/DVDInterface.h
+++ b/Source/Core/Core/HW/DVD/DVDInterface.h
@@ -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);
diff --git a/Source/Core/Core/IOS/DI/DI.cpp b/Source/Core/Core/IOS/DI/DI.cpp
index 70a6038a47..7dc2f714e4 100644
--- a/Source/Core/Core/IOS/DI/DI.cpp
+++ b/Source/Core/Core/IOS/DI/DI.cpp
@@ -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
diff --git a/Source/Core/Core/IOS/DI/DI.h b/Source/Core/Core/IOS/DI/DI.h
index f52980f3ad..975b0adc51 100644
--- a/Source/Core/Core/IOS/DI/DI.h
+++ b/Source/Core/Core/IOS/DI/DI.h
@@ -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;
};