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
This commit is contained in:
Shawn Hoffman 2009-03-02 04:02:09 +00:00
parent 8ec6c0eea4
commit e65ba57814
6 changed files with 83 additions and 37 deletions

View File

@ -18,6 +18,7 @@
#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"
@ -26,6 +27,8 @@
namespace SerialInterface namespace SerialInterface
{ {
static int changeDevice;
void RunSIBuffer(); void RunSIBuffer();
void UpdateInterrupts(); void UpdateInterrupts();
@ -229,7 +232,6 @@ void DoState(PointerWrap &p)
void Init() void Init()
{ {
// TODO: allow dynamic attaching/detaching of devices
for (int i = 0; i < NUMBER_OF_CHANNELS; i++) for (int i = 0; i < NUMBER_OF_CHANNELS; i++)
{ {
g_Channel[i].m_Out.Hex = 0; g_Channel[i].m_Out.Hex = 0;
@ -243,16 +245,15 @@ void Init()
g_ComCSR.Hex = 0; g_ComCSR.Hex = 0;
g_StatusReg.Hex = 0; g_StatusReg.Hex = 0;
g_EXIClockCount.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() void Shutdown()
{ {
for (int i = 0; i < NUMBER_OF_CHANNELS; i++) for (int i = 0; i < NUMBER_OF_CHANNELS; i++)
{ RemoveDevice(i);
delete g_Channel[i].m_pDevice;
g_Channel[i].m_pDevice = NULL;
}
} }
void Read32(u32& _uReturnValue, const u32 _iAddress) 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.RDSTINT) g_ComCSR.RDSTINT = 0;
if (tmpComCSR.TCINT) g_ComCSR.TCINT = 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(); if (tmpComCSR.TSTART) RunSIBuffer();
UpdateInterrupts(); UpdateInterrupts();
} }
@ -419,36 +420,36 @@ void Write32(const u32 _iValue, const u32 _iAddress)
{ {
USIStatusReg tmpStatus(_iValue); USIStatusReg tmpStatus(_iValue);
// just update the writable bits // clear bits ( if(tmp.bit) SISR.bit=0 )
g_StatusReg.NOREP0 = tmpStatus.NOREP0 ? 1 : 0; if (tmpStatus.NOREP0) g_StatusReg.NOREP0 = 0;
g_StatusReg.COLL0 = tmpStatus.COLL0 ? 1 : 0; if (tmpStatus.COLL0) g_StatusReg.COLL0 = 0;
g_StatusReg.OVRUN0 = tmpStatus.OVRUN0 ? 1 : 0; if (tmpStatus.OVRUN0) g_StatusReg.OVRUN0 = 0;
g_StatusReg.UNRUN0 = tmpStatus.UNRUN0 ? 1 : 0; if (tmpStatus.UNRUN0) g_StatusReg.UNRUN0 = 0;
g_StatusReg.NOREP1 = tmpStatus.NOREP1 ? 1 : 0; if (tmpStatus.NOREP1) g_StatusReg.NOREP1 = 0;
g_StatusReg.COLL1 = tmpStatus.COLL1 ? 1 : 0; if (tmpStatus.COLL1) g_StatusReg.COLL1 = 0;
g_StatusReg.OVRUN1 = tmpStatus.OVRUN1 ? 1 : 0; if (tmpStatus.OVRUN1) g_StatusReg.OVRUN1 = 0;
g_StatusReg.UNRUN1 = tmpStatus.UNRUN1 ? 1 : 0; if (tmpStatus.UNRUN1) g_StatusReg.UNRUN1 = 0;
g_StatusReg.NOREP2 = tmpStatus.NOREP2 ? 1 : 0; if (tmpStatus.NOREP2) g_StatusReg.NOREP2 = 0;
g_StatusReg.COLL2 = tmpStatus.COLL2 ? 1 : 0; if (tmpStatus.COLL2) g_StatusReg.COLL2 = 0;
g_StatusReg.OVRUN2 = tmpStatus.OVRUN2 ? 1 : 0; if (tmpStatus.OVRUN2) g_StatusReg.OVRUN2 = 0;
g_StatusReg.UNRUN2 = tmpStatus.UNRUN2 ? 1 : 0; if (tmpStatus.UNRUN2) g_StatusReg.UNRUN2 = 0;
g_StatusReg.NOREP3 = tmpStatus.NOREP3 ? 1 : 0; if (tmpStatus.NOREP3) g_StatusReg.NOREP3 = 0;
g_StatusReg.COLL3 = tmpStatus.COLL3 ? 1 : 0; if (tmpStatus.COLL3) g_StatusReg.COLL3 = 0;
g_StatusReg.OVRUN3 = tmpStatus.OVRUN3 ? 1 : 0; if (tmpStatus.OVRUN3) g_StatusReg.OVRUN3 = 0;
g_StatusReg.UNRUN3 = tmpStatus.UNRUN3 ? 1 : 0; if (tmpStatus.UNRUN3) g_StatusReg.UNRUN3 = 0;
// send command to devices // send command to devices
if (tmpStatus.WR) if (tmpStatus.WR)
{ {
g_StatusReg.WR = 0;
g_Channel[0].m_pDevice->SendCommand(g_Channel[0].m_Out.Hex); 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[1].m_pDevice->SendCommand(g_Channel[1].m_Out.Hex);
g_Channel[2].m_pDevice->SendCommand(g_Channel[2].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_Channel[3].m_pDevice->SendCommand(g_Channel[3].m_Out.Hex);
g_StatusReg.WR = 0;
g_StatusReg.WRST0 = 0; g_StatusReg.WRST0 = 0;
g_StatusReg.WRST1 = 0; g_StatusReg.WRST1 = 0;
g_StatusReg.WRST2 = 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); _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() void UpdateDevices()
{ {
// Update channels // Update channels

View File

@ -33,6 +33,9 @@ void UpdateDevices();
void RemoveDevice(int _iDeviceNumber); void RemoveDevice(int _iDeviceNumber);
void AddDevice(const TSIDevices _device, 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 Read32(u32& _uReturnValue, const u32 _iAddress);
void Write32(const u32 _iValue, const u32 _iAddress); void Write32(const u32 _iValue, const u32 _iAddress);

View File

@ -63,8 +63,9 @@ public:
int RunBuffer(u8* _pBuffer, int _iLength) int RunBuffer(u8* _pBuffer, int _iLength)
{ {
// (shuffle2) Logging of this function will be done above, in ISIDevice::RunBuffer // Debug logging
// No device. (shuffle2) Maybe this should be SI_ERROR_NO_RESPONSE? ISIDevice::RunBuffer(_pBuffer, _iLength);
reinterpret_cast<u32*>(_pBuffer)[0] = 0x00000000; reinterpret_cast<u32*>(_pBuffer)[0] = 0x00000000;
return 4; return 4;
} }

View File

@ -90,7 +90,7 @@ int CSIDevice_GCController::RunBuffer(u8* _pBuffer, int _iLength)
iPosition = _iLength; iPosition = _iLength;
break; break;
// WII Something // WII Something - this could be bogus
case 0xCE: case 0xCE:
WARN_LOG(SERIALINTERFACE, "Unknown Wii SI Command"); WARN_LOG(SERIALINTERFACE, "Unknown Wii SI Command");
break; break;
@ -113,6 +113,9 @@ int CSIDevice_GCController::RunBuffer(u8* _pBuffer, int _iLength)
// GetData // GetData
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Return true on new data (max 7 Bytes and 6 bits ;) // 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 bool
CSIDevice_GCController::GetData(u32& _Hi, u32& _Low) 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.stickY);
_Hi |= (u32)((u8)PadStatus.stickX << 8); _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 = (u8)PadStatus.triggerRight;
_Low |= (u32)((u8)PadStatus.triggerLeft << 8); _Low |= (u32)((u8)PadStatus.triggerLeft << 8);
_Low |= (u32)((u8)PadStatus.substickY << 16); _Low |= (u32)((u8)PadStatus.substickY << 16);
_Low |= (u32)((u8)PadStatus.substickX << 24); _Low |= (u32)((u8)PadStatus.substickX << 24);
SetMic(PadStatus.MicButton); // This is dumb and should not be here
// F|RES: SetMic(PadStatus.MicButton); // This is dumb and should not be here
// 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;
return true; return true;
} }

View File

@ -71,7 +71,6 @@ private:
}; };
SOrigin m_origin; SOrigin m_origin;
int DeviceNum;
public: public:

View File

@ -20,6 +20,7 @@
#include "Core.h" // Core #include "Core.h" // Core
#include "HW/EXI.h" #include "HW/EXI.h"
#include "HW/SI.h"
#include "ConsoleWindow.h" #include "ConsoleWindow.h"
#include "Globals.h" // Local #include "Globals.h" // Local
@ -137,8 +138,6 @@ void CConfigMain::UpdateGUI()
SkipIdle->Disable(); SkipIdle->Disable();
EnableCheats->Disable(); EnableCheats->Disable();
GCSystemLang->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(); WiiPage->Disable();
PathsPage->Disable(); PathsPage->Disable();
PluginPage->Disable(); PluginPage->Disable();
@ -705,6 +704,12 @@ void CConfigMain::ChooseSIDevice(std::string deviceName, int deviceNum)
tempType = SI_DUMMY; tempType = SI_DUMMY;
SConfig::GetInstance().m_SIDevice[deviceNum] = tempType; 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) void CConfigMain::ChooseEXIDevice(std::string deviceName, int deviceNum)