diff --git a/Source/Core/Core/Src/Boot/Boot.cpp b/Source/Core/Core/Src/Boot/Boot.cpp index 1ed10d9d42..588386bf5a 100644 --- a/Source/Core/Core/Src/Boot/Boot.cpp +++ b/Source/Core/Core/Src/Boot/Boot.cpp @@ -140,7 +140,6 @@ bool CBoot::LoadMapFromFilename(const std::string &_rFilename, const char *_game ////////////////////////////////////////////////////////////////////////////////////////// // Load a GC or Wii BIOS file -// ŻŻŻŻŻŻŻŻŻŻŻŻŻ bool CBoot::Load_BIOS(const std::string& _rBiosFilename) { bool bResult = false; @@ -148,16 +147,13 @@ bool CBoot::Load_BIOS(const std::string& _rBiosFilename) if (!File::ReadFileToString(false, _rBiosFilename.c_str(), data)) return false; - Memory::WriteBigEData((const u8*)data.data(), 0x81300000, data.size()); + Memory::WriteBigEData((const u8*)data.data() + 0x820, 0x81300000, data.size() - 0x820); PC = 0x81300000; return true; } -///////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////////////// // Third boot step after BootManager and Core. See Call schedule in BootManager.cpp -// ŻŻŻŻŻŻŻŻŻŻŻŻŻ bool CBoot::BootUp() { const bool bDebugIsoBootup = false; @@ -193,7 +189,7 @@ bool CBoot::BootUp() VideoInterface::SetRegionReg((char)VolumeHandler::GetVolume()->GetUniqueID().at(3)); - DVDInterface::SetDiscInside(true); + DVDInterface::SetDiscInside(VolumeHandler::IsValid()); // Use HLE BIOS or not if (_StartupPara.bHLEBios) @@ -259,6 +255,8 @@ bool CBoot::BootUp() } } + DVDInterface::SetDiscInside(VolumeHandler::IsValid()); + CDolLoader dolLoader(_StartupPara.m_strFilename.c_str()); PC = dolLoader.GetEntryPoint(); #ifdef _DEBUG @@ -274,7 +272,7 @@ bool CBoot::BootUp() { if(!File::Exists(_StartupPara.m_strFilename.c_str())) { - PanicAlert("The file you specified (%s) does not exists", + PanicAlert("The file you specified (%s) does not exist", _StartupPara.m_strFilename.c_str()); return false; } @@ -327,6 +325,15 @@ bool CBoot::BootUp() if (LoadMapFromFilename(_StartupPara.m_strFilename)) HLE::PatchFunctions(); + + // load default image or create virtual drive from directory + if (!_StartupPara.m_strDVDRoot.empty()) + VolumeHandler::SetVolumeDirectory(_StartupPara.m_strDVDRoot, true); + else if (!_StartupPara.m_strDefaultGCM.empty()) + VolumeHandler::SetVolumeName(_StartupPara.m_strDefaultGCM); + + DVDInterface::SetDiscInside(VolumeHandler::IsValid()); + break; @@ -334,7 +341,7 @@ bool CBoot::BootUp() // =================================================================================== case SCoreStartupParameter::BOOT_BIOS: { - DVDInterface::SetDiscInside(false); + DVDInterface::SetDiscInside(VolumeHandler::IsValid()); if (Load_BIOS(_StartupPara.m_strBios)) { if (LoadMapFromFilename(_StartupPara.m_strFilename)) diff --git a/Source/Core/Core/Src/CoreParameter.cpp b/Source/Core/Core/Src/CoreParameter.cpp index d04d17b9dc..cf920b8a77 100644 --- a/Source/Core/Core/Src/CoreParameter.cpp +++ b/Source/Core/Core/Src/CoreParameter.cpp @@ -171,7 +171,7 @@ bool SCoreStartupParameter::AutoSetup(EBootBios _BootBios) bNTSC = false; bWii = true; - Region = EUR_DIR; + Region = EUR_DIR; m_BootType = BOOT_WII_NAND; if (pVolume) diff --git a/Source/Core/Core/Src/HW/DVDInterface.cpp b/Source/Core/Core/Src/HW/DVDInterface.cpp index a810e35508..755fe5ae20 100644 --- a/Source/Core/Core/Src/HW/DVDInterface.cpp +++ b/Source/Core/Core/Src/HW/DVDInterface.cpp @@ -17,6 +17,8 @@ #include "Common.h" // Common #include "ChunkFile.h" +#include "../ConfigManager.h" +#include "../CoreTiming.h" #include "StreamADPCM.H" // Core #include "DVDInterface.h" @@ -197,6 +199,9 @@ bool g_bDiscInside = false; Common::CriticalSection dvdread_section; +static int changeDisc; +void ChangeDiscCallback(u64 userdata, int cyclesLate); + void DoState(PointerWrap &p) { p.Do(dvdMem); @@ -224,7 +229,7 @@ void Init() dvdMem.AudioPos = 0; dvdMem.AudioLength = 0; -// SetLidOpen(true); + changeDisc = CoreTiming::RegisterEvent("ChangeDisc", ChangeDiscCallback); } void Shutdown() @@ -237,22 +242,65 @@ void SetDiscInside(bool _DiscInside) g_bDiscInside = _DiscInside; } +bool IsDiscInside() +{ + return g_bDiscInside; +} + +// Take care of all logic of "swapping discs" +// We want this in the "backend", NOT the gui +void ChangeDiscCallback(u64 userdata, int cyclesLate) +{ + std::string FileName((const char*)userdata); + SetDiscInside(false); + SetLidOpen(); + + std::string& SavedFileName = SConfig::GetInstance().m_LocalCoreStartupParameter.m_strFilename; + + if (FileName.empty()) + { + // Empty the drive + VolumeHandler::EjectVolume(); + } + else if (VolumeHandler::SetVolumeName(FileName)) + { + // Save the new ISO file name + SavedFileName = FileName; + } + else + { + PanicAlert("Invalid file"); + + // Put back the old one + VolumeHandler::SetVolumeName(SavedFileName); + } + + SetLidOpen(false); + SetDiscInside(VolumeHandler::IsValid()); +} + +void ChangeDisc(const char* _FileName) +{ + const char* NoDisc = ""; + CoreTiming::ScheduleEvent_Threadsafe(0, changeDisc, (u64)NoDisc); + CoreTiming::ScheduleEvent_Threadsafe(500000000, changeDisc, (u64)_FileName); +} + void SetLidOpen(bool _bOpen) { - if (_bOpen) - dvdMem.CoverReg.CVR = 1; - else - dvdMem.CoverReg.CVR = 0; + dvdMem.CoverReg.CVR = _bOpen ? 1 : 0; GenerateDVDInterrupt(INT_CVRINT); } bool IsLidOpen() { - if (dvdMem.CoverReg.CVR) - return true; - else - return false; + return (dvdMem.CoverReg.CVR == 1); +} + +void ClearCoverInterrupt() +{ + dvdMem.CoverReg.CVRINT = 0; } bool DVDRead(u32 _iDVDOffset, u32 _iRamAddress, u32 _iLength) @@ -457,7 +505,7 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg) // 0004-0007 releaseDate // 0008-001F padding(0) //========================================================================================================= - case 0x12: + case DVDLowInquiry: { // small safety check, dunno if it's needed if ((dvdMem.Command[1] == 0) && (dvdMem.DMALength.Length == 0x20)) @@ -494,7 +542,7 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg) // Command2 <- Address in ram of the buffer //========================================================================================================= case 0xA8: - { + { if (g_bDiscInside) { u32 iDVDOffset = dvdMem.Command[1] << 2; @@ -515,7 +563,7 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg) _DMAControlReg.TSTART = 0; dvdMem.DMALength.Length = 0; GenerateDVDInterrupt(INT_DEINT); - g_ErrorCode = 0x03023A00; + g_ErrorCode = ERROR_NO_DISK | ERROR_COVER_H; return; } } @@ -526,7 +574,7 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg) // Command/Subcommand/Padding <- AB000000 // Command0 <- Position on DVD shr 2 //========================================================================================================= - case 0xAB: + case DVDLowSeek: { #if MAX_LOGLEVEL >= DEBUG_LEVEL u32 offset = dvdMem.Command[1] << 2; @@ -535,14 +583,15 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg) } break; + case DVDLowOffset: + DEBUG_LOG(DVDINTERFACE, "DVDLowOffset: ignoring..."); + break; + //========================================================================================================= // REQUEST ERROR (Immediate) // Command/Subcommand/Padding <- E0000000 //========================================================================================================= - case 0xD9: - INFO_LOG(DVDINTERFACE, "DVD: command 0xD9, called by gcos multigame discs\n Report if you are running anything else"); - break; - case 0xE0: + case DVDLowRequestError: ERROR_LOG(DVDINTERFACE, "Requesting error"); dvdMem.Immediate = g_ErrorCode; break; @@ -587,7 +636,7 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg) //========================================================================================================= case 0xE2: { - /**/ if (m_bStream) + if (m_bStream) dvdMem.Immediate = 1; else dvdMem.Immediate = 0; @@ -599,7 +648,7 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg) // STOP MOTOR (Immediate) // Command/Subcommand/Padding <- E3000000 //========================================================================================================= - case 0xE3: + case DVDLowStopMotor: DEBUG_LOG(DVDINTERFACE, "Stop motor"); break; @@ -608,8 +657,8 @@ void ExecuteCommand(UDIDMAControlRegister& _DMAControlReg) // Command/Subcommand/Padding <- E4000000 (disable) // Command/Subcommand/Padding <- E4010000 (enable) //========================================================================================================= - case 0xE4: -/**/ if (((dvdMem.Command[0] & 0x00FF0000) >> 16) == 1) + case DVDLowAudioBufferConfig: + if (((dvdMem.Command[0] & 0x00FF0000) >> 16) == 1) { m_bStream = true; DEBUG_LOG(DVDINTERFACE, "DVD(Audio): Audio enabled"); diff --git a/Source/Core/Core/Src/HW/DVDInterface.h b/Source/Core/Core/Src/HW/DVDInterface.h index 4a2f536ff1..98d7045c5f 100644 --- a/Source/Core/Core/Src/HW/DVDInterface.h +++ b/Source/Core/Core/Src/HW/DVDInterface.h @@ -28,13 +28,18 @@ void Init(); void Shutdown(); void DoState(PointerWrap &p); +// Disc detection and swapping void SetDiscInside(bool _DiscInside); -void SwapDisc(const char * fileName); +bool IsDiscInside(); +void ChangeDisc(const char* _FileName); // Lid Functions -void SetLidOpen(bool open = true); +void SetLidOpen(bool _bOpen = true); bool IsLidOpen(); +// Used as low level control by WII_IPC_HLE_Device_DI +void ClearCoverInterrupt(); + // DVD Access Functions bool DVDRead(u32 _iDVDOffset, u32 _iRamAddress, u32 _iLength); bool DVDReadADPCM(u8* _pDestBuffer, u32 _iNumSamples); @@ -46,6 +51,71 @@ void Read32(u32& _uReturnValue, const u32 _iAddress); // Write32 void Write32(const u32 _iValue, const u32 _iAddress); + +// Not sure about endianness here. I'll just name them like this... +enum DIErrorLow +{ + ERROR_READY = 0x00000000, // Ready. + ERROR_COVER_L = 0x01000000, // Cover is opened. + ERROR_CHANGE_DISK = 0x02000000, // Disk change. + ERROR_NO_DISK = 0x03000000, // No Disk. + ERROR_MOTOR_STOP_L = 0x04000000, // Motor stop. + ERROR_NO_DISKID_L = 0x05000000 // Disk ID not read. +}; +enum DIErrorHigh +{ + ERROR_NONE = 0x000000, // No error. + ERROR_MOTOR_STOP_H = 0x020400, // Motor stopped. + ERROR_NO_DISKID_H = 0x020401, // Disk ID not read. + ERROR_COVER_H = 0x023a00, // Medium not present / Cover opened. + ERROR_SEEK_NDONE = 0x030200, // No Seek complete. + ERROR_READ = 0x031100, // UnRecoverd read error. + ERROR_PROTOCOL = 0x040800, // Transfer protocol error. + ERROR_INV_CMD = 0x052000, // Invalid command operation code. + ERROR_AUDIO_BUF = 0x052001, // Audio Buffer not set. + ERROR_BLOCK_OOB = 0x052100, // Logical block address out of bounds. + ERROR_INV_FIELD = 0x052400, // Invalid Field in command packet. + ERROR_INV_AUDIO = 0x052401, // Invalid audio command. + ERROR_INV_PERIOD = 0x052402, // Configuration out of permitted period. + ERROR_END_USR_AREA = 0x056300, // End of user area encountered on this track. + ERROR_MEDIUM = 0x062800, // Medium may have changed. + ERROR_MEDIUM_REQ = 0x0b5a01 // Operator medium removal request. +}; + +enum DICommand +{ + 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 +}; + } // end of namespace DVDInterface #endif diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp index 5029c67a6c..9b945651b6 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp @@ -19,6 +19,7 @@ #include "WII_IPC_HLE_Device_DI.h" +#include "../HW/DVDInterface.h" #include "../HW/CPU.h" #include "../HW/Memmap.h" #include "../Core.h" @@ -28,6 +29,8 @@ #include "VolumeCreator.h" #include "Filesystem.h" +using namespace DVDInterface; + CWII_IPC_HLE_Device_di::CWII_IPC_HLE_Device_di(u32 _DeviceID, const std::string& _rDeviceName ) : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) @@ -61,21 +64,16 @@ bool CWII_IPC_HLE_Device_di::Close(u32 _CommandAddress) bool CWII_IPC_HLE_Device_di::IOCtl(u32 _CommandAddress) { - INFO_LOG(WII_IPC_DVD, "CWII_IPC_DVD_Device_di::IOCtl"); - u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10); u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14); u32 BufferOut = Memory::Read_U32(_CommandAddress + 0x18); u32 BufferOutSize = Memory::Read_U32(_CommandAddress + 0x1C); u32 Command = Memory::Read_U32(BufferIn) >> 24; - DEBUG_LOG(WII_IPC_DVD, "%s - Command(0x%08x) BufferIn(0x%08x, 0x%x) BufferOut(0x%08x, 0x%x)", - GetDeviceName().c_str(), Command, BufferIn, BufferInSize, BufferOut, BufferOutSize); + DEBUG_LOG(WII_IPC_DVD, "IOCtl Command(0x%08x) BufferIn(0x%08x, 0x%x) BufferOut(0x%08x, 0x%x)", + Command, BufferIn, BufferInSize, BufferOut, BufferOutSize); - if (Command == 0x7a) - DumpCommands(_CommandAddress, 8, LogTypes::WII_IPC_DVD, LogTypes::LINFO); - - u32 ReturnValue = ExecuteCommand(BufferIn, BufferInSize, BufferOut, BufferOutSize); + u32 ReturnValue = ExecuteCommand(BufferIn, BufferInSize, BufferOut, BufferOutSize); Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); return true; @@ -83,8 +81,6 @@ bool CWII_IPC_HLE_Device_di::IOCtl(u32 _CommandAddress) bool CWII_IPC_HLE_Device_di::IOCtlV(u32 _CommandAddress) { - INFO_LOG(WII_IPC_DVD, "CWII_IPC_DVD_Device_di::IOCtlV"); - SIOCtlVBuffer CommandBuffer(_CommandAddress); // Prepare the out buffer(s) with zeros as a safety precaution @@ -98,33 +94,29 @@ bool CWII_IPC_HLE_Device_di::IOCtlV(u32 _CommandAddress) u32 ReturnValue = 0; switch (CommandBuffer.Parameter) { - // DVDLowOpenPartition - case 0x8b: + case DVDLowOpenPartition: { _dbg_assert_msg_(WII_IPC_DVD, CommandBuffer.InBuffer[1].m_Address == 0, "DVDLowOpenPartition with ticket"); _dbg_assert_msg_(WII_IPC_DVD, CommandBuffer.InBuffer[2].m_Address == 0, "DVDLowOpenPartition with cert chain"); - u8 partition = Memory::Read_U32(CommandBuffer.m_Address + 4); - INFO_LOG(WII_IPC_DVD, "DVD IOCtlV: DVDLowOpenPartition %i", partition); - bool readOK = false; - u64 TMDOffset = 0; - readOK |= VolumeHandler::GetTMDOffset(partition, TMDOffset); + // Get TMD offset for requested partition... + u64 TMDOffset = ((u64)Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address + 4) << 2 ) + 0x2c0; + + INFO_LOG(WII_IPC_DVD, "DVDLowOpenPartition: TMDOffset 0x%016llx", TMDOffset); // Read TMD to the buffer readOK |= VolumeHandler::RAWReadToPtr(Memory::GetPointer(CommandBuffer.PayloadBuffer[0].m_Address), TMDOffset, CommandBuffer.PayloadBuffer[0].m_Size); - // Second outbuffer is error, we can ignore it - ReturnValue = readOK ? 1 : 0; } break; default: - ERROR_LOG(WII_IPC_DVD, "DVD IOCtlV: %i", CommandBuffer.Parameter); - _dbg_assert_msg_(WII_IPC_DVD, 0, "DVD IOCtlV: %i", CommandBuffer.Parameter); + ERROR_LOG(WII_IPC_DVD, "IOCtlV: %i", CommandBuffer.Parameter); + _dbg_assert_msg_(WII_IPC_DVD, 0, "IOCtlV: %i", CommandBuffer.Parameter); break; } @@ -149,15 +141,15 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 m_pFileSystem = DiscIO::CreateFileSystem(VolumeHandler::GetVolume()); // De-initializing a filesystem if the volume was unmounted - if(m_pFileSystem && !VolumeHandler::IsValid()) { + if(m_pFileSystem && !VolumeHandler::IsValid()) + { delete m_pFileSystem; m_pFileSystem = NULL; } switch (Command) { - // DVDLowInquiry - case 0x12: + case DVDLowInquiry: { u8* buffer = Memory::GetPointer(_BufferOut); @@ -184,27 +176,21 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 buffer[7] = 0x02; buffer[8] = 0x61; // version - DEBUG_LOG(WII_IPC_DVD, "%s executes DVDLowInquiry (Buffer 0x%08x, 0x%x)", - GetDeviceName().c_str(), _BufferOut, _BufferOutSize); - - return 1; + INFO_LOG(WII_IPC_DVD, "DVDLowInquiry (Buffer 0x%08x, 0x%x)", + _BufferOut, _BufferOutSize); } break; - // DVDLowReadDiskID - case 0x70: + case DVDLowReadDiskID: { VolumeHandler::RAWReadToPtr(Memory::GetPointer(_BufferOut), 0, _BufferOutSize); - DEBUG_LOG(WII_IPC_DVD, "DVDLowReadDiskID %s", + INFO_LOG(WII_IPC_DVD, "DVDLowReadDiskID %s", ArrayToString(Memory::GetPointer(_BufferOut), _BufferOutSize, 0, _BufferOutSize).c_str()); - - return 1; } break; - // DVDLowRead - case 0x71: + case DVDLowRead: { if (_BufferOut == 0) { @@ -217,12 +203,12 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 const char *pFilename = m_pFileSystem->GetFileName(DVDAddress); if (pFilename != NULL) { - INFO_LOG(WII_IPC_DVD, " DVDLowRead: %s (0x%x) - (DVDAddr: 0x%x, Size: 0x%x)", + INFO_LOG(WII_IPC_DVD, "DVDLowRead: %s (0x%x) - (DVDAddr: 0x%x, Size: 0x%x)", pFilename, m_pFileSystem->GetFileSize(pFilename), DVDAddress, Size); } else { - INFO_LOG(WII_IPC_DVD, " DVDLowRead: file unkw - (DVDAddr: 0x%x, Size: 0x%x)", + INFO_LOG(WII_IPC_DVD, "DVDLowRead: file unkw - (DVDAddr: 0x%x, Size: 0x%x)", DVDAddress, Size); } @@ -236,133 +222,78 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 { PanicAlert("Cant read from DVD_Plugin - DVD-Interface: Fatal Error"); } - - return 1; } break; - // DVDLowWaitForCoverClose - case 0x79: + case DVDLowWaitForCoverClose: { - INFO_LOG(WII_IPC_DVD, "%s executes DVDLowWaitForCoverClose (Buffer 0x%08x, 0x%x)", - GetDeviceName().c_str(), _BufferOut, _BufferOutSize); - return 4; + INFO_LOG(WII_IPC_DVD, "DVDLowWaitForCoverClose (Buffer 0x%08x, 0x%x)", + _BufferOut, _BufferOutSize); + return 4; // ??? } break; - // DVDLowPrepareCoverRegister - // DVDLowGetCoverReg - Called by "Legend of Spyro", MP3 and Wii System Menu - case 0x7a: - { - u8* buffer = Memory::GetPointer(_BufferOut); - - // DVD Cover Register States: - // 0x00: Unknown state (keeps checking for DVD) - // 0x01: No Disc inside - // 0xFE: Reads Disc + case DVDLowGetCoverReg: + // DVD Cover Register States: + // 0x00: Unknown state (keeps checking for DVD) + // 0x01: No Disc inside + // 0xFE: Read Disc - // We notify the application that we ejected a disc by - // replacing the Change Disc menu button with "Eject" which - // in turn makes volume handler invalid for at least one - // ioctl and then the user has enough time to load another - // disc. - // TODO: Make ejection mechanism recognized. (Currently eject - // only works if DVDLowReset is called) - - buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0x00; + // TODO: Make user-generated ejection mechanism recognized. + // (Currently eject only works if DVDLowReset is called) - if(m_pFileSystem) - buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0xFE; + // Test cases for this command: Legend of Spyro, MP3, WiiMenu + // WiiMenu currently will stop polling /dev/di if no disc is inserted on boot + // This makes me think it is wanting some interrupt when a disc is inserted + // However, DVDInterface::ChangeDisc does not accomplish this...needs investigation! - INFO_LOG(WII_IPC_DVD, "%s executes DVDLowGetCoverReg (Buffer 0x%08x, 0x%x) %s", - GetDeviceName().c_str(), _BufferOut, _BufferOutSize, - ArrayToString(buffer, _BufferOutSize, 0, _BufferOutSize).c_str()); + if (IsDiscInside()) + Memory::Write_U32(0xfe, _BufferOut); + else if (IsLidOpen()) + Memory::Write_U32(0x00, _BufferOut); + else + Memory::Write_U32(0x01, _BufferOut); - - /* - Hack for Legend of Spyro. Switching the 4th byte between 0 and 1 gets - through this check. The out buffer address remains the same all the - time so we don't have to bother making a global function. - - TODO: Make this compatible with MP3 - /* - static u8 coverByte = 0; - - u8* buffer = Memory::GetPointer(_BufferOut); - buffer[3] = coverByte; - - if(coverByte) - coverByte = 0; - else - coverByte = 0x01; - - return 1; - */ - - } - break; - - // DVDLowNotifyReset - case 0x7e: - ERROR_LOG(WII_IPC_DVD, "DVDLowNotifyReset"); + INFO_LOG(WII_IPC_DVD, "DVDLowGetCoverReg 0x%08x", Memory::Read_U32(_BufferOut)); break; - // DVDLowReadDvdPhysical - case 0x80: - ERROR_LOG(WII_IPC_DVD, "DVDLowReadDvdPhysical"); + case DVDLowNotifyReset: + PanicAlert("DVDLowNotifyReset"); break; - // DVDLowReadDvdCopyright - case 0x81: - ERROR_LOG(WII_IPC_DVD, "DVDLowReadDvdCopyright"); + case DVDLowReadDvdPhysical: + PanicAlert("DVDLowReadDvdPhysical"); break; - // DVDLowReadDvdDiscKey - case 0x82: - ERROR_LOG(WII_IPC_DVD, "DVDLowReadDvdDiscKey"); + case DVDLowReadDvdCopyright: + PanicAlert("DVDLowReadDvdCopyright"); break; - // DVDLowClearCoverInterrupt - case 0x86: - { - INFO_LOG(WII_IPC_DVD, "%s executes DVDLowClearCoverInterrupt (Buffer 0x%08x, 0x%x)", - GetDeviceName().c_str(), _BufferOut, _BufferOutSize); - return 1; - } + case DVDLowReadDvdDiscKey: + PanicAlert("DVDLowReadDvdDiscKey"); break; - // DVDLowGetCoverStatus - case 0x88: - { - INFO_LOG(WII_IPC_DVD, "%s executes DVDLowGetCoverStatus (Buffer 0x%08x, 0x%x)", - GetDeviceName().c_str(), _BufferOut, _BufferOutSize); - return 1; - } + case DVDLowClearCoverInterrupt: + // TODO: check (seems to work ok) + INFO_LOG(WII_IPC_DVD, "DVDLowClearCoverInterrupt"); + ClearCoverInterrupt(); break; - // DVDLowReset - case 0x8a: - { - INFO_LOG(WII_IPC_DVD, "%s executes DVDLowReset (Buffer 0x%08x, 0x%x)", - GetDeviceName().c_str(), _BufferOut, _BufferOutSize); - return 1; - } + case DVDLowGetCoverStatus: + // TODO: check (haven't tested yet) + Memory::Write_U32(IsDiscInside() ? 2 : 0, _BufferOut); + INFO_LOG(WII_IPC_DVD, "DVDLowGetCoverStatus %i", IsDiscInside() ? 2 : 0); break; - // DVDLowOpenPartition - case 0x8b: - ERROR_LOG(WII_IPC_DVD, "DVDLowOpenPartition"); - return 1; + case DVDLowReset: + INFO_LOG(WII_IPC_DVD, "DVDLowReset"); break; - // DVDLowClosePartition - case 0x8c: - DEBUG_LOG(WII_IPC_DVD, "DVDLowClosePartition"); - return 1; + case DVDLowClosePartition: + INFO_LOG(WII_IPC_DVD, "DVDLowClosePartition"); break; - // DVDLowUnencryptedRead - case 0x8d: + case DVDLowUnencryptedRead: { if (_BufferOut == 0) { @@ -385,8 +316,8 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 || (((DVDAddress32 + Size) > 0x7ed40000) && (DVDAddress32 + Size) < 0x7ed40008) )) { - INFO_LOG(WII_IPC_DVD, "DVDLowUnencryptedRead: trying to read out of bounds @ %x", DVDAddress32); - m_ErrorStatus = 0x52100; // Logical block address out of range + WARN_LOG(WII_IPC_DVD, "DVDLowUnencryptedRead: trying to read out of bounds @ %x", DVDAddress32); + m_ErrorStatus = ERROR_READY | ERROR_BLOCK_OOB; // Should cause software to call DVDLowRequestError return 2; } @@ -405,108 +336,109 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 { PanicAlert("Cant read from DVD_Plugin - DVD-Interface: Fatal Error"); } - - return 1; } break; - // DVDLowEnableDvdVideo - case 0x8e: + case DVDLowEnableDvdVideo: ERROR_LOG(WII_IPC_DVD, "DVDLowEnableDvdVideo"); break; - // DVDLowReportKey - case 0xa4: + case DVDLowReportKey: INFO_LOG(WII_IPC_DVD, "DVDLowReportKey"); - // Does not work on commercial discs - m_ErrorStatus = 0x052000; // Invalid command operation code + // Does not work on retail discs/drives + // Retail games send this command to see if they are running on real retail hw + m_ErrorStatus = ERROR_READY | ERROR_INV_CMD; return 2; break; - - // DVDLowSeek - case 0xab: - ERROR_LOG(WII_IPC_DVD, "DVDLowSeek"); + + case DVDLowSeek: + { + u64 DVDAddress = Memory::Read_U32(_BufferIn + 0x4) << 2; + const char *pFilename = m_pFileSystem->GetFileName(DVDAddress); + if (pFilename != NULL) + { + INFO_LOG(WII_IPC_DVD, "DVDLowSeek: %s (0x%x) - (DVDAddr: 0x%x)", + pFilename, m_pFileSystem->GetFileSize(pFilename), DVDAddress); + } + else + { + INFO_LOG(WII_IPC_DVD, "DVDLowSeek: file unkw - (DVDAddr: 0x%x)", + DVDAddress); + } + } break; // Apparently Dx commands have never been seen in dolphin? *shrug* - // DVDLowReadDvd - case 0xd0: + case DVDLowReadDvd: ERROR_LOG(WII_IPC_DVD, "DVDLowReadDvd"); break; - // DVDLowReadDvdConfig - case 0xd1: + case DVDLowReadDvdConfig: ERROR_LOG(WII_IPC_DVD, "DVDLowReadDvdConfig"); break; - // DVDLowStopLaser - case 0xd2: + case DVDLowStopLaser: ERROR_LOG(WII_IPC_DVD, "DVDLowStopLaser"); break; - // DVDLowOffset - case 0xd9: + case DVDLowOffset: ERROR_LOG(WII_IPC_DVD, "DVDLowOffset"); break; - // DVDLowReadDiskBca - case 0xda: + case DVDLowReadDiskBca: ERROR_LOG(WII_IPC_DVD, "DVDLowReadDiskBca"); break; - // DVDLowRequestDiscStatus - case 0xdb: + case DVDLowRequestDiscStatus: ERROR_LOG(WII_IPC_DVD, "DVDLowRequestDiscStatus"); break; - // DVDLowRequestRetryNumber - case 0xdc: + case DVDLowRequestRetryNumber: ERROR_LOG(WII_IPC_DVD, "DVDLowRequestRetryNumber"); break; - // DVDLowSetMaximumRotation - case 0xdd: + case DVDLowSetMaximumRotation: ERROR_LOG(WII_IPC_DVD, "DVDLowSetMaximumRotation"); break; - // DVDLowSerMeasControl - case 0xdf: + case DVDLowSerMeasControl: ERROR_LOG(WII_IPC_DVD, "DVDLowSerMeasControl"); break; - // DVDLowRequestError - case 0xe0: + case DVDLowRequestError: // Identical to the error codes found in yagcd section 5.7.3.5.1 (so far) WARN_LOG(WII_IPC_DVD, "DVDLowRequestError status = 0x%08x", m_ErrorStatus); Memory::Write_U32(m_ErrorStatus, _BufferOut); + // When does error status get reset? break; // Ex commands are immediate and respond with 4 bytes - // DVDLowStopMotor - case 0xe3: + case DVDLowStopMotor: { - u32 eject = Memory::Read_U32(_BufferIn + 0x04); + u32 eject = Memory::Read_U32(_BufferIn + 4); + // Drive won't do anything till reset is issued. I think it replies like nothing is wrong though? + u32 kill = Memory::Read_U32(_BufferIn + 8); - INFO_LOG(WII_IPC_DVD, "%s executes DVDLowStopMotor eject = %s", - GetDeviceName().c_str(), eject ? "true" : "false"); + INFO_LOG(WII_IPC_DVD, "DVDLowStopMotor %s %s", + eject ? "eject" : "", kill ? "kill!" : ""); if (eject) { - // TODO: eject the disc + SetLidOpen(true); + SetDiscInside(false); } } break; - // DVDLowAudioBufferConfig - case 0xe4: + case DVDLowAudioBufferConfig: ERROR_LOG(WII_IPC_DVD, "DVDLowAudioBufferConfig"); break; default: - ERROR_LOG(WII_IPC_DVD, "%s executes unknown cmd 0x%08x (Buffer 0x%08x, 0x%x)", - GetDeviceName().c_str(), Command, _BufferOut, _BufferOutSize); + ERROR_LOG(WII_IPC_DVD, "unknown cmd 0x%08x (Buffer 0x%08x, 0x%x)", + Command, _BufferOut, _BufferOutSize); - PanicAlert("%s executes unknown cmd 0x%08x", GetDeviceName().c_str(), Command); + PanicAlert("unknown cmd 0x%08x", Command); break; } diff --git a/Source/Core/Core/Src/VolumeHandler.cpp b/Source/Core/Core/Src/VolumeHandler.cpp index 401037255f..5970fd2bd2 100644 --- a/Source/Core/Core/Src/VolumeHandler.cpp +++ b/Source/Core/Core/Src/VolumeHandler.cpp @@ -44,10 +44,6 @@ bool SetVolumeName(const std::string& _rFullPath) { if (g_pVolume) { - // This code looks scary. Can the try/catch stuff be removed? - // This cause a "Unhandled exception ... Access violation - // reading location ..." after you have started and stopped two - // or three games delete g_pVolume; g_pVolume = NULL; } @@ -114,27 +110,4 @@ bool IsWii() return false; } -bool GetTMDOffset(u32 _Partition, u64& _Offset) -{ - bool ret = false; - - if (IsWii()) - { - // Get the info table - u32 pInfoTableOffset = 0; - ret |= RAWReadToPtr((u8*)&pInfoTableOffset, 0x40004, 4); - u64 InfoTableOffset = (u64)Common::swap32(pInfoTableOffset) << 2; - - // Get the offset of the partition - u32 pInfoTableEntryOffset = 0; - ret |= RAWReadToPtr((u8*)&pInfoTableEntryOffset, InfoTableOffset + (_Partition * 8), 4); - u64 PartitionOffset = (u64)Common::swap32(pInfoTableEntryOffset) << 2; - - _Offset = PartitionOffset + 0x2c0; - } - - return ret; -} - - } // namespace diff --git a/Source/Core/Core/Src/VolumeHandler.h b/Source/Core/Core/Src/VolumeHandler.h index c6763c4b4c..1a820d2ac6 100644 --- a/Source/Core/Core/Src/VolumeHandler.h +++ b/Source/Core/Core/Src/VolumeHandler.h @@ -35,8 +35,6 @@ u32 Read32(u64 _Offset); bool ReadToPtr(u8* ptr, u64 _dwOffset, u64 _dwLength); bool RAWReadToPtr(u8* ptr, u64 _dwOffset, u64 _dwLength); -bool GetTMDOffset(u32 _Partition, u64& _Offset); - bool IsValid(); bool IsWii(); diff --git a/Source/Core/DolphinWX/Src/Frame.h b/Source/Core/DolphinWX/Src/Frame.h index cdffb1db48..7f242b0375 100644 --- a/Source/Core/DolphinWX/Src/Frame.h +++ b/Source/Core/DolphinWX/Src/Frame.h @@ -34,14 +34,11 @@ inline wxBitmap _wxGetBitmapFromMemory(const unsigned char* data, int length) wxMemoryInputStream is(data, length); return(wxBitmap(wxImage(is, wxBITMAP_TYPE_ANY, -1), -1)); } -//////////////////////////////// - -////////////////////////////////////////////////////////////////////////// // Class declarations -// ŻŻŻŻŻŻŻŻŻŻ class CGameListCtrl; class CLogWindow; + class CFrame : public wxFrame { public: @@ -76,7 +73,6 @@ class CFrame : public wxFrame // --------------------------------------- // Wiimote leds - // --------------- void ModifyStatusBar(); void CreateDestroy(int Case); void CreateLeds(); void CreateSpeakers(); @@ -156,7 +152,8 @@ class CFrame : public wxFrame void OnQuit(wxCommandEvent& event); void OnHelp(wxCommandEvent& event); - void OnOpen(wxCommandEvent& event); void DoOpen(bool Boot); // File menu + void OnOpen(wxCommandEvent& event); // File menu + void DoOpen(bool Boot); void OnRefresh(wxCommandEvent& event); void OnBrowse(wxCommandEvent& event); void OnBootDrive(wxCommandEvent& event); @@ -184,8 +181,10 @@ class CFrame : public wxFrame void OnToggleStatusbar(wxCommandEvent& event); void OnToggleLogWindow(wxCommandEvent& event); void OnToggleConsole(wxCommandEvent& event); - void OnKeyDown(wxKeyEvent& event); void OnKeyUp(wxKeyEvent& event); - void OnDoubleClick(wxMouseEvent& event); void OnMotion(wxMouseEvent& event); + void OnKeyDown(wxKeyEvent& event); + void OnKeyUp(wxKeyEvent& event); + void OnDoubleClick(wxMouseEvent& event); + void OnMotion(wxMouseEvent& event); void OnHostMessage(wxCommandEvent& event); @@ -223,7 +222,5 @@ class CFrame : public wxFrame // Event table DECLARE_EVENT_TABLE(); }; -//////////////////////////////// #endif // __FRAME_H_ - diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp index 372cf92dec..1356d0e2ac 100644 --- a/Source/Core/DolphinWX/Src/FrameTools.cpp +++ b/Source/Core/DolphinWX/Src/FrameTools.cpp @@ -16,9 +16,6 @@ // http://code.google.com/p/dolphin-emu/ - -// Windows - /* CFrame is the main parent window. Inside CFrame there is m_Panel which is the parent for the rendering window (when we render to the main window). In Windows @@ -28,7 +25,6 @@ window handle that is returned by CreateWindow() can be accessed from Core::GetWindowHandle(). */ - // FIXME: why doesn't it work on windows??? #ifndef _WIN32 #include "Common.h" @@ -67,10 +63,7 @@ Core::GetWindowHandle(). #include // wxWidgets -// ---------------------------------------------------------------------------- // Resources -// ---------------------------------------------------------------------------- - extern "C" { #include "../resources/Dolphin.c" // Dolphin icon #include "../resources/toolbar_browse.c" @@ -130,7 +123,7 @@ void CFrame::CreateMenu() // Emulation menu wxMenu* emulationMenu = new wxMenu; emulationMenu->Append(IDM_PLAY, _T("&Play")); - emulationMenu->Append(IDM_CHANGEDISC, _T("Load Disc")); + emulationMenu->Append(IDM_CHANGEDISC, _T("Change Disc")); emulationMenu->Append(IDM_STOP, _T("&Stop")); emulationMenu->AppendSeparator(); wxMenu *saveMenu = new wxMenu; @@ -272,13 +265,14 @@ void CFrame::RecreateToolbar() SetToolBar(TheToolBar); UpdateGUI(); } + void CFrame::InitBitmaps() { // Get selected theme int Theme = SConfig::GetInstance().m_LocalCoreStartupParameter.iTheme; - /* Save memory by only having one set of bitmaps loaded at any time. I mean, they are still - in the exe, which is in memory, but at least we wont make another copy of all of them. */ + // Save memory by only having one set of bitmaps loaded at any time. I mean, they are still + // in the exe, which is in memory, but at least we wont make another copy of all of them. */ switch (Theme) { case BOOMY: @@ -374,9 +368,7 @@ void CFrame::InitBitmaps() } -////////////////////////////////////////////////////////////////////////////////////// // Start the game or change the disc -// ------------- void CFrame::BootGame() { // Rerecording @@ -401,8 +393,8 @@ void CFrame::BootGame() { BootManager::BootCore(m_GameListCtrl->GetSelectedISO()->GetFileName()); } - /* Start the default ISO, or if we don't have a default ISO, start the last - started ISO */ + // Start the default ISO, or if we don't have a default ISO, start the last + // started ISO else if (!SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDefaultGCM.empty() && wxFileExists(wxString(SConfig::GetInstance().m_LocalCoreStartupParameter. m_strDefaultGCM.c_str(), wxConvUTF8))) @@ -416,13 +408,9 @@ void CFrame::BootGame() } } -// Open file to boot or for changing disc +// Open file to boot void CFrame::OnOpen(wxCommandEvent& WXUNUSED (event)) { - // Don't allow this for an initialized core - //if (Core::GetState() != Core::CORE_UNINITIALIZED) - // return; - DoOpen(true); } @@ -441,60 +429,36 @@ void CFrame::DoOpen(bool Boot) ), wxFD_OPEN | wxFD_PREVIEW | wxFD_FILE_MUST_EXIST, this); - if (!path) - { - return; - } + + bool fileChosen = path ? true : false; std::string currentDir2 = File::GetCurrentDirectory(); if (currentDir != currentDir2) { - PanicAlert("Current dir changed has been changeg from %s to %s after wxFileSelector!",currentDir.c_str(),currentDir2.c_str()); + PanicAlert("Current dir changed from %s to %s after wxFileSelector!",currentDir.c_str(),currentDir2.c_str()); File::SetCurrentDirectory(currentDir.c_str()); } // Should we boot a new game or just change the disc? - if(Boot) + if (Boot) { + if (!fileChosen) + return; BootManager::BootCore(std::string(path.ToAscii())); } else { - // Get the current ISO name - std::string OldName = SConfig::GetInstance().m_LocalCoreStartupParameter.m_strFilename; - - // Change the iso and make sure it's a valid file - if(!VolumeHandler::SetVolumeName(std::string(path.ToAscii()))) - { - PanicAlert("The file you selected is not a valid ISO file. Please try again."); - - // Put back the old one - VolumeHandler::SetVolumeName(OldName); - } - // Yes it is a valid ISO file - else - { - // Save the new ISO file name - SConfig::GetInstance().m_LocalCoreStartupParameter.m_strFilename = std::string(path.ToAscii()); - } + if (!fileChosen) + path = wxT(""); + DVDInterface::ChangeDisc(path.c_str()); } } void CFrame::OnChangeDisc(wxCommandEvent& WXUNUSED (event)) { - if(VolumeHandler::IsValid()) { - VolumeHandler::EjectVolume(); - GetMenuBar()->FindItem(IDM_CHANGEDISC)->SetText(wxT("Load Disc")); - return; - } - - DVDInterface::SetLidOpen(true); DoOpen(false); - DVDInterface::SetLidOpen(false); - DVDInterface::SetDiscInside(true); - GetMenuBar()->FindItem(IDM_CHANGEDISC)->SetText(wxT("Eject")); } void CFrame::OnPlay(wxCommandEvent& WXUNUSED (event)) @@ -507,12 +471,7 @@ void CFrame::OnBootDrive(wxCommandEvent& event) BootManager::BootCore(drives[event.GetId()-IDM_DRIVE1]); } -//////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////////////////////// // Refresh the file list and browse for a favorites directory -// ------------- void CFrame::OnRefresh(wxCommandEvent& WXUNUSED (event)) { if (m_GameListCtrl) @@ -570,14 +529,15 @@ void CFrame::DoStop() Core::Stop(); - /* This is needed together with the option to not "delete g_EmuThread" in Core.cpp, because then - we have to wait a moment before GetState() == CORE_UNINITIALIZED so that UpdateGUI() works. - It's also needed when a WaitForSingleObject() has timed out so that the ShutDown() process - has continued without all threads having come to a rest. It's not compatible with the - SETUP_TIMER_WAITING option (because the Stop returns before it's finished). - - Without this we just see the gray CPanel background because the ISO list will not be displayed. - */ + /* + This is needed together with the option to not "delete g_EmuThread" in Core.cpp, because then + we have to wait a moment before GetState() == CORE_UNINITIALIZED so that UpdateGUI() works. + It's also needed when a WaitForSingleObject() has timed out so that the ShutDown() process + has continued without all threads having come to a rest. It's not compatible with the + SETUP_TIMER_WAITING option (because the Stop returns before it's finished). + + Without this we just see the gray CPanel background because the ISO list will not be displayed. + */ #ifndef SETUP_TIMER_WAITING if (bRenderToMain) while(Core::GetState() != Core::CORE_UNINITIALIZED) SLEEP(10); @@ -591,8 +551,6 @@ void CFrame::OnStop(wxCommandEvent& WXUNUSED (event)) { DoStop(); } -//////////////////////////////////////////////////// - void CFrame::OnConfigMain(wxCommandEvent& WXUNUSED (event)) { @@ -601,7 +559,6 @@ void CFrame::OnConfigMain(wxCommandEvent& WXUNUSED (event)) m_GameListCtrl->Update(); } - void CFrame::OnPluginGFX(wxCommandEvent& WXUNUSED (event)) { CPluginManager::GetInstance().OpenConfig( @@ -690,8 +647,8 @@ void CFrame::OnLoadWiiMenu(wxCommandEvent& WXUNUSED (event)) BootManager::BootCore(FULL_WII_MENU_DIR); } -/* Toogle fullscreen. In Windows the fullscreen mode is accomplished by expanding the m_Panel to cover - the entire screen (when we render to the main window). */ +// Toogle fullscreen. In Windows the fullscreen mode is accomplished by expanding the m_Panel to cover +// the entire screen (when we render to the main window). void CFrame::OnToggleFullscreen(wxCommandEvent& WXUNUSED (event)) { ShowFullScreen(true); @@ -928,4 +885,3 @@ void CFrame::GameListChanged(wxCommandEvent& event) m_GameListCtrl->Update(); } } -