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
This commit is contained in:
Shawn Hoffman 2009-02-28 21:30:43 +00:00
parent c83a034d12
commit 9a93928e3e
4 changed files with 74 additions and 38 deletions

View File

@ -18,15 +18,18 @@
#include "Common.h" #include "Common.h"
#include "ChunkFile.h" #include "ChunkFile.h"
#include "../ConfigManager.h" #include "../ConfigManager.h"
#include "../CoreTiming.h"
#include "PeripheralInterface.h" #include "PeripheralInterface.h"
#include "../PowerPC/PowerPC.h" #include "../PowerPC/PowerPC.h"
#include "EXI_Channel.h" #include "EXI.h"
namespace ExpansionInterface namespace ExpansionInterface
{ {
static int changeDevice;
enum enum
{ {
NUM_CHANNELS = 3 NUM_CHANNELS = 3
@ -49,6 +52,8 @@ void Init()
g_Channels[0].AddDevice(SConfig::GetInstance().m_EXIDevice[2], 2); g_Channels[0].AddDevice(SConfig::GetInstance().m_EXIDevice[2], 2);
g_Channels[1].AddDevice(SConfig::GetInstance().m_EXIDevice[1], 0); g_Channels[1].AddDevice(SConfig::GetInstance().m_EXIDevice[1], 0);
g_Channels[2].AddDevice(EXIDEVICE_AD16, 0); g_Channels[2].AddDevice(EXIDEVICE_AD16, 0);
changeDevice = CoreTiming::RegisterEvent("ChangeEXIDevice", ChangeDeviceCallback);
} }
void Shutdown() void Shutdown()
@ -62,6 +67,23 @@ void DoState(PointerWrap &p)
// TODO: descend all the devices recursively. // 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() void Update()
{ {
g_Channels[0].Update(); g_Channels[0].Update();

View File

@ -18,6 +18,8 @@
#define _EXIINTERFACE_H #define _EXIINTERFACE_H
#include "Common.h" #include "Common.h"
#include "EXI_Channel.h"
#include "Thread.h"
class PointerWrap; class PointerWrap;
namespace ExpansionInterface namespace ExpansionInterface
@ -30,6 +32,9 @@ void DoState(PointerWrap &p);
void Update(); void Update();
void UpdateInterrupts(); void UpdateInterrupts();
void ChangeDeviceCallback(u64 userdata, int cyclesLate);
void ChangeDevice(u8 channel, TEXIDevices device, u8 slot);
void Read32(u32& _uReturnValue, const u32 _iAddress); void Read32(u32& _uReturnValue, const u32 _iAddress);
void Write32(const u32 _iValue, const u32 _iAddress); void Write32(const u32 _iValue, const u32 _iAddress);

View File

@ -19,6 +19,7 @@
#include <vector> #include <vector>
#include "Core.h" // Core #include "Core.h" // Core
#include "HW/EXI.h"
#include "ConsoleWindow.h" #include "ConsoleWindow.h"
#include "Globals.h" // Local #include "Globals.h" // Local
@ -135,10 +136,9 @@ void CConfigMain::UpdateGUI()
OptimizeQuantizers->Disable(); OptimizeQuantizers->Disable();
SkipIdle->Disable(); SkipIdle->Disable();
EnableCheats->Disable(); EnableCheats->Disable();
// Disable GC Stuff, but devices should be dynamic soon
GCSystemLang->Disable(); GCSystemLang->Disable();
GCEXIDevice[0]->Disable(); GCEXIDevice[1]->Disable(); GCEXIDevice[2]->Disable();
GCMemcardPath[0]->Disable(); GCMemcardPath[1]->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(); GCSIDevice[0]->Disable(); GCSIDevice[1]->Disable(); GCSIDevice[2]->Disable(); GCSIDevice[3]->Disable();
WiiPage->Disable(); WiiPage->Disable();
PathsPage->Disable(); PathsPage->Disable();
@ -628,51 +628,26 @@ void CConfigMain::CoreSettingsChanged(wxCommandEvent& event)
void CConfigMain::GCSettingsChanged(wxCommandEvent& event) void CConfigMain::GCSettingsChanged(wxCommandEvent& event)
{ {
int sidevice = 0; int sidevice = 0;
int exidevice = 0;
switch (event.GetId()) switch (event.GetId())
{ {
case ID_GC_SRAM_LNG: case ID_GC_SRAM_LNG:
SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage = GCSystemLang->GetSelection(); SConfig::GetInstance().m_LocalCoreStartupParameter.SelectedLanguage = GCSystemLang->GetSelection();
break; 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: case ID_GC_EXIDEVICE_SLOTA:
switch (event.GetSelection()) ChooseEXIDevice(std::string(event.GetString().mb_str()), exidevice);
{
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);
break; break;
case ID_GC_EXIDEVICE_SLOTA_PATH: case ID_GC_EXIDEVICE_SLOTA_PATH:
ChooseMemcardPath(SConfig::GetInstance().m_strMemoryCardA, true); ChooseMemcardPath(SConfig::GetInstance().m_strMemoryCardA, true);
break; 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: case ID_GC_EXIDEVICE_SLOTB_PATH:
ChooseMemcardPath(SConfig::GetInstance().m_strMemoryCardB, false); ChooseMemcardPath(SConfig::GetInstance().m_strMemoryCardB, false);
break; 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: case ID_GC_SIDEVICE3:
sidevice++; sidevice++;
@ -688,11 +663,13 @@ void CConfigMain::GCSettingsChanged(wxCommandEvent& event)
void CConfigMain::ChooseMemcardPath(std::string& strMemcard, bool isSlotA) void CConfigMain::ChooseMemcardPath(std::string& strMemcard, bool isSlotA)
{ {
std::string filename = std::string(wxFileSelector std::string filename = std::string(wxFileSelector(
(wxT("Choose a file to open"), wxT("Choose a file to open"),
wxT(FULL_GC_USER_DIR), isSlotA ? wxT(GC_MEMCARDA):wxT(GC_MEMCARDB), wxT(FULL_GC_USER_DIR),
isSlotA ? wxT(GC_MEMCARDA) : wxT(GC_MEMCARDB),
wxEmptyString, wxEmptyString,
wxT("Gamecube Memory Cards (*.raw,*.gcp)|*.raw;*.gcp")).mb_str()); wxT("Gamecube Memory Cards (*.raw,*.gcp)|*.raw;*.gcp")).mb_str());
if (!filename.empty()) if (!filename.empty())
strMemcard = filename; strMemcard = filename;
} }
@ -709,6 +686,37 @@ void CConfigMain::ChooseSIDevice(std::string deviceName, int deviceNum)
SConfig::GetInstance().m_SIDevice[deviceNum] = tempType; 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
}
}
/////////////////////////////////////////// ///////////////////////////////////////////

View File

@ -281,6 +281,7 @@ class CConfigMain
void GCSettingsChanged(wxCommandEvent& event); void GCSettingsChanged(wxCommandEvent& event);
void ChooseMemcardPath(std::string& strMemcard, bool isSlotA); void ChooseMemcardPath(std::string& strMemcard, bool isSlotA);
void ChooseSIDevice(std::string deviceName, int deviceNum); void ChooseSIDevice(std::string deviceName, int deviceNum);
void ChooseEXIDevice(std::string deviceName, int deviceNum);
void WiiSettingsChanged(wxCommandEvent& event); void WiiSettingsChanged(wxCommandEvent& event);
void ISOPathsSelectionChanged(wxCommandEvent& event); void ISOPathsSelectionChanged(wxCommandEvent& event);
void AddRemoveISOPaths(wxCommandEvent& event); void AddRemoveISOPaths(wxCommandEvent& event);