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:
parent
8ec6c0eea4
commit
e65ba57814
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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<u32*>(_pBuffer)[0] = 0x00000000;
|
||||
return 4;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -71,7 +71,6 @@ private:
|
|||
};
|
||||
|
||||
SOrigin m_origin;
|
||||
int DeviceNum;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue