From 9a93928e3e5a3e9dff48aabb9c8bbe78c53f3e1d Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Sat, 28 Feb 2009 21:30:43 +0000 Subject: [PATCH] allow hotplugging of exi devices. memcard_a seems to have some bug which convinces the hw there is a 0mb device there when it's really a dummy device... git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2481 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/Src/HW/EXI.cpp | 24 ++++++- Source/Core/Core/Src/HW/EXI.h | 5 ++ Source/Core/DolphinWX/Src/ConfigMain.cpp | 82 +++++++++++++----------- Source/Core/DolphinWX/Src/ConfigMain.h | 1 + 4 files changed, 74 insertions(+), 38 deletions(-) diff --git a/Source/Core/Core/Src/HW/EXI.cpp b/Source/Core/Core/Src/HW/EXI.cpp index 8b470d0e13..9ad70840c0 100644 --- a/Source/Core/Core/Src/HW/EXI.cpp +++ b/Source/Core/Core/Src/HW/EXI.cpp @@ -18,15 +18,18 @@ #include "Common.h" #include "ChunkFile.h" #include "../ConfigManager.h" +#include "../CoreTiming.h" #include "PeripheralInterface.h" #include "../PowerPC/PowerPC.h" -#include "EXI_Channel.h" +#include "EXI.h" namespace ExpansionInterface { +static int changeDevice; + enum { NUM_CHANNELS = 3 @@ -49,6 +52,8 @@ void Init() g_Channels[0].AddDevice(SConfig::GetInstance().m_EXIDevice[2], 2); g_Channels[1].AddDevice(SConfig::GetInstance().m_EXIDevice[1], 0); g_Channels[2].AddDevice(EXIDEVICE_AD16, 0); + + changeDevice = CoreTiming::RegisterEvent("ChangeEXIDevice", ChangeDeviceCallback); } void Shutdown() @@ -62,6 +67,23 @@ void DoState(PointerWrap &p) // TODO: descend all the devices recursively. } +void ChangeDeviceCallback(u64 userdata, int cyclesLate) +{ + u8 channel = (u8)(userdata >> 32); + u8 device = (u8)(userdata >> 16); + u8 slot = (u8)userdata; + + g_Channels[channel].AddDevice((TEXIDevices)device, slot); +} + +void ChangeDevice(u8 channel, TEXIDevices device, u8 slot) +{ + // 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, ((u64)channel << 32) | ((u64)EXIDEVICE_DUMMY << 16) | slot); + CoreTiming::ScheduleEvent_Threadsafe(500000000, changeDevice, ((u64)channel << 32) | ((u64)device << 16) | slot); +} + void Update() { g_Channels[0].Update(); diff --git a/Source/Core/Core/Src/HW/EXI.h b/Source/Core/Core/Src/HW/EXI.h index 8499b629bc..2a8fc3813e 100644 --- a/Source/Core/Core/Src/HW/EXI.h +++ b/Source/Core/Core/Src/HW/EXI.h @@ -18,6 +18,8 @@ #define _EXIINTERFACE_H #include "Common.h" +#include "EXI_Channel.h" +#include "Thread.h" class PointerWrap; namespace ExpansionInterface @@ -30,6 +32,9 @@ void DoState(PointerWrap &p); void Update(); void UpdateInterrupts(); +void ChangeDeviceCallback(u64 userdata, int cyclesLate); +void ChangeDevice(u8 channel, TEXIDevices device, u8 slot); + void Read32(u32& _uReturnValue, const u32 _iAddress); void Write32(const u32 _iValue, const u32 _iAddress); diff --git a/Source/Core/DolphinWX/Src/ConfigMain.cpp b/Source/Core/DolphinWX/Src/ConfigMain.cpp index 38ac56111f..d4b8f807ed 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.cpp +++ b/Source/Core/DolphinWX/Src/ConfigMain.cpp @@ -19,6 +19,7 @@ #include #include "Core.h" // Core +#include "HW/EXI.h" #include "ConsoleWindow.h" #include "Globals.h" // Local @@ -135,10 +136,9 @@ void CConfigMain::UpdateGUI() OptimizeQuantizers->Disable(); SkipIdle->Disable(); EnableCheats->Disable(); - // Disable GC Stuff, but devices should be dynamic soon GCSystemLang->Disable(); - GCEXIDevice[0]->Disable(); GCEXIDevice[1]->Disable(); GCEXIDevice[2]->Disable(); GCMemcardPath[0]->Disable(); GCMemcardPath[1]->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(); @@ -628,51 +628,26 @@ void CConfigMain::CoreSettingsChanged(wxCommandEvent& event) void CConfigMain::GCSettingsChanged(wxCommandEvent& event) { int sidevice = 0; + int exidevice = 0; switch (event.GetId()) { case ID_GC_SRAM_LNG: SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage = GCSystemLang->GetSelection(); break; + case ID_GC_EXIDEVICE_SP1: // The only thing we emulate on SP1 is the BBA + exidevice++; + case ID_GC_EXIDEVICE_SLOTB: + exidevice++; case ID_GC_EXIDEVICE_SLOTA: - switch (event.GetSelection()) - { - case 1: // memcard - SConfig::GetInstance().m_EXIDevice[0] = EXIDEVICE_MEMORYCARD_A; - break; - case 2: // mic - SConfig::GetInstance().m_EXIDevice[0] = EXIDEVICE_MIC; - break; - default: - SConfig::GetInstance().m_EXIDevice[0] = EXIDEVICE_DUMMY; - break; - } - GCMemcardPath[0]->Enable(event.GetSelection() == 1); + ChooseEXIDevice(std::string(event.GetString().mb_str()), exidevice); break; case ID_GC_EXIDEVICE_SLOTA_PATH: ChooseMemcardPath(SConfig::GetInstance().m_strMemoryCardA, true); break; - case ID_GC_EXIDEVICE_SLOTB: - switch (event.GetSelection()) - { - case 1: // memcard - SConfig::GetInstance().m_EXIDevice[1] = EXIDEVICE_MEMORYCARD_B; - break; - case 2: // mic - SConfig::GetInstance().m_EXIDevice[1] = EXIDEVICE_MIC; - break; - default: - SConfig::GetInstance().m_EXIDevice[1] = EXIDEVICE_DUMMY; - break; - } - GCMemcardPath[1]->Enable(event.GetSelection() == 1); - break; case ID_GC_EXIDEVICE_SLOTB_PATH: ChooseMemcardPath(SConfig::GetInstance().m_strMemoryCardB, false); break; - case ID_GC_EXIDEVICE_SP1: // The only thing we emulate on SP1 is the BBA - SConfig::GetInstance().m_EXIDevice[2] = event.GetSelection() ? EXIDEVICE_ETH : EXIDEVICE_DUMMY; - break; case ID_GC_SIDEVICE3: sidevice++; @@ -688,11 +663,13 @@ void CConfigMain::GCSettingsChanged(wxCommandEvent& event) void CConfigMain::ChooseMemcardPath(std::string& strMemcard, bool isSlotA) { - std::string filename = std::string(wxFileSelector - (wxT("Choose a file to open"), - wxT(FULL_GC_USER_DIR), isSlotA ? wxT(GC_MEMCARDA):wxT(GC_MEMCARDB), - wxEmptyString, + std::string filename = std::string(wxFileSelector( + wxT("Choose a file to open"), + wxT(FULL_GC_USER_DIR), + isSlotA ? wxT(GC_MEMCARDA) : wxT(GC_MEMCARDB), + wxEmptyString, wxT("Gamecube Memory Cards (*.raw,*.gcp)|*.raw;*.gcp")).mb_str()); + if (!filename.empty()) strMemcard = filename; } @@ -709,6 +686,37 @@ void CConfigMain::ChooseSIDevice(std::string deviceName, int deviceNum) SConfig::GetInstance().m_SIDevice[deviceNum] = tempType; } + +void CConfigMain::ChooseEXIDevice(std::string deviceName, int deviceNum) +{ + TEXIDevices tempType; + + if (deviceName.compare("Memory Card") == 0) + tempType = deviceNum ? EXIDEVICE_MEMORYCARD_B : EXIDEVICE_MEMORYCARD_A; + else if (deviceName.compare("Mic") == 0) + tempType = EXIDEVICE_MIC; + else if (deviceName.compare("BBA") == 0) + tempType = EXIDEVICE_ETH; + else + tempType = EXIDEVICE_DUMMY; + + // Gray out the memcard path button if we're not on a memcard + if (tempType == EXIDEVICE_MEMORYCARD_A || tempType == EXIDEVICE_MEMORYCARD_B) + GCMemcardPath[deviceNum]->Enable(); + else if (deviceNum == 0 || deviceNum == 1) + GCMemcardPath[deviceNum]->Disable(); + + SConfig::GetInstance().m_EXIDevice[deviceNum] = tempType; + + if (Core::GetState() != Core::CORE_UNINITIALIZED) + { + // Change plugged device! :D + ExpansionInterface::ChangeDevice( + (deviceNum == 1) ? 1 : 0, // SlotB is on channel 1, slotA and SP1 are on 0 + tempType, // The device enum to change to + (deviceNum == 2) ? 2 : 0); // SP1 is device 2, slots are device 0 + } +} /////////////////////////////////////////// diff --git a/Source/Core/DolphinWX/Src/ConfigMain.h b/Source/Core/DolphinWX/Src/ConfigMain.h index edd8bbe4f8..60fbdd487f 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.h +++ b/Source/Core/DolphinWX/Src/ConfigMain.h @@ -281,6 +281,7 @@ class CConfigMain void GCSettingsChanged(wxCommandEvent& event); void ChooseMemcardPath(std::string& strMemcard, bool isSlotA); void ChooseSIDevice(std::string deviceName, int deviceNum); + void ChooseEXIDevice(std::string deviceName, int deviceNum); void WiiSettingsChanged(wxCommandEvent& event); void ISOPathsSelectionChanged(wxCommandEvent& event); void AddRemoveISOPaths(wxCommandEvent& event);