fake out gcos into thinking it is using dvd drive debug commands

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3093 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Shawn Hoffman 2009-04-27 16:55:20 +00:00
parent 1990c79c25
commit ae41086ec8
2 changed files with 154 additions and 51 deletions

View File

@ -74,6 +74,15 @@ enum DVDInterruptType
INT_CVRINT = 3, INT_CVRINT = 3,
}; };
// debug commands which may be ORd
enum
{
STOP_DRIVE = 0,
START_DRIVE = 0x100,
ACCEPT_COPY = 0x4000,
DISC_CHECK = 0x8000,
};
// DI Status Register // DI Status Register
union UDISR union UDISR
{ {
@ -101,7 +110,7 @@ union UDICVR
{ {
unsigned CVR : 1; // 0: Cover closed 1: Cover open unsigned CVR : 1; // 0: Cover closed 1: Cover open
unsigned CVRINTMASK : 1; // 1: Interrupt enabled; unsigned CVRINTMASK : 1; // 1: Interrupt enabled;
unsigned CVRINT : 1; // 1: Interrupt clear unsigned CVRINT : 1; // r 1: Interrupt requested w 1: Interrupt clear
unsigned : 29; unsigned : 29;
}; };
UDICVR() {Hex = 0;} UDICVR() {Hex = 0;}
@ -156,6 +165,14 @@ union UDIConfigRegister
UDIConfigRegister(u32 _hex) {Hex = _hex;} UDIConfigRegister(u32 _hex) {Hex = _hex;}
}; };
// HACK to allow multi-command debug-mode transfers
struct SDIDebugTransfer
{
u32 Address;
u16 Length;
bool InProgress;
};
// hardware registers // hardware registers
struct DVDMemStruct struct DVDMemStruct
{ {
@ -170,12 +187,13 @@ struct DVDMemStruct
u32 AudioStart; u32 AudioStart;
u32 AudioPos; u32 AudioPos;
u32 AudioLength; u32 AudioLength;
SDIDebugTransfer DebugTransfer;
}; };
// STATE_TO_SAVE // STATE_TO_SAVE
DVDMemStruct dvdMem; DVDMemStruct dvdMem;
u32 g_ErrorCode = 0x00; u32 g_ErrorCode = 0x00;
bool g_bDiscInside = true; bool g_bDiscInside = false;
Common::CriticalSection dvdread_section; Common::CriticalSection dvdread_section;
@ -221,24 +239,12 @@ void SetDiscInside(bool _DiscInside)
void SetLidOpen(bool _bOpen) void SetLidOpen(bool _bOpen)
{ {
if (_bOpen)
dvdMem.CoverReg.Hex = 0x7;
else
dvdMem.CoverReg.Hex = 0x0;
GenerateDVDInterrupt(INT_CVRINT);
//Todo: Make this work perhaps?
/*
if (_bOpen) if (_bOpen)
dvdMem.CoverReg.CVR = 1; dvdMem.CoverReg.CVR = 1;
else else
dvdMem.CoverReg.CVR = 0; dvdMem.CoverReg.CVR = 0;
*/
UpdateInterrupts(); GenerateDVDInterrupt(INT_CVRINT);
} }
bool IsLidOpen() bool IsLidOpen()
@ -345,20 +351,13 @@ void Write32(const u32 _iValue, const u32 _iAddress)
case DI_COVER_REGISTER: case DI_COVER_REGISTER:
{ {
/*
// Todo: fix this, it doesn't work properly
UDICVR tmpCoverReg(_iValue); UDICVR tmpCoverReg(_iValue);
dvdMem.CoverReg.CVR = 0;
dvdMem.CoverReg.CVRINTMASK = tmpCoverReg.CVRINTMASK; dvdMem.CoverReg.CVRINTMASK = tmpCoverReg.CVRINTMASK;
if (tmpCoverReg.CVRINT) dvdMem.CoverReg.CVRINT = 0;
if (tmpCoverReg.CVRINT) dvdMem.CoverReg.CVRINT = 0;
UpdateInterrupts(); UpdateInterrupts();
_dbg_assert_(DVDINTERFACE, (tmpCoverReg.CVR == 0));
*/
} }
break; break;
@ -430,8 +429,19 @@ bool m_bStream = false;
void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg) void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg)
{ {
_dbg_assert_(DVDINTERFACE, _DMAControlReg.RW == 0); // only DVD to Memory _dbg_assert_(DVDINTERFACE, _DMAControlReg.RW == 0); // only DVD to Memory
// Catch multi-command transfers here
if (dvdMem.DebugTransfer.InProgress)
{
dvdMem.DebugTransfer.InProgress = false;
// If we ever need to actually read/write the drive ram/cache, here would be the place
// Up to 12bytes can be written at once (dvdMem.Command[0] through dvdMem.Command[2])
INFO_LOG(DVDINTERFACE, "\t queued cmd: 0x%08x @ 0x%08x NOT IMPLEMENTED",
dvdMem.Command[0], dvdMem.DebugTransfer.Address);
}
else
{ // The huge switch is in this else!
switch ((dvdMem.Command[0] & 0xFF000000) >> 24) switch ((dvdMem.Command[0] & 0xFF000000) >> 24)
{ {
//========================================================================================================= //=========================================================================================================
@ -448,25 +458,34 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg)
// 0008-001F padding(0) // 0008-001F padding(0)
//========================================================================================================= //=========================================================================================================
case 0x12: case 0x12:
{ {
#if MAX_LOGLEVEL >= INFO_LEVEL // small safety check, dunno if it's needed
u32 offset = dvdMem.Command[1]; if ((dvdMem.Command[1] == 0) && (dvdMem.DMALength.Length == 0x20))
// u32 sourcelength = dvdMem.Command[2];
#endif
u32 destbuffer = dvdMem.DMAAddress.Address;
u32 destlength = dvdMem.DMALength.Length;
dvdMem.DMALength.Length = 0;
INFO_LOG(DVDINTERFACE, "[WARNING] DVD: Get drive info offset=%08x, destbuffer=%08x, destlength=%08x", offset * 4, destbuffer, destlength);
// metroid uses this...
for (unsigned int i = 0; i < destlength / 4; i++)
{ {
Memory::Write_U32(0, destbuffer + i * 4); u8* driveInfo = Memory::GetPointer(dvdMem.DMAAddress.Address);
// gives the correct output in GCOS - 06 2001/08 (61)
// there may be other stuff missing ?
driveInfo[4] = 0x20;
driveInfo[5] = 0x01;
driveInfo[6] = 0x06;
driveInfo[7] = 0x08;
driveInfo[8] = 0x61;
// Just for fun
INFO_LOG(DVDINTERFACE, "Drive Info: %02x %02x%02x/%02x (%02x)",
driveInfo[6], driveInfo[4], driveInfo[5], driveInfo[7], driveInfo[8]);
} }
} }
break; break;
//=========================================================================================================
// SET EXTENSION
// Apparently the drive needs certain flags set explicitly?
//=========================================================================================================
case 0x55:
INFO_LOG(DVDINTERFACE, "SetExtension %x", _DMAControlReg);
break;
//========================================================================================================= //=========================================================================================================
// READ (DMA) // READ (DMA)
// Command/Subcommand/Padding <- A8000000 // Command/Subcommand/Padding <- A8000000
@ -480,18 +499,21 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg)
{ {
u32 iDVDOffset = dvdMem.Command[1] << 2; u32 iDVDOffset = dvdMem.Command[1] << 2;
u32 iSrcLength = dvdMem.Command[2]; u32 iSrcLength = dvdMem.Command[2];
if (false) { iSrcLength++; } // avoid warning << wtf is this?
INFO_LOG(DVDINTERFACE, "DVD: Read ISO: DVDOffset=%08x, DMABuffer=%08x, SrcLength=%08x, DMALength=%08x",iDVDOffset,dvdMem.DMAAddress.Address,iSrcLength,dvdMem.DMALength.Length); INFO_LOG(DVDINTERFACE, "Read ISO: DVDOffset=%08x, DMABuffer=%08x, SrcLength=%08x, DMALength=%08x",
iDVDOffset, dvdMem.DMAAddress.Address, iSrcLength, dvdMem.DMALength.Length);
_dbg_assert_(DVDINTERFACE, iSrcLength == dvdMem.DMALength.Length); _dbg_assert_(DVDINTERFACE, iSrcLength == dvdMem.DMALength.Length);
if (DVDRead(iDVDOffset, dvdMem.DMAAddress.Address, dvdMem.DMALength.Length) != true) if (!DVDRead(iDVDOffset, dvdMem.DMAAddress.Address, dvdMem.DMALength.Length))
{ {
PanicAlert("Cant read from DVD_Plugin - DVD-Interface: Fatal Error"); PanicAlert("Cant read from DVD_Plugin - DVD-Interface: Fatal Error");
} }
} }
else else
{ {
// there is no disc to read // there is no disc to read
_DMAControlReg.TSTART = 0;
dvdMem.DMALength.Length = 0;
GenerateDVDInterrupt(INT_DEINT); GenerateDVDInterrupt(INT_DEINT);
g_ErrorCode = 0x03023A00; g_ErrorCode = 0x03023A00;
return; return;
@ -509,7 +531,7 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg)
#if MAX_LOGLEVEL >= DEBUG_LEVEL #if MAX_LOGLEVEL >= DEBUG_LEVEL
u32 offset = dvdMem.Command[1] << 2; u32 offset = dvdMem.Command[1] << 2;
#endif #endif
DEBUG_LOG(DVDINTERFACE, "DVD: Seek: offset=%08x (ignoring)", offset); DEBUG_LOG(DVDINTERFACE, "Seek: offset=%08x (ignoring)", offset);
} }
break; break;
@ -518,7 +540,7 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg)
// Command/Subcommand/Padding <- E0000000 // Command/Subcommand/Padding <- E0000000
//========================================================================================================= //=========================================================================================================
case 0xE0: case 0xE0:
ERROR_LOG(DVDINTERFACE, "DVD: Requesting error"); ERROR_LOG(DVDINTERFACE, "Requesting error");
dvdMem.Immediate = g_ErrorCode; dvdMem.Immediate = g_ErrorCode;
break; break;
@ -550,7 +572,8 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg)
m_bStream = true; m_bStream = true;
DEBUG_LOG(DVDINTERFACE, "DVD(Audio) Stream subcmd = %02x offset = %08x length=%08x", subCommand, dvdMem.AudioPos, dvdMem.AudioLength); DEBUG_LOG(DVDINTERFACE, "DVD(Audio) Stream subcmd = %02x offset = %08x length=%08x",
subCommand, dvdMem.AudioPos, dvdMem.AudioLength);
} }
} }
break; break;
@ -574,7 +597,7 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg)
// Command/Subcommand/Padding <- E3000000 // Command/Subcommand/Padding <- E3000000
//========================================================================================================= //=========================================================================================================
case 0xE3: case 0xE3:
DEBUG_LOG(DVDINTERFACE, "DVD: Stop motor"); DEBUG_LOG(DVDINTERFACE, "Stop motor");
break; break;
//========================================================================================================= //=========================================================================================================
@ -595,14 +618,93 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg)
}*/ }*/
break; break;
//=========================================================================================================
// SET STATUS
//=========================================================================================================
case 0xEE:
INFO_LOG(DVDINTERFACE, "SetStatus %x", _DMAControlReg);
break;
//=========================================================================================================
// DEBUG COMMANDS
// Subcommands:
// 0x00: ?
// 0x01: read/write memory/cache
// 0x10: ?
// 0x11: stop/start/accept copy/disk check CAN BE OR'd!
// 0x12: jump (jsr) to address
//=========================================================================================================
case 0xFE:
{
u8 subCommand = (dvdMem.Command[0] & 0x00FF0000) >> 16;
u16 argument = (u16)(dvdMem.Command[0] & 0x0000FFFF);
switch (subCommand)
{
case 0x01:
{
dvdMem.DebugTransfer.Address = dvdMem.Command[1];
dvdMem.DebugTransfer.Length = dvdMem.Command[2] >> 16; // can be up to 12 bytes
INFO_LOG(DVDINTERFACE, "Next cmd will %s %i bytes to drive %s @ 0x%08x",
(argument & 0x100) ? "write" : "read", dvdMem.DebugTransfer.Length,
(argument & 0x8000) ? "cache" : "mem", dvdMem.DebugTransfer.Address);
dvdMem.DebugTransfer.InProgress = true;
}
break;
case 0x11:
char flags[256];
sprintf(flags, "%s%s%s%s",
(argument & STOP_DRIVE) ? "StopDrive " : "",
(argument & START_DRIVE) ? "StartDrive " : "",
(argument & ACCEPT_COPY) ? "AcceptCopy " : "",
(argument & DISC_CHECK) ? "DiscCheck" : "");
INFO_LOG(DVDINTERFACE, "Debug cmd(s): %s", flags);
break;
default:
WARN_LOG(DVDINTERFACE, "Unsupported DVD Drive debug command 0x%08x", dvdMem.Command[0]);
break;
}
}
break;
//=========================================================================================================
// UNLOCK COMMANDS 1: "MATSHITA" 2: "DVD-GAME"
// LOL
//=========================================================================================================
case 0xFF:
{
if (dvdMem.Command[0] == 0xFF014D41
&& dvdMem.Command[1] == 0x54534849
&& dvdMem.Command[2] == 0x54410200)
{
INFO_LOG(DVDINTERFACE, "Unlock test 1 passed");
}
else if (dvdMem.Command[0] == 0xFF004456
&& dvdMem.Command[1] == 0x442D4741
&& dvdMem.Command[2] == 0x4D450300)
{
INFO_LOG(DVDINTERFACE, "Unlock test 2 passed");
}
else
{
INFO_LOG(DVDINTERFACE, "Unlock test failed");
}
}
break;
//========================================================================================================= //=========================================================================================================
// UNKNOWN DVD COMMAND // UNKNOWN DVD COMMAND
//========================================================================================================= //=========================================================================================================
default: default:
PanicAlert("DVD - Unknown DVD command %08x - fatal error", dvdMem.Command[0]); PanicAlert("Unknown DVD command %08x - fatal error", dvdMem.Command[0]);
_dbg_assert_(DVDINTERFACE, 0); _dbg_assert_(DVDINTERFACE, 0);
break; break;
} }
} // end of if(dvdMem.DebugTransfer.InProgress)
// transfer is done // transfer is done
_DMAControlReg.TSTART = 0; _DMAControlReg.TSTART = 0;

View File

@ -320,11 +320,12 @@ void Write16(const u16 _iValue, const u32 _iAddress)
break; break;
case VI_VERTICAL_BEAM_POSITION: case VI_VERTICAL_BEAM_POSITION:
_dbg_assert_(VIDEOINTERFACE,0); // writing the beam position goes against yagcd, let's cross our fingers
VerticalBeamPos = _iValue;
break; break;
case VI_HORIZONTAL_BEAM_POSITION: case VI_HORIZONTAL_BEAM_POSITION:
_dbg_assert_(VIDEOINTERFACE,0); HorizontalBeamPos = _iValue;
break; break;
// RETRACE STUFF ... // RETRACE STUFF ...