From e65ba57814e0490991f6c022951d57349f610b23 Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Mon, 2 Mar 2009 04:02:09 +0000 Subject: [PATCH] enable hotswapping of SI devices. not quite sure if si_dummy is detected as no device or unknown device, but games seem to like it. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2513 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/Src/HW/SI.cpp | 87 +++++++++++++------ Source/Core/Core/Src/HW/SI.h | 3 + Source/Core/Core/Src/HW/SI_Device.cpp | 5 +- .../Core/Src/HW/SI_DeviceGCController.cpp | 15 ++-- .../Core/Core/Src/HW/SI_DeviceGCController.h | 1 - Source/Core/DolphinWX/Src/ConfigMain.cpp | 9 +- 6 files changed, 83 insertions(+), 37 deletions(-) diff --git a/Source/Core/Core/Src/HW/SI.cpp b/Source/Core/Core/Src/HW/SI.cpp index ca2989f82a..8523c9751c 100644 --- a/Source/Core/Core/Src/HW/SI.cpp +++ b/Source/Core/Core/Src/HW/SI.cpp @@ -18,6 +18,7 @@ #include "Common.h" #include "ChunkFile.h" #include "../ConfigManager.h" +#include "../CoreTiming.h" #include "PeripheralInterface.h" @@ -26,6 +27,8 @@ namespace SerialInterface { +static int changeDevice; + void RunSIBuffer(); void UpdateInterrupts(); @@ -229,7 +232,6 @@ void DoState(PointerWrap &p) void Init() { - // TODO: allow dynamic attaching/detaching of devices for (int i = 0; i < NUMBER_OF_CHANNELS; i++) { g_Channel[i].m_Out.Hex = 0; @@ -243,16 +245,15 @@ void Init() g_ComCSR.Hex = 0; g_StatusReg.Hex = 0; g_EXIClockCount.Hex = 0; - memset(g_SIBuffer, 0xce, 128); + memset(g_SIBuffer, 0xce, 128); // This could be the cause of "WII something" in GCController + + changeDevice = CoreTiming::RegisterEvent("ChangeSIDevice", ChangeDeviceCallback); } void Shutdown() { for (int i = 0; i < NUMBER_OF_CHANNELS; i++) - { - delete g_Channel[i].m_pDevice; - g_Channel[i].m_pDevice = NULL; - } + RemoveDevice(i); } void Read32(u32& _uReturnValue, const u32 _iAddress) @@ -409,7 +410,7 @@ void Write32(const u32 _iValue, const u32 _iAddress) if (tmpComCSR.RDSTINT) g_ComCSR.RDSTINT = 0; if (tmpComCSR.TCINT) g_ComCSR.TCINT = 0; - // be careful: runsi-buffer after updating the INT flags + // be careful: run si-buffer after updating the INT flags if (tmpComCSR.TSTART) RunSIBuffer(); UpdateInterrupts(); } @@ -419,36 +420,36 @@ void Write32(const u32 _iValue, const u32 _iAddress) { USIStatusReg tmpStatus(_iValue); - // just update the writable bits - g_StatusReg.NOREP0 = tmpStatus.NOREP0 ? 1 : 0; - g_StatusReg.COLL0 = tmpStatus.COLL0 ? 1 : 0; - g_StatusReg.OVRUN0 = tmpStatus.OVRUN0 ? 1 : 0; - g_StatusReg.UNRUN0 = tmpStatus.UNRUN0 ? 1 : 0; + // clear bits ( if(tmp.bit) SISR.bit=0 ) + if (tmpStatus.NOREP0) g_StatusReg.NOREP0 = 0; + if (tmpStatus.COLL0) g_StatusReg.COLL0 = 0; + if (tmpStatus.OVRUN0) g_StatusReg.OVRUN0 = 0; + if (tmpStatus.UNRUN0) g_StatusReg.UNRUN0 = 0; - g_StatusReg.NOREP1 = tmpStatus.NOREP1 ? 1 : 0; - g_StatusReg.COLL1 = tmpStatus.COLL1 ? 1 : 0; - g_StatusReg.OVRUN1 = tmpStatus.OVRUN1 ? 1 : 0; - g_StatusReg.UNRUN1 = tmpStatus.UNRUN1 ? 1 : 0; + if (tmpStatus.NOREP1) g_StatusReg.NOREP1 = 0; + if (tmpStatus.COLL1) g_StatusReg.COLL1 = 0; + if (tmpStatus.OVRUN1) g_StatusReg.OVRUN1 = 0; + if (tmpStatus.UNRUN1) g_StatusReg.UNRUN1 = 0; - g_StatusReg.NOREP2 = tmpStatus.NOREP2 ? 1 : 0; - g_StatusReg.COLL2 = tmpStatus.COLL2 ? 1 : 0; - g_StatusReg.OVRUN2 = tmpStatus.OVRUN2 ? 1 : 0; - g_StatusReg.UNRUN2 = tmpStatus.UNRUN2 ? 1 : 0; + if (tmpStatus.NOREP2) g_StatusReg.NOREP2 = 0; + if (tmpStatus.COLL2) g_StatusReg.COLL2 = 0; + if (tmpStatus.OVRUN2) g_StatusReg.OVRUN2 = 0; + if (tmpStatus.UNRUN2) g_StatusReg.UNRUN2 = 0; - g_StatusReg.NOREP3 = tmpStatus.NOREP3 ? 1 : 0; - g_StatusReg.COLL3 = tmpStatus.COLL3 ? 1 : 0; - g_StatusReg.OVRUN3 = tmpStatus.OVRUN3 ? 1 : 0; - g_StatusReg.UNRUN3 = tmpStatus.UNRUN3 ? 1 : 0; + if (tmpStatus.NOREP3) g_StatusReg.NOREP3 = 0; + if (tmpStatus.COLL3) g_StatusReg.COLL3 = 0; + if (tmpStatus.OVRUN3) g_StatusReg.OVRUN3 = 0; + if (tmpStatus.UNRUN3) g_StatusReg.UNRUN3 = 0; // send command to devices if (tmpStatus.WR) { - g_StatusReg.WR = 0; g_Channel[0].m_pDevice->SendCommand(g_Channel[0].m_Out.Hex); g_Channel[1].m_pDevice->SendCommand(g_Channel[1].m_Out.Hex); g_Channel[2].m_pDevice->SendCommand(g_Channel[2].m_Out.Hex); g_Channel[3].m_pDevice->SendCommand(g_Channel[3].m_Out.Hex); + g_StatusReg.WR = 0; g_StatusReg.WRST0 = 0; g_StatusReg.WRST1 = 0; g_StatusReg.WRST2 = 0; @@ -524,6 +525,42 @@ void AddDevice(const TSIDevices _device, int _iDeviceNumber) _dbg_assert_(SERIALINTERFACE, g_Channel[_iDeviceNumber].m_pDevice != NULL); } +void ChangeDeviceCallback(u64 userdata, int cyclesLate) +{ + u8 channel = (u8)(userdata >> 32); + // doubt this matters... +// g_Channel[channel].m_Out.Hex = 0; +// g_Channel[channel].m_InHi.Hex = 0; +// g_Channel[channel].m_InLo.Hex = 0; + + // raise the NO RESPONSE error + switch (channel) + { + case 0: + g_StatusReg.NOREP0 = 1; + break; + case 1: + g_StatusReg.NOREP1 = 1; + break; + case 2: + g_StatusReg.NOREP2 = 1; + break; + case 3: + g_StatusReg.NOREP3 = 1; + break; + } + + AddDevice((TSIDevices)(u32)userdata, channel); +} + +void ChangeDevice(TSIDevices device, int deviceNumber) +{ + // Called from GUI, so we need to make it thread safe. + // Let the hardware see no device for .5b cycles + CoreTiming::ScheduleEvent_Threadsafe(0, changeDevice, (SI_DUMMY | (u64)deviceNumber << 32)); + CoreTiming::ScheduleEvent_Threadsafe(500000000, changeDevice, (device | (u64)deviceNumber << 32)); +} + void UpdateDevices() { // Update channels diff --git a/Source/Core/Core/Src/HW/SI.h b/Source/Core/Core/Src/HW/SI.h index de5e7661d6..42ac39eddc 100644 --- a/Source/Core/Core/Src/HW/SI.h +++ b/Source/Core/Core/Src/HW/SI.h @@ -33,6 +33,9 @@ void UpdateDevices(); void RemoveDevice(int _iDeviceNumber); void AddDevice(const TSIDevices _device, int _iDeviceNumber); +void ChangeDeviceCallback(u64 userdata, int cyclesLate); +void ChangeDevice(TSIDevices device, int deviceNumber); + void Read32(u32& _uReturnValue, const u32 _iAddress); void Write32(const u32 _iValue, const u32 _iAddress); diff --git a/Source/Core/Core/Src/HW/SI_Device.cpp b/Source/Core/Core/Src/HW/SI_Device.cpp index 66474ec9cc..fed00ad3d6 100644 --- a/Source/Core/Core/Src/HW/SI_Device.cpp +++ b/Source/Core/Core/Src/HW/SI_Device.cpp @@ -63,8 +63,9 @@ public: int RunBuffer(u8* _pBuffer, int _iLength) { - // (shuffle2) Logging of this function will be done above, in ISIDevice::RunBuffer - // No device. (shuffle2) Maybe this should be SI_ERROR_NO_RESPONSE? + // Debug logging + ISIDevice::RunBuffer(_pBuffer, _iLength); + reinterpret_cast(_pBuffer)[0] = 0x00000000; return 4; } diff --git a/Source/Core/Core/Src/HW/SI_DeviceGCController.cpp b/Source/Core/Core/Src/HW/SI_DeviceGCController.cpp index ee1226eef6..c8a19af89f 100644 --- a/Source/Core/Core/Src/HW/SI_DeviceGCController.cpp +++ b/Source/Core/Core/Src/HW/SI_DeviceGCController.cpp @@ -90,7 +90,7 @@ int CSIDevice_GCController::RunBuffer(u8* _pBuffer, int _iLength) iPosition = _iLength; break; - // WII Something + // WII Something - this could be bogus case 0xCE: WARN_LOG(SERIALINTERFACE, "Unknown Wii SI Command"); break; @@ -113,6 +113,9 @@ int CSIDevice_GCController::RunBuffer(u8* _pBuffer, int _iLength) // GetData ////////////////////////////////////////////////////////////////////////// // Return true on new data (max 7 Bytes and 6 bits ;) +// [00?SYXBA] [1LRZUDRL] [x] [y] [cx] [cy] [l] [r] +// |\_ ERR_LATCH (error latched - check SISR) +// |_ ERR_STATUS (error on last GetData or SendCmd?) bool CSIDevice_GCController::GetData(u32& _Hi, u32& _Low) { @@ -123,18 +126,16 @@ CSIDevice_GCController::GetData(u32& _Hi, u32& _Low) _Hi = (u32)((u8)PadStatus.stickY); _Hi |= (u32)((u8)PadStatus.stickX << 8); - _Hi |= (u32)((u16)PadStatus.button << 16); + _Hi |= (u32)((u16)PadStatus.button << 16); // The highest 3bits should always be 0 + _Hi |= 0x00800000; // This bit is always on + //_Hi |= 0x20000000; // ? _Low = (u8)PadStatus.triggerRight; _Low |= (u32)((u8)PadStatus.triggerLeft << 8); _Low |= (u32)((u8)PadStatus.substickY << 16); _Low |= (u32)((u8)PadStatus.substickX << 24); - SetMic(PadStatus.MicButton); // This is dumb and should not be here - // F|RES: - // i dunno if i should force it here - // means that the pad must be "combined" with the origin to math the "final" OSPad-Struct - _Hi |= 0x00800000; + SetMic(PadStatus.MicButton); // This is dumb and should not be here return true; } diff --git a/Source/Core/Core/Src/HW/SI_DeviceGCController.h b/Source/Core/Core/Src/HW/SI_DeviceGCController.h index 8608e36390..39b66c3664 100644 --- a/Source/Core/Core/Src/HW/SI_DeviceGCController.h +++ b/Source/Core/Core/Src/HW/SI_DeviceGCController.h @@ -71,7 +71,6 @@ private: }; SOrigin m_origin; - int DeviceNum; public: diff --git a/Source/Core/DolphinWX/Src/ConfigMain.cpp b/Source/Core/DolphinWX/Src/ConfigMain.cpp index 292432bf40..3be36d3e72 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.cpp +++ b/Source/Core/DolphinWX/Src/ConfigMain.cpp @@ -20,6 +20,7 @@ #include "Core.h" // Core #include "HW/EXI.h" +#include "HW/SI.h" #include "ConsoleWindow.h" #include "Globals.h" // Local @@ -137,8 +138,6 @@ void CConfigMain::UpdateGUI() SkipIdle->Disable(); EnableCheats->Disable(); GCSystemLang->Disable(); - // Disable GC SI Stuff, but devices should be dynamic soon - GCSIDevice[0]->Disable(); GCSIDevice[1]->Disable(); GCSIDevice[2]->Disable(); GCSIDevice[3]->Disable(); WiiPage->Disable(); PathsPage->Disable(); PluginPage->Disable(); @@ -705,6 +704,12 @@ void CConfigMain::ChooseSIDevice(std::string deviceName, int deviceNum) tempType = SI_DUMMY; SConfig::GetInstance().m_SIDevice[deviceNum] = tempType; + + if (Core::GetState() != Core::CORE_UNINITIALIZED) + { + // Change plugged device! :D + SerialInterface::ChangeDevice(tempType, deviceNum); + } } void CConfigMain::ChooseEXIDevice(std::string deviceName, int deviceNum)