1 // Copyright 2008 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4 
5 #pragma once
6 
7 #include <memory>
8 #include <optional>
9 #include <string>
10 #include <vector>
11 
12 #include "Common/CommonTypes.h"
13 
14 class PointerWrap;
15 namespace DiscIO
16 {
17 class VolumeDisc;
18 struct Partition;
19 }  // namespace DiscIO
20 namespace MMIO
21 {
22 class Mapping;
23 }
24 
25 namespace DVDInterface
26 {
27 enum class DICommand : u8
28 {
29   Inquiry = 0x12,
30   ReportKey = 0xa4,
31   Read = 0xa8,
32   Seek = 0xab,
33   ReadDVDMetadata = 0xad,
34   ReadDVD = 0xd0,
35   ReadDVDConfig = 0xd1,
36   StopLaser = 0xd2,
37   Offset = 0xd9,
38   ReadBCA = 0xda,
39   RequestDiscStatus = 0xdb,
40   RequestRetryNumber = 0xdc,
41   SetMaximumRotation = 0xdd,
42   SerMeasControl = 0xdf,
43   RequestError = 0xe0,
44   AudioStream = 0xe1,
45   RequestAudioStatus = 0xe2,
46   StopMotor = 0xe3,
47   AudioBufferConfig = 0xe4,
48   Debug = 0xfe,
49   DebugUnlock = 0xff,
50   Unknown55 = 0x55,
51   UnknownEE = 0xee,
52 };
53 
54 // Disc drive state.
55 // Reported in error codes as 0 for Ready, and value-1 for the rest
56 // (i.e. Ready and ReadyNoReadsMade are both reported as 0)
57 enum class DriveState : u8
58 {
59   Ready = 0,
60   ReadyNoReadsMade = 1,
61   CoverOpened = 2,
62   DiscChangeDetected = 3,
63   NoMediumPresent = 4,
64   MotorStopped = 5,
65   DiscIdNotRead = 6
66 };
67 
68 // Actual drive error codes, which fill the remaining 3 bytes
69 // Numbers more or less match a SCSI sense key (1 nybble) followed by SCSI ASC/ASCQ (2 bytes).
70 enum class DriveError : u32
71 {
72   None = 0x00000,                  // No error.
73   MotorStopped = 0x20400,          // Motor stopped.
74   NoDiscID = 0x20401,              // Disk ID not read.
75   MediumNotPresent = 0x23a00,      // Medium not present / Cover opened.
76   SeekNotDone = 0x30200,           // No seek complete.
77   ReadError = 0x31100,             // Unrecovered read error.
78   ProtocolError = 0x40800,         // Transfer protocol error.
79   InvalidCommand = 0x52000,        // Invalid command operation code.
80   NoAudioBuf = 0x52001,            // Audio Buffer not set.
81   BlockOOB = 0x52100,              // Logical block address out of bounds.
82   InvalidField = 0x52400,          // Invalid field in command packet.
83   InvalidAudioCommand = 0x52401,   // Invalid audio command.
84   InvalidPeriod = 0x52402,         // Configuration out of permitted period.
85   EndOfUserArea = 0x56300,         // End of user area encountered on this track.
86   MediumChanged = 0x62800,         // Medium may have changed.
87   MediumRemovalRequest = 0xb5a01,  // Operator medium removal request.
88 };
89 
90 enum class DIInterruptType : int
91 {
92   DEINT = 0,
93   TCINT = 1,
94   BRKINT = 2,
95   CVRINT = 3,
96 };
97 
98 enum class ReplyType : u32
99 {
100   NoReply,
101   Interrupt,
102   IOS,
103   DTK,
104 };
105 
106 enum class EjectCause
107 {
108   User,
109   Software,
110 };
111 
112 void Init();
113 void ResetDrive(bool spinup);
114 void Shutdown();
115 void DoState(PointerWrap& p);
116 
117 void RegisterMMIO(MMIO::Mapping* mmio, u32 base);
118 
119 void SetDisc(std::unique_ptr<DiscIO::VolumeDisc> disc,
120              std::optional<std::vector<std::string>> auto_disc_change_paths);
121 bool IsDiscInside();
122 void EjectDisc(EjectCause cause);                        // Must only be called on the CPU thread
123 void ChangeDisc(const std::vector<std::string>& paths);  // Must only be called on the CPU thread
124 void ChangeDisc(const std::string& new_path);            // Must only be called on the CPU thread
125 bool AutoChangeDisc();                                   // Must only be called on the CPU thread
126 
127 // This function returns true and calls SConfig::SetRunningGameMetadata(Volume&, Partition&)
128 // if both of the following conditions are true:
129 // - A disc is inserted
130 // - The title_id argument doesn't contain a value, or its value matches the disc's title ID
131 bool UpdateRunningGameMetadata(std::optional<u64> title_id = {});
132 
133 // Direct access to DI for IOS HLE (simpler to implement than how real IOS accesses DI,
134 // and lets us skip encrypting/decrypting in some cases)
135 void ExecuteCommand(ReplyType reply_type);
136 void PerformDecryptingRead(u32 position, u32 length, u32 output_address,
137                            const DiscIO::Partition& partition, ReplyType reply_type);
138 // Exposed for use by emulated BS2; does not perform any checks on drive state
139 void AudioBufferConfig(bool enable_dtk, u8 dtk_buffer_length);
140 
141 void SetDriveState(DriveState state);
142 void SetDriveError(DriveError error);
143 
144 // Used by DVDThread
145 void FinishExecutingCommand(ReplyType reply_type, DIInterruptType interrupt_type, s64 cycles_late,
146                             const std::vector<u8>& data = std::vector<u8>());
147 
148 // Used by IOS HLE
149 void SetInterruptEnabled(DIInterruptType interrupt, bool enabled);
150 void ClearInterrupt(DIInterruptType interrupt);
151 
152 }  // end of namespace DVDInterface
153