From c779f95b87da8cdb451035c2d52016ed7e271459 Mon Sep 17 00:00:00 2001 From: "XTra.KrazzY" Date: Mon, 8 Jun 2009 00:14:48 +0000 Subject: [PATCH] -Wii System Menu now recognizes DVDs using the Load Disc/Eject feature! Games hang though (probably due to unknown ES call) -/dev/di IPC: Cleaned up code and fixed a bug (which I used to accidentally find out what I did), added Volume eject feature for VolumeHandler. -Partially documented Wii DVD cover flags. -Files opened in Wii Read-Write mode are now set to append. -Removed annoying overhead-ish "Idle" log message. As for /dev/di: Someone clearly didn't know what he was doing in that file. Someone freed memory which didn't belong to that file and then complained about a crash. Needless to say the problem is now solved. Big TODO on the /dev/di code though, ExecuteCommand is practically doing nothing but reading. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3365 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/Src/CoreTiming.cpp | 2 +- .../Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp | 65 ++++++++++++------- .../Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.h | 1 - .../Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp | 14 ++-- Source/Core/Core/Src/VolumeHandler.cpp | 13 ++++ Source/Core/Core/Src/VolumeHandler.h | 2 + Source/Core/DolphinWX/Src/FrameTools.cpp | 9 ++- 7 files changed, 75 insertions(+), 31 deletions(-) diff --git a/Source/Core/Core/Src/CoreTiming.cpp b/Source/Core/Core/Src/CoreTiming.cpp index 0ce53b27c8..92d7c75b5b 100644 --- a/Source/Core/Core/Src/CoreTiming.cpp +++ b/Source/Core/Core/Src/CoreTiming.cpp @@ -404,7 +404,7 @@ void LogPendingEvents() void Idle() { - DEBUG_LOG(POWERPC, "Idle"); + //DEBUG_LOG(POWERPC, "Idle"); idledCycles += downcount; downcount = 0; 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 62bdb4ef01..a15cdb1e0d 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 @@ -31,13 +31,11 @@ CWII_IPC_HLE_Device_di::CWII_IPC_HLE_Device_di(u32 _DeviceID, const std::string& _rDeviceName ) : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) - , m_pVolume(NULL) , m_pFileSystem(NULL) , m_ErrorStatus(0) { - m_pVolume = VolumeHandler::GetVolume(); - if (m_pVolume) - m_pFileSystem = DiscIO::CreateFileSystem(m_pVolume); + if (VolumeHandler::IsValid()) + m_pFileSystem = DiscIO::CreateFileSystem(VolumeHandler::GetVolume()); } CWII_IPC_HLE_Device_di::~CWII_IPC_HLE_Device_di() @@ -47,10 +45,6 @@ CWII_IPC_HLE_Device_di::~CWII_IPC_HLE_Device_di() delete m_pFileSystem; m_pFileSystem = NULL; } - // This caused the crash in VolumeHandler.cpp, setting m_pVolume = NULL; didn't help - // it still makes VolumeHandler.cpp have a non-NULL pointer with no content so that - // delete crashes - //if(m_pVolume) { delete m_pVolume; m_pVolume = NULL; } } bool CWII_IPC_HLE_Device_di::Open(u32 _CommandAddress, u32 _Mode) @@ -67,10 +61,7 @@ bool CWII_IPC_HLE_Device_di::Close(u32 _CommandAddress) bool CWII_IPC_HLE_Device_di::IOCtl(u32 _CommandAddress) { - INFO_LOG(WII_IPC_DVD, "*******************************"); INFO_LOG(WII_IPC_DVD, "CWII_IPC_DVD_Device_di::IOCtl"); - INFO_LOG(WII_IPC_DVD, "*******************************"); - u32 BufferIn = Memory::Read_U32(_CommandAddress + 0x10); u32 BufferInSize = Memory::Read_U32(_CommandAddress + 0x14); @@ -82,7 +73,7 @@ bool CWII_IPC_HLE_Device_di::IOCtl(u32 _CommandAddress) GetDeviceName().c_str(), Command, BufferIn, BufferInSize, BufferOut, BufferOutSize); if (Command == 0x7a) - DumpCommands(_CommandAddress, 8, LogTypes::WII_IPC_DVD, LogTypes::LWARNING); + DumpCommands(_CommandAddress, 8, LogTypes::WII_IPC_DVD, LogTypes::LINFO); u32 ReturnValue = ExecuteCommand(BufferIn, BufferInSize, BufferOut, BufferOutSize); Memory::Write_U32(ReturnValue, _CommandAddress + 0x4); @@ -92,9 +83,7 @@ bool CWII_IPC_HLE_Device_di::IOCtl(u32 _CommandAddress) bool CWII_IPC_HLE_Device_di::IOCtlV(u32 _CommandAddress) { - INFO_LOG(WII_IPC_DVD, "*******************************"); INFO_LOG(WII_IPC_DVD, "CWII_IPC_DVD_Device_di::IOCtlV"); - INFO_LOG(WII_IPC_DVD, "*******************************"); SIOCtlVBuffer CommandBuffer(_CommandAddress); @@ -155,6 +144,16 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 Memory::Memset(_BufferOut, 0, _BufferOutSize); } + // Initializing a filesystem if it was just loaded + if(!m_pFileSystem && VolumeHandler::IsValid()) + m_pFileSystem = DiscIO::CreateFileSystem(VolumeHandler::GetVolume()); + + // De-initializing a filesystem if the volume was unmounted + if(m_pFileSystem && !VolumeHandler::IsValid()) { + delete m_pFileSystem; + m_pFileSystem = NULL; + } + switch (Command) { // DVDLowInquiry @@ -252,19 +251,40 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 break; // DVDLowPrepareCoverRegister - // DVDLowGetCoverReg - Called by "Legend of Spyro" and MP3 + // DVDLowGetCoverReg - Called by "Legend of Spyro", MP3 and Wii System Menu case 0x7a: { - INFO_LOG(WII_IPC_DVD, "%s executes DVDLowGetCoverReg (Buffer 0x%08x, 0x%x)", - GetDeviceName().c_str(), _BufferOut, _BufferOutSize); + u8* buffer = Memory::GetPointer(_BufferOut); + + // DVD Cover Register States: + // 0x00: Unknown state (keeps checking for DVD) + // 0x01: No Disc inside + // 0xFE: Reads Disc - // -------------------------------------------------------------------- - /* Hack for Legend of Spyro. Switching the 4th byte between 0 and 1 gets + // 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; + + if(m_pFileSystem) + buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0xFE; + + 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()); + + + /* + 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 */ - // ------------------------- + TODO: Make this compatible with MP3 /* static u8 coverByte = 0; @@ -275,9 +295,10 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 coverByte = 0; else coverByte = 0x01; - + return 1; */ + } break; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.h index 378e5e1bb8..ebe817658d 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.h @@ -43,7 +43,6 @@ private: u32 ExecuteCommand(u32 BufferIn, u32 BufferInSize, u32 _BufferOut, u32 BufferOutSize); - DiscIO::IVolume* m_pVolume; DiscIO::IFileSystem* m_pFileSystem; u32 m_ErrorStatus; }; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp index af094b0842..6366781e91 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_FileIO.cpp @@ -49,11 +49,7 @@ CWII_IPC_HLE_Device_FileIO::CWII_IPC_HLE_Device_FileIO(u32 _DeviceID, const std: CWII_IPC_HLE_Device_FileIO::~CWII_IPC_HLE_Device_FileIO() { - if (m_pFileHandle != NULL) - { - fclose(m_pFileHandle); - m_pFileHandle = NULL; - } + } bool @@ -62,6 +58,12 @@ CWII_IPC_HLE_Device_FileIO::Close(u32 _CommandAddress) u32 DeviceID = Memory::Read_U32(_CommandAddress + 8); INFO_LOG(WII_IPC_FILEIO, "FileIO: Close %s (DeviceID=%08x)", GetDeviceName().c_str(), DeviceID); + if (m_pFileHandle != NULL) + { + fclose(m_pFileHandle); + m_pFileHandle = NULL; + } + // Close always return 0 for success Memory::Write_U32(0, _CommandAddress + 4); @@ -101,7 +103,7 @@ CWII_IPC_HLE_Device_FileIO::Open(u32 _CommandAddress, u32 _Mode) { case 0x01: m_pFileHandle = fopen(m_Filename.c_str(), "rb"); break; case 0x02: m_pFileHandle = fopen(m_Filename.c_str(), "wb"); break; - case 0x03: m_pFileHandle = fopen(m_Filename.c_str(), "r+b"); break; + case 0x03: m_pFileHandle = fopen(m_Filename.c_str(), "a+b"); break; default: PanicAlert("CWII_IPC_HLE_Device_FileIO: unknown open mode"); break; } } diff --git a/Source/Core/Core/Src/VolumeHandler.cpp b/Source/Core/Core/Src/VolumeHandler.cpp index 3c05f56dda..401037255f 100644 --- a/Source/Core/Core/Src/VolumeHandler.cpp +++ b/Source/Core/Core/Src/VolumeHandler.cpp @@ -27,6 +27,19 @@ DiscIO::IVolume *GetVolume() { return g_pVolume; } +void EjectVolume() +{ + 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; + } +} + bool SetVolumeName(const std::string& _rFullPath) { if (g_pVolume) diff --git a/Source/Core/Core/Src/VolumeHandler.h b/Source/Core/Core/Src/VolumeHandler.h index 478ebcf90e..c6763c4b4c 100644 --- a/Source/Core/Core/Src/VolumeHandler.h +++ b/Source/Core/Core/Src/VolumeHandler.h @@ -42,6 +42,8 @@ bool IsWii(); DiscIO::IVolume *GetVolume(); +void EjectVolume(); + } // namespace #endif diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp index d8595ab198..6ae91d6816 100644 --- a/Source/Core/DolphinWX/Src/FrameTools.cpp +++ b/Source/Core/DolphinWX/Src/FrameTools.cpp @@ -131,7 +131,7 @@ void CFrame::CreateMenu() // Emulation menu wxMenu* emulationMenu = new wxMenu; emulationMenu->Append(IDM_PLAY, _T("&Play")); - emulationMenu->Append(IDM_CHANGEDISC, _T("Change Disc")); + emulationMenu->Append(IDM_CHANGEDISC, _T("Load Disc")); emulationMenu->Append(IDM_STOP, _T("&Stop")); emulationMenu->AppendSeparator(); wxMenu *saveMenu = new wxMenu; @@ -485,10 +485,17 @@ void CFrame::DoOpen(bool Boot) void CFrame::OnChangeDisc(wxCommandEvent& WXUNUSED (event)) { + if(VolumeHandler::IsValid()) { + VolumeHandler::EjectVolume(); + GetMenuBar()->FindItem(IDM_CHANGEDISC)->SetText("Load Disc"); + return; + } + DVDInterface::SetLidOpen(true); DoOpen(false); DVDInterface::SetLidOpen(false); DVDInterface::SetDiscInside(true); + GetMenuBar()->FindItem(IDM_CHANGEDISC)->SetText("Eject"); } void CFrame::OnPlay(wxCommandEvent& WXUNUSED (event))