mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
Split /dev/di commands from DVDInterface
The various ioctls sometimes have different arguments than the DI command registers, though they generally overlap. There are also a bunch of ioctls that don't even normally go into DVDInterface, just returning various data. Some of the implemented ioctls are new to Dolphin.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -24,38 +24,31 @@ class Mapping;
|
||||
|
||||
namespace DVDInterface
|
||||
{
|
||||
enum DICommand
|
||||
enum class DICommand : u8
|
||||
{
|
||||
DVDLowInquiry = 0x12,
|
||||
DVDLowReadDiskID = 0x70,
|
||||
DVDLowRead = 0x71,
|
||||
DVDLowWaitForCoverClose = 0x79,
|
||||
DVDLowGetCoverReg = 0x7a, // DVDLowPrepareCoverRegister?
|
||||
DVDLowNotifyReset = 0x7e,
|
||||
DVDLowReadDvdPhysical = 0x80,
|
||||
DVDLowReadDvdCopyright = 0x81,
|
||||
DVDLowReadDvdDiscKey = 0x82,
|
||||
DVDLowClearCoverInterrupt = 0x86,
|
||||
DVDLowGetCoverStatus = 0x88,
|
||||
DVDLowReset = 0x8a,
|
||||
DVDLowOpenPartition = 0x8b,
|
||||
DVDLowClosePartition = 0x8c,
|
||||
DVDLowUnencryptedRead = 0x8d,
|
||||
DVDLowEnableDvdVideo = 0x8e,
|
||||
DVDLowReportKey = 0xa4,
|
||||
DVDLowSeek = 0xab,
|
||||
DVDLowReadDvd = 0xd0,
|
||||
DVDLowReadDvdConfig = 0xd1,
|
||||
DVDLowStopLaser = 0xd2,
|
||||
DVDLowOffset = 0xd9,
|
||||
DVDLowReadDiskBca = 0xda,
|
||||
DVDLowRequestDiscStatus = 0xdb,
|
||||
DVDLowRequestRetryNumber = 0xdc,
|
||||
DVDLowSetMaximumRotation = 0xdd,
|
||||
DVDLowSerMeasControl = 0xdf,
|
||||
DVDLowRequestError = 0xe0,
|
||||
DVDLowStopMotor = 0xe3,
|
||||
DVDLowAudioBufferConfig = 0xe4
|
||||
Inquiry = 0x12,
|
||||
ReportKey = 0xa4,
|
||||
Read = 0xa8,
|
||||
Seek = 0xab,
|
||||
ReadDVDMetadata = 0xad,
|
||||
ReadDVD = 0xd0,
|
||||
ReadDVDConfig = 0xd1,
|
||||
StopLaser = 0xd2,
|
||||
Offset = 0xd9,
|
||||
ReadBCA = 0xda,
|
||||
RequestDiscStatus = 0xdb,
|
||||
RequestRetryNumber = 0xdc,
|
||||
SetMaximumRotation = 0xdd,
|
||||
SerMeasControl = 0xdf,
|
||||
RequestError = 0xe0,
|
||||
AudioStream = 0xe1,
|
||||
RequestAudioStatus = 0xe2,
|
||||
StopMotor = 0xe3,
|
||||
AudioBufferConfig = 0xe4,
|
||||
Debug = 0xfe,
|
||||
DebugUnlock = 0xff,
|
||||
Unknown55 = 0x55,
|
||||
UnknownEE = 0xee,
|
||||
};
|
||||
|
||||
// "low" error codes
|
||||
@@ -86,12 +79,12 @@ constexpr u32 ERROR_MEDIUM = 0x062800; // Medium may have changed.
|
||||
constexpr u32 ERROR_MEDIUM_REQ = 0x0b5a01; // Operator medium removal request.
|
||||
constexpr u32 HIGH_ERROR_MASK = 0x00ffffff;
|
||||
|
||||
enum DIInterruptType : int
|
||||
enum class DIInterruptType : int
|
||||
{
|
||||
INT_DEINT = 0,
|
||||
INT_TCINT = 1,
|
||||
INT_BRKINT = 2,
|
||||
INT_CVRINT = 3,
|
||||
DEINT = 0,
|
||||
TCINT = 1,
|
||||
BRKINT = 2,
|
||||
CVRINT = 3,
|
||||
};
|
||||
|
||||
enum class ReplyType : u32
|
||||
@@ -99,7 +92,7 @@ enum class ReplyType : u32
|
||||
NoReply,
|
||||
Interrupt,
|
||||
IOS,
|
||||
DTK
|
||||
DTK,
|
||||
};
|
||||
|
||||
enum class EjectCause
|
||||
@@ -132,8 +125,8 @@ 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(u32 command_0, u32 command_1, u32 command_2, u32 output_address,
|
||||
u32 output_length, bool reply_to_ios);
|
||||
void ExecuteCommand(ReplyType reply_type);
|
||||
void PerformDecryptingRead(u32 position, u32 length, u32 output_address, ReplyType reply_type);
|
||||
|
||||
void SetLowError(u32 low_error);
|
||||
void SetHighError(u32 high_error);
|
||||
@@ -142,4 +135,8 @@ void SetHighError(u32 high_error);
|
||||
void FinishExecutingCommand(ReplyType reply_type, DIInterruptType interrupt_type, s64 cycles_late,
|
||||
const std::vector<u8>& data = std::vector<u8>());
|
||||
|
||||
// Used by IOS HLE
|
||||
void SetInterruptEnabled(DIInterruptType interrupt, bool enabled);
|
||||
void ClearInterrupt(DIInterruptType interrupt);
|
||||
|
||||
} // end of namespace DVDInterface
|
||||
|
||||
@@ -354,8 +354,8 @@ static void FinishRead(u64 id, s64 cycles_late)
|
||||
}
|
||||
|
||||
// Notify the emulated software that the command has been executed
|
||||
DVDInterface::FinishExecutingCommand(request.reply_type, DVDInterface::INT_TCINT, cycles_late,
|
||||
buffer);
|
||||
DVDInterface::FinishExecutingCommand(request.reply_type, DVDInterface::DIInterruptType::TCINT,
|
||||
cycles_late, buffer);
|
||||
}
|
||||
|
||||
static void DVDThread()
|
||||
|
||||
+600
-38
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <deque>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
@@ -15,7 +16,16 @@ class PointerWrap;
|
||||
|
||||
namespace DVDInterface
|
||||
{
|
||||
enum DIInterruptType : int;
|
||||
enum class DIInterruptType : int;
|
||||
}
|
||||
namespace CoreTiming
|
||||
{
|
||||
struct EventType;
|
||||
}
|
||||
|
||||
namespace IOS::HLE
|
||||
{
|
||||
void Init();
|
||||
}
|
||||
|
||||
namespace IOS::HLE::Device
|
||||
@@ -25,16 +35,107 @@ class DI : public Device
|
||||
public:
|
||||
DI(Kernel& ios, const std::string& device_name);
|
||||
|
||||
static void InterruptFromDVDInterface(DVDInterface::DIInterruptType interrupt_type);
|
||||
|
||||
void DoState(PointerWrap& p) override;
|
||||
|
||||
IPCCommandResult Open(const OpenRequest& request) override;
|
||||
IPCCommandResult IOCtl(const IOCtlRequest& request) override;
|
||||
IPCCommandResult IOCtlV(const IOCtlVRequest& request) override;
|
||||
|
||||
void FinishIOCtl(DVDInterface::DIInterruptType interrupt_type);
|
||||
enum class DIIoctl : u32
|
||||
{
|
||||
DVDLowInquiry = 0x12,
|
||||
DVDLowReadDiskID = 0x70,
|
||||
DVDLowRead = 0x71,
|
||||
DVDLowWaitForCoverClose = 0x79,
|
||||
DVDLowGetCoverRegister = 0x7a, // DVDLowPrepareCoverRegister
|
||||
DVDLowNotifyReset = 0x7e,
|
||||
DVDLowSetSpinupFlag = 0x7f,
|
||||
DVDLowReadDvdPhysical = 0x80,
|
||||
DVDLowReadDvdCopyright = 0x81,
|
||||
DVDLowReadDvdDiscKey = 0x82,
|
||||
DVDLowGetLength = 0x83,
|
||||
DVDLowGetImmBuf = 0x84, // Unconfirmed name
|
||||
DVDLowUnmaskCoverInterrupt = 0x85,
|
||||
DVDLowClearCoverInterrupt = 0x86,
|
||||
// 0x87 is a dummied out command
|
||||
DVDLowGetCoverStatus = 0x88,
|
||||
DVDLowEnableCoverInterrupt = 0x89, // Unconfirmed name
|
||||
DVDLowReset = 0x8a,
|
||||
DVDLowOpenPartition = 0x8b, // ioctlv only
|
||||
DVDLowClosePartition = 0x8c,
|
||||
DVDLowUnencryptedRead = 0x8d,
|
||||
DVDLowEnableDvdVideo = 0x8e,
|
||||
DVDLowGetNoDiscOpenPartitionParams = 0x90, // ioctlv, dummied out
|
||||
DVDLowNoDiscOpenPartition = 0x91, // ioctlv, dummied out
|
||||
DVDLowGetNoDiscBufferSizes = 0x92, // ioctlv, dummied out
|
||||
DVDLowOpenPartitionWithTmdAndTicket = 0x93, // ioctlv
|
||||
DVDLowOpenPartitionWithTmdAndTicketView = 0x94, // ioctlv
|
||||
DVDLowGetStatusRegister = 0x95, // DVDLowPrepareStatusRegsiter
|
||||
DVDLowGetControlRegister = 0x96, // DVDLowPrepareControlRegister
|
||||
DVDLowReportKey = 0xa4,
|
||||
// 0xa8 is unusable externally
|
||||
DVDLowSeek = 0xab,
|
||||
DVDLowReadDvd = 0xd0,
|
||||
DVDLowReadDvdConfig = 0xd1,
|
||||
DVDLowStopLaser = 0xd2,
|
||||
DVDLowOffset = 0xd9,
|
||||
DVDLowReadDiskBca = 0xda,
|
||||
DVDLowRequestDiscStatus = 0xdb,
|
||||
DVDLowRequestRetryNumber = 0xdc,
|
||||
DVDLowSetMaximumRotation = 0xdd,
|
||||
DVDLowSerMeasControl = 0xdf,
|
||||
DVDLowRequestError = 0xe0,
|
||||
DVDLowAudioStream = 0xe1,
|
||||
DVDLowRequestAudioStatus = 0xe2,
|
||||
DVDLowStopMotor = 0xe3,
|
||||
DVDLowAudioBufferConfig = 0xe4,
|
||||
};
|
||||
|
||||
enum class DIResult : s32
|
||||
{
|
||||
Success = 1,
|
||||
DriveError = 2,
|
||||
CoverClosed = 4,
|
||||
ReadTimedOut = 16,
|
||||
SecurityError = 32,
|
||||
VerifyError = 64,
|
||||
BadArgument = 128,
|
||||
};
|
||||
|
||||
private:
|
||||
void StartIOCtl(const IOCtlRequest& request);
|
||||
struct ExecutingCommandInfo
|
||||
{
|
||||
ExecutingCommandInfo() {}
|
||||
ExecutingCommandInfo(u32 request_address)
|
||||
: m_request_address(request_address), m_copy_diimmbuf(false)
|
||||
{
|
||||
}
|
||||
u32 m_request_address;
|
||||
bool m_copy_diimmbuf;
|
||||
};
|
||||
|
||||
friend void ::IOS::HLE::Init();
|
||||
|
||||
void ProcessQueuedIOCtl();
|
||||
std::optional<DIResult> StartIOCtl(const IOCtlRequest& request);
|
||||
std::optional<DIResult> WriteIfFits(const IOCtlRequest& request, u32 value);
|
||||
std::optional<DIResult> StartDMATransfer(u32 command_length, const IOCtlRequest& request);
|
||||
std::optional<DIResult> StartImmediateTransfer(const IOCtlRequest& request,
|
||||
bool write_to_buf = true);
|
||||
|
||||
void InitializeIfFirstTime();
|
||||
void ResetDIRegisters();
|
||||
static void FinishDICommandCallback(u64 userdata, s64 ticksbehind);
|
||||
void FinishDICommand(DIResult result);
|
||||
|
||||
static CoreTiming::EventType* s_finish_executing_di_command;
|
||||
|
||||
std::optional<ExecutingCommandInfo> m_executing_command;
|
||||
std::deque<u32> m_commands_to_execute;
|
||||
|
||||
bool m_has_initialized = false;
|
||||
u32 m_last_length = 0;
|
||||
};
|
||||
} // namespace IOS::HLE::Device
|
||||
|
||||
@@ -782,6 +782,9 @@ void Init()
|
||||
device->EventNotify();
|
||||
});
|
||||
|
||||
Device::DI::s_finish_executing_di_command =
|
||||
CoreTiming::RegisterEvent("FinishDICommand", Device::DI::FinishDICommandCallback);
|
||||
|
||||
// Start with IOS80 to simulate part of the Wii boot process.
|
||||
s_ios = std::make_unique<EmulationKernel>(Titles::SYSTEM_MENU_IOS);
|
||||
// On a Wii, boot2 launches the system menu IOS, which then launches the system menu
|
||||
|
||||
Reference in New Issue
Block a user