mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 06:09:50 -06:00
replace SI_DUMMY with SI_NONE, an actual null device.
tweak SI a little so that it doesn't block things which block on the status reg. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4713 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
@ -228,7 +228,7 @@ void SConfig::LoadSettings()
|
|||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
sprintf(sidevicenum, "SIDevice%i", i);
|
sprintf(sidevicenum, "SIDevice%i", i);
|
||||||
ini.Get("Core", sidevicenum, (u32*)&m_SIDevice[i], i==0 ? SI_GC_CONTROLLER:SI_DUMMY);
|
ini.Get("Core", sidevicenum, (u32*)&m_SIDevice[i], i==0 ? SI_GC_CONTROLLER:SI_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
ini.Get("Core", "RunCompareServer", &m_LocalCoreStartupParameter.bRunCompareServer, false);
|
ini.Get("Core", "RunCompareServer", &m_LocalCoreStartupParameter.bRunCompareServer, false);
|
||||||
|
@ -75,10 +75,10 @@ union USIChannelOut
|
|||||||
u32 Hex;
|
u32 Hex;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned OUTPUT1 : 8;
|
u32 OUTPUT1 : 8;
|
||||||
unsigned OUTPUT0 : 8;
|
u32 OUTPUT0 : 8;
|
||||||
unsigned CMD : 8;
|
u32 CMD : 8;
|
||||||
unsigned : 8;
|
u32 : 8;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -88,12 +88,12 @@ union USIChannelIn_Hi
|
|||||||
u32 Hex;
|
u32 Hex;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned INPUT3 : 8;
|
u32 INPUT3 : 8;
|
||||||
unsigned INPUT2 : 8;
|
u32 INPUT2 : 8;
|
||||||
unsigned INPUT1 : 8;
|
u32 INPUT1 : 8;
|
||||||
unsigned INPUT0 : 6;
|
u32 INPUT0 : 6;
|
||||||
unsigned ERRLATCH : 1; // 0: no error 1: Error latched. Check SISR.
|
u32 ERRLATCH : 1; // 0: no error 1: Error latched. Check SISR.
|
||||||
unsigned ERRSTAT : 1; // 0: no error 1: error on last transfer
|
u32 ERRSTAT : 1; // 0: no error 1: error on last transfer
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -103,10 +103,10 @@ union USIChannelIn_Lo
|
|||||||
u32 Hex;
|
u32 Hex;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned INPUT7 : 8;
|
u32 INPUT7 : 8;
|
||||||
unsigned INPUT6 : 8;
|
u32 INPUT6 : 8;
|
||||||
unsigned INPUT5 : 8;
|
u32 INPUT5 : 8;
|
||||||
unsigned INPUT4 : 8;
|
u32 INPUT4 : 8;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -125,17 +125,17 @@ union USIPoll
|
|||||||
u32 Hex;
|
u32 Hex;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned VBCPY3 : 1; // 1: write to output buffer only on vblank
|
u32 VBCPY3 : 1; // 1: write to output buffer only on vblank
|
||||||
unsigned VBCPY2 : 1;
|
u32 VBCPY2 : 1;
|
||||||
unsigned VBCPY1 : 1;
|
u32 VBCPY1 : 1;
|
||||||
unsigned VBCPY0 : 1;
|
u32 VBCPY0 : 1;
|
||||||
unsigned EN3 : 1; // Enable polling of channel
|
u32 EN3 : 1; // Enable polling of channel
|
||||||
unsigned EN2 : 1; // does not affect communication RAM transfers
|
u32 EN2 : 1; // does not affect communication RAM transfers
|
||||||
unsigned EN1 : 1;
|
u32 EN1 : 1;
|
||||||
unsigned EN0 : 1;
|
u32 EN0 : 1;
|
||||||
unsigned Y : 8; // Polls per frame
|
u32 Y : 8; // Polls per frame
|
||||||
unsigned X : 10; // Polls per X lines. begins at vsync, min 7, max depends on video mode
|
u32 X : 10; // Polls per X lines. begins at vsync, min 7, max depends on video mode
|
||||||
unsigned : 6;
|
u32 : 6;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -145,22 +145,22 @@ union USIComCSR
|
|||||||
u32 Hex;
|
u32 Hex;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned TSTART : 1; // write: start transfer read: transfer status
|
u32 TSTART : 1; // write: start transfer read: transfer status
|
||||||
unsigned CHANNEL : 2; // determines which SI channel will be used on the communication interface.
|
u32 CHANNEL : 2; // determines which SI channel will be used on the communication interface.
|
||||||
unsigned : 3;
|
u32 : 3;
|
||||||
unsigned CALLBEN : 1; // Callback enable
|
u32 CALLBEN : 1; // Callback enable
|
||||||
unsigned CMDEN : 1; // Command enable?
|
u32 CMDEN : 1; // Command enable?
|
||||||
unsigned INLNGTH : 7;
|
u32 INLNGTH : 7;
|
||||||
unsigned : 1;
|
u32 : 1;
|
||||||
unsigned OUTLNGTH : 7; // Communication Channel Output Length in bytes
|
u32 OUTLNGTH : 7; // Communication Channel Output Length in bytes
|
||||||
unsigned : 1;
|
u32 : 1;
|
||||||
unsigned CHANEN : 1; // Channel enable?
|
u32 CHANEN : 1; // Channel enable?
|
||||||
unsigned CHANNUM : 2; // Channel number?
|
u32 CHANNUM : 2; // Channel number?
|
||||||
unsigned RDSTINTMSK : 1; // Read Status Interrupt Status Mask
|
u32 RDSTINTMSK : 1; // Read Status Interrupt Status Mask
|
||||||
unsigned RDSTINT : 1; // Read Status Interrupt Status
|
u32 RDSTINT : 1; // Read Status Interrupt Status
|
||||||
unsigned COMERR : 1; // Communication Error (set 0)
|
u32 COMERR : 1; // Communication Error (set 0)
|
||||||
unsigned TCINTMSK : 1; // Transfer Complete Interrupt Mask
|
u32 TCINTMSK : 1; // Transfer Complete Interrupt Mask
|
||||||
unsigned TCINT : 1; // Transfer Complete Interrupt
|
u32 TCINT : 1; // Transfer Complete Interrupt
|
||||||
};
|
};
|
||||||
USIComCSR() {Hex = 0;}
|
USIComCSR() {Hex = 0;}
|
||||||
USIComCSR(u32 _hex) {Hex = _hex;}
|
USIComCSR(u32 _hex) {Hex = _hex;}
|
||||||
@ -172,35 +172,35 @@ union USIStatusReg
|
|||||||
u32 Hex;
|
u32 Hex;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned UNRUN3 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error
|
u32 UNRUN3 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error
|
||||||
unsigned OVRUN3 : 1; // (RWC) write 1: bit cleared read 1: overrun error
|
u32 OVRUN3 : 1; // (RWC) write 1: bit cleared read 1: overrun error
|
||||||
unsigned COLL3 : 1; // (RWC) write 1: bit cleared read 1: collision error
|
u32 COLL3 : 1; // (RWC) write 1: bit cleared read 1: collision error
|
||||||
unsigned NOREP3 : 1; // (RWC) write 1: bit cleared read 1: response error
|
u32 NOREP3 : 1; // (RWC) write 1: bit cleared read 1: response error
|
||||||
unsigned WRST3 : 1; // (R) 1: buffer channel0 not copied
|
u32 WRST3 : 1; // (R) 1: buffer channel0 not copied
|
||||||
unsigned RDST3 : 1; // (R) 1: new Data available
|
u32 RDST3 : 1; // (R) 1: new Data available
|
||||||
unsigned : 2; // 7:6
|
u32 : 2; // 7:6
|
||||||
unsigned UNRUN2 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error
|
u32 UNRUN2 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error
|
||||||
unsigned OVRUN2 : 1; // (RWC) write 1: bit cleared read 1: overrun error
|
u32 OVRUN2 : 1; // (RWC) write 1: bit cleared read 1: overrun error
|
||||||
unsigned COLL2 : 1; // (RWC) write 1: bit cleared read 1: collision error
|
u32 COLL2 : 1; // (RWC) write 1: bit cleared read 1: collision error
|
||||||
unsigned NOREP2 : 1; // (RWC) write 1: bit cleared read 1: response error
|
u32 NOREP2 : 1; // (RWC) write 1: bit cleared read 1: response error
|
||||||
unsigned WRST2 : 1; // (R) 1: buffer channel0 not copied
|
u32 WRST2 : 1; // (R) 1: buffer channel0 not copied
|
||||||
unsigned RDST2 : 1; // (R) 1: new Data available
|
u32 RDST2 : 1; // (R) 1: new Data available
|
||||||
unsigned : 2; // 15:14
|
u32 : 2; // 15:14
|
||||||
unsigned UNRUN1 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error
|
u32 UNRUN1 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error
|
||||||
unsigned OVRUN1 : 1; // (RWC) write 1: bit cleared read 1: overrun error
|
u32 OVRUN1 : 1; // (RWC) write 1: bit cleared read 1: overrun error
|
||||||
unsigned COLL1 : 1; // (RWC) write 1: bit cleared read 1: collision error
|
u32 COLL1 : 1; // (RWC) write 1: bit cleared read 1: collision error
|
||||||
unsigned NOREP1 : 1; // (RWC) write 1: bit cleared read 1: response error
|
u32 NOREP1 : 1; // (RWC) write 1: bit cleared read 1: response error
|
||||||
unsigned WRST1 : 1; // (R) 1: buffer channel0 not copied
|
u32 WRST1 : 1; // (R) 1: buffer channel0 not copied
|
||||||
unsigned RDST1 : 1; // (R) 1: new Data available
|
u32 RDST1 : 1; // (R) 1: new Data available
|
||||||
unsigned : 2; // 23:22
|
u32 : 2; // 23:22
|
||||||
unsigned UNRUN0 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error
|
u32 UNRUN0 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error
|
||||||
unsigned OVRUN0 : 1; // (RWC) write 1: bit cleared read 1: overrun error
|
u32 OVRUN0 : 1; // (RWC) write 1: bit cleared read 1: overrun error
|
||||||
unsigned COLL0 : 1; // (RWC) write 1: bit cleared read 1: collision error
|
u32 COLL0 : 1; // (RWC) write 1: bit cleared read 1: collision error
|
||||||
unsigned NOREP0 : 1; // (RWC) write 1: bit cleared read 1: response error
|
u32 NOREP0 : 1; // (RWC) write 1: bit cleared read 1: response error
|
||||||
unsigned WRST0 : 1; // (R) 1: buffer channel0 not copied
|
u32 WRST0 : 1; // (R) 1: buffer channel0 not copied
|
||||||
unsigned RDST0 : 1; // (R) 1: new Data available
|
u32 RDST0 : 1; // (R) 1: new Data available
|
||||||
unsigned : 1;
|
u32 : 1;
|
||||||
unsigned WR : 1; // (RW) write 1 start copy, read 0 copy done
|
u32 WR : 1; // (RW) write 1 start copy, read 0 copy done
|
||||||
};
|
};
|
||||||
USIStatusReg() {Hex = 0;}
|
USIStatusReg() {Hex = 0;}
|
||||||
USIStatusReg(u32 _hex) {Hex = _hex;}
|
USIStatusReg(u32 _hex) {Hex = _hex;}
|
||||||
@ -212,8 +212,8 @@ union USIEXIClockCount
|
|||||||
u32 Hex;
|
u32 Hex;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned LOCK : 1; // 1: prevents CPU from setting EXI clock to 32MHz
|
u32 LOCK : 1; // 1: prevents CPU from setting EXI clock to 32MHz
|
||||||
unsigned : 30;
|
u32 : 0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -249,9 +249,13 @@ void Init()
|
|||||||
|
|
||||||
g_Poll.Hex = 0;
|
g_Poll.Hex = 0;
|
||||||
g_Poll.X = 7;
|
g_Poll.X = 7;
|
||||||
|
|
||||||
g_ComCSR.Hex = 0;
|
g_ComCSR.Hex = 0;
|
||||||
|
|
||||||
g_StatusReg.Hex = 0;
|
g_StatusReg.Hex = 0;
|
||||||
|
|
||||||
g_EXIClockCount.Hex = 0;
|
g_EXIClockCount.Hex = 0;
|
||||||
|
g_EXIClockCount.LOCK = 1;
|
||||||
memset(g_SIBuffer, 0, 128);
|
memset(g_SIBuffer, 0, 128);
|
||||||
|
|
||||||
changeDevice = CoreTiming::RegisterEvent("ChangeSIDevice", ChangeDeviceCallback);
|
changeDevice = CoreTiming::RegisterEvent("ChangeSIDevice", ChangeDeviceCallback);
|
||||||
@ -286,13 +290,11 @@ void Read32(u32& _uReturnValue, const u32 _iAddress)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case SI_CHANNEL_0_IN_HI:
|
case SI_CHANNEL_0_IN_HI:
|
||||||
g_StatusReg.RDST0 = 0;
|
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
_uReturnValue = g_Channel[0].m_InHi.Hex;
|
_uReturnValue = g_Channel[0].m_InHi.Hex;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case SI_CHANNEL_0_IN_LO:
|
case SI_CHANNEL_0_IN_LO:
|
||||||
g_StatusReg.RDST0 = 0;
|
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
_uReturnValue = g_Channel[0].m_InLo.Hex;
|
_uReturnValue = g_Channel[0].m_InLo.Hex;
|
||||||
return;
|
return;
|
||||||
@ -305,13 +307,11 @@ void Read32(u32& _uReturnValue, const u32 _iAddress)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case SI_CHANNEL_1_IN_HI:
|
case SI_CHANNEL_1_IN_HI:
|
||||||
g_StatusReg.RDST1 = 0;
|
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
_uReturnValue = g_Channel[1].m_InHi.Hex;
|
_uReturnValue = g_Channel[1].m_InHi.Hex;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case SI_CHANNEL_1_IN_LO:
|
case SI_CHANNEL_1_IN_LO:
|
||||||
g_StatusReg.RDST1 = 0;
|
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
_uReturnValue = g_Channel[1].m_InLo.Hex;
|
_uReturnValue = g_Channel[1].m_InLo.Hex;
|
||||||
return;
|
return;
|
||||||
@ -324,13 +324,11 @@ void Read32(u32& _uReturnValue, const u32 _iAddress)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case SI_CHANNEL_2_IN_HI:
|
case SI_CHANNEL_2_IN_HI:
|
||||||
g_StatusReg.RDST2 = 0;
|
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
_uReturnValue = g_Channel[2].m_InHi.Hex;
|
_uReturnValue = g_Channel[2].m_InHi.Hex;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case SI_CHANNEL_2_IN_LO:
|
case SI_CHANNEL_2_IN_LO:
|
||||||
g_StatusReg.RDST2 = 0;
|
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
_uReturnValue = g_Channel[2].m_InLo.Hex;
|
_uReturnValue = g_Channel[2].m_InLo.Hex;
|
||||||
return;
|
return;
|
||||||
@ -343,13 +341,11 @@ void Read32(u32& _uReturnValue, const u32 _iAddress)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case SI_CHANNEL_3_IN_HI:
|
case SI_CHANNEL_3_IN_HI:
|
||||||
g_StatusReg.RDST3 = 0;
|
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
_uReturnValue = g_Channel[3].m_InHi.Hex;
|
_uReturnValue = g_Channel[3].m_InHi.Hex;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case SI_CHANNEL_3_IN_LO:
|
case SI_CHANNEL_3_IN_LO:
|
||||||
g_StatusReg.RDST3 = 0;
|
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
_uReturnValue = g_Channel[3].m_InLo.Hex;
|
_uReturnValue = g_Channel[3].m_InLo.Hex;
|
||||||
return;
|
return;
|
||||||
@ -402,7 +398,7 @@ void Write32(const u32 _iValue, const u32 _iAddress)
|
|||||||
case SI_CHANNEL_3_IN_LO: g_Channel[3].m_InLo.Hex = _iValue; break;
|
case SI_CHANNEL_3_IN_LO: g_Channel[3].m_InLo.Hex = _iValue; break;
|
||||||
|
|
||||||
case SI_POLL:
|
case SI_POLL:
|
||||||
INFO_LOG(SERIALINTERFACE, "Poll: X=%03d Y=%03d %s%s%s%s%s%s%s%s",
|
INFO_LOG(SERIALINTERFACE, "Wrote Poll: X=%03d Y=%03d %s%s%s%s%s%s%s%s",
|
||||||
g_Poll.X, g_Poll.Y,
|
g_Poll.X, g_Poll.Y,
|
||||||
g_Poll.EN0 ? "EN0 ":" ", g_Poll.EN1 ? "EN1 ":" ",
|
g_Poll.EN0 ? "EN0 ":" ", g_Poll.EN1 ? "EN1 ":" ",
|
||||||
g_Poll.EN2 ? "EN2 ":" ", g_Poll.EN3 ? "EN3 ":" ",
|
g_Poll.EN2 ? "EN2 ":" ", g_Poll.EN3 ? "EN3 ":" ",
|
||||||
@ -478,12 +474,12 @@ void Write32(const u32 _iValue, const u32 _iAddress)
|
|||||||
g_EXIClockCount.Hex = _iValue;
|
g_EXIClockCount.Hex = _iValue;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x80:
|
case 0x80: // Bogus? never seen it with ma own eyes
|
||||||
INFO_LOG(SERIALINTERFACE, "WII something at 0xCD006480");
|
INFO_LOG(SERIALINTERFACE, "WII something at 0xCD006480");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_dbg_assert_(SERIALINTERFACE,0);
|
_dbg_assert_(SERIALINTERFACE, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -522,11 +518,8 @@ void GenerateSIInterrupt(SIInterruptType _SIInterrupt)
|
|||||||
|
|
||||||
void RemoveDevice(int _iDeviceNumber)
|
void RemoveDevice(int _iDeviceNumber)
|
||||||
{
|
{
|
||||||
if (g_Channel[_iDeviceNumber].m_pDevice != NULL)
|
delete g_Channel[_iDeviceNumber].m_pDevice;
|
||||||
{
|
g_Channel[_iDeviceNumber].m_pDevice = NULL;
|
||||||
delete g_Channel[_iDeviceNumber].m_pDevice;
|
|
||||||
g_Channel[_iDeviceNumber].m_pDevice = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddDevice(const TSIDevices _device, int _iDeviceNumber)
|
void AddDevice(const TSIDevices _device, int _iDeviceNumber)
|
||||||
@ -538,54 +531,50 @@ void AddDevice(const TSIDevices _device, int _iDeviceNumber)
|
|||||||
|
|
||||||
// create the new one
|
// create the new one
|
||||||
g_Channel[_iDeviceNumber].m_pDevice = SIDevice_Create(_device, _iDeviceNumber);
|
g_Channel[_iDeviceNumber].m_pDevice = SIDevice_Create(_device, _iDeviceNumber);
|
||||||
_dbg_assert_(SERIALINTERFACE, g_Channel[_iDeviceNumber].m_pDevice != NULL);
|
}
|
||||||
|
|
||||||
|
void SetNoResponse(u32 channel)
|
||||||
|
{
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
g_ComCSR.COMERR = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChangeDeviceCallback(u64 userdata, int cyclesLate)
|
void ChangeDeviceCallback(u64 userdata, int cyclesLate)
|
||||||
{
|
{
|
||||||
u8 channel = (u8)(userdata >> 32);
|
u8 channel = (u8)(userdata >> 32);
|
||||||
// doubt this matters...
|
|
||||||
g_Channel[channel].m_Out.Hex = 0;
|
g_Channel[channel].m_Out.Hex = 0;
|
||||||
g_Channel[channel].m_InHi.Hex = 0;
|
g_Channel[channel].m_InHi.Hex = 0;
|
||||||
g_Channel[channel].m_InLo.Hex = 0;
|
g_Channel[channel].m_InLo.Hex = 0;
|
||||||
|
|
||||||
// raise the NO RESPONSE error
|
SetNoResponse(channel);
|
||||||
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);
|
AddDevice((TSIDevices)(u32)userdata, channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChangeDevice(TSIDevices device, int deviceNumber)
|
void ChangeDevice(TSIDevices device, int channel)
|
||||||
{
|
{
|
||||||
// Called from GUI, so we need to make it thread safe.
|
// Called from GUI, so we need to make it thread safe.
|
||||||
// Let the hardware see no device for .5b cycles
|
// Let the hardware see no device for .5b cycles
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(0, changeDevice, (SI_DUMMY | (u64)deviceNumber << 32));
|
CoreTiming::ScheduleEvent_Threadsafe(0, changeDevice, ((u64)channel << 32) | SI_NONE);
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(500000000, changeDevice, (device | (u64)deviceNumber << 32));
|
CoreTiming::ScheduleEvent_Threadsafe(500000000, changeDevice, ((u64)channel << 32) | device);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateDevices()
|
void UpdateDevices()
|
||||||
{
|
{
|
||||||
// Update channels
|
// Update channels and set the status bit if there's new data
|
||||||
g_StatusReg.RDST0 = g_Channel[0].m_pDevice->GetData(g_Channel[0].m_InHi.Hex, g_Channel[0].m_InLo.Hex) ? 1 : 0;
|
g_StatusReg.RDST0 = !!g_Channel[0].m_pDevice->GetData(g_Channel[0].m_InHi.Hex, g_Channel[0].m_InLo.Hex);
|
||||||
g_StatusReg.RDST1 = g_Channel[1].m_pDevice->GetData(g_Channel[1].m_InHi.Hex, g_Channel[1].m_InLo.Hex) ? 1 : 0;
|
g_StatusReg.RDST1 = !!g_Channel[1].m_pDevice->GetData(g_Channel[1].m_InHi.Hex, g_Channel[1].m_InLo.Hex);
|
||||||
g_StatusReg.RDST2 = g_Channel[2].m_pDevice->GetData(g_Channel[2].m_InHi.Hex, g_Channel[2].m_InLo.Hex) ? 1 : 0;
|
g_StatusReg.RDST2 = !!g_Channel[2].m_pDevice->GetData(g_Channel[2].m_InHi.Hex, g_Channel[2].m_InLo.Hex);
|
||||||
g_StatusReg.RDST3 = g_Channel[3].m_pDevice->GetData(g_Channel[3].m_InHi.Hex, g_Channel[3].m_InLo.Hex) ? 1 : 0;
|
g_StatusReg.RDST3 = !!g_Channel[3].m_pDevice->GetData(g_Channel[3].m_InHi.Hex, g_Channel[3].m_InLo.Hex);
|
||||||
|
|
||||||
// Update interrupts
|
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ 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 ChangeDeviceCallback(u64 userdata, int cyclesLate);
|
||||||
void ChangeDevice(TSIDevices device, int deviceNumber);
|
void ChangeDevice(TSIDevices device, int channel);
|
||||||
|
|
||||||
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);
|
||||||
|
@ -48,30 +48,22 @@ int ISIDevice::RunBuffer(u8* _pBuffer, int _iLength)
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// --- class CSIDummy ---
|
// Stub class for saying nothing is attached, and not having to deal with null pointers :)
|
||||||
// Just a dummy that logs reads and writes
|
class CSIDevice_Null : public ISIDevice
|
||||||
// to be used for SI devices we haven't emulated
|
|
||||||
// DOES NOT FUNCTION AS "NO DEVICE INSERTED" -> Appears as unknown device
|
|
||||||
class CSIDevice_Dummy : public ISIDevice
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CSIDevice_Dummy(int _iDeviceNumber) :
|
CSIDevice_Null(int _iDeviceNumber) : ISIDevice(_iDeviceNumber) {}
|
||||||
ISIDevice(_iDeviceNumber)
|
virtual ~CSIDevice_Null() {}
|
||||||
{}
|
|
||||||
|
|
||||||
virtual ~CSIDevice_Dummy(){}
|
int RunBuffer(u8* _pBuffer, int _iLength) {
|
||||||
|
reinterpret_cast<u32*>(_pBuffer)[0] = SI_ERROR_NO_RESPONSE;
|
||||||
int RunBuffer(u8* _pBuffer, int _iLength)
|
|
||||||
{
|
|
||||||
// Debug logging
|
|
||||||
ISIDevice::RunBuffer(_pBuffer, _iLength);
|
|
||||||
|
|
||||||
reinterpret_cast<u32*>(_pBuffer)[0] = 0x00000000;
|
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
bool GetData(u32& _Hi, u32& _Low) {
|
||||||
bool GetData(u32& _Hi, u32& _Low) {DEBUG_LOG(SERIALINTERFACE, "SI DUMMY %i GetData", this->m_iDeviceNumber); return false;}
|
_Hi = 0x80000000;
|
||||||
void SendCommand(u32 _Cmd, u8 _Poll){DEBUG_LOG(SERIALINTERFACE, "SI DUMMY %i SendCommand: %08x", this->m_iDeviceNumber, _Cmd);}
|
return true;
|
||||||
|
}
|
||||||
|
void SendCommand(u32 _Cmd, u8 _Poll) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -80,10 +72,6 @@ ISIDevice* SIDevice_Create(TSIDevices _SIDevice, int _iDeviceNumber)
|
|||||||
{
|
{
|
||||||
switch(_SIDevice)
|
switch(_SIDevice)
|
||||||
{
|
{
|
||||||
case SI_DUMMY:
|
|
||||||
return new CSIDevice_Dummy(_iDeviceNumber);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SI_GC_CONTROLLER:
|
case SI_GC_CONTROLLER:
|
||||||
return new CSIDevice_GCController(_iDeviceNumber);
|
return new CSIDevice_GCController(_iDeviceNumber);
|
||||||
break;
|
break;
|
||||||
@ -96,10 +84,9 @@ ISIDevice* SIDevice_Create(TSIDevices _SIDevice, int _iDeviceNumber)
|
|||||||
return new CSIDevice_AMBaseboard(_iDeviceNumber);
|
return new CSIDevice_AMBaseboard(_iDeviceNumber);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SI_NONE:
|
||||||
default:
|
default:
|
||||||
return new CSIDevice_Dummy(_iDeviceNumber);
|
return new CSIDevice_Null(_iDeviceNumber);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
// Devices can reply with these, but idk if we'll ever use them...
|
// Devices can reply with these
|
||||||
#define SI_ERROR_NO_RESPONSE 0x0008 // Nothing is attached
|
#define SI_ERROR_NO_RESPONSE 0x0008 // Nothing is attached
|
||||||
#define SI_ERROR_UNKNOWN 0x0040 // Unknown device is attached
|
#define SI_ERROR_UNKNOWN 0x0040 // Unknown device is attached
|
||||||
#define SI_ERROR_BUSY 0x0080 // Still detecting
|
#define SI_ERROR_BUSY 0x0080 // Still detecting
|
||||||
@ -60,7 +60,7 @@ public:
|
|||||||
// SI Device IDs
|
// SI Device IDs
|
||||||
enum TSIDevices
|
enum TSIDevices
|
||||||
{
|
{
|
||||||
SI_DUMMY = 0,
|
SI_NONE = SI_ERROR_NO_RESPONSE,
|
||||||
SI_N64_MIC = 0x00010000,
|
SI_N64_MIC = 0x00010000,
|
||||||
SI_N64_KEYBOARD = 0x00020000,
|
SI_N64_KEYBOARD = 0x00020000,
|
||||||
SI_N64_MOUSE = 0x02000000,
|
SI_N64_MOUSE = 0x02000000,
|
||||||
|
@ -214,6 +214,7 @@ bool CSIDevice_GCController::GetData(u32& _Hi, u32& _Low)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Keep track of the special button combos (embedded in controller hardware... :( )
|
// Keep track of the special button combos (embedded in controller hardware... :( )
|
||||||
|
// Should technically be in "gc time", but we just use host system time :)
|
||||||
EButtonCombo tempCombo;
|
EButtonCombo tempCombo;
|
||||||
if ((PadStatus.button & 0xff00) == (PAD_BUTTON_Y|PAD_BUTTON_X|PAD_BUTTON_START))
|
if ((PadStatus.button & 0xff00) == (PAD_BUTTON_Y|PAD_BUTTON_X|PAD_BUTTON_START))
|
||||||
tempCombo = COMBO_ORIGIN;
|
tempCombo = COMBO_ORIGIN;
|
||||||
|
@ -411,7 +411,7 @@ void CConfigMain::CreateGUIControls()
|
|||||||
GCSIDeviceText[1] = new wxStaticText(GamecubePage, ID_GC_SIDEVICE_TEXT, wxT("Port 2"), wxDefaultPosition, wxDefaultSize);
|
GCSIDeviceText[1] = new wxStaticText(GamecubePage, ID_GC_SIDEVICE_TEXT, wxT("Port 2"), wxDefaultPosition, wxDefaultSize);
|
||||||
GCSIDeviceText[2] = new wxStaticText(GamecubePage, ID_GC_SIDEVICE_TEXT, wxT("Port 3"), wxDefaultPosition, wxDefaultSize);
|
GCSIDeviceText[2] = new wxStaticText(GamecubePage, ID_GC_SIDEVICE_TEXT, wxT("Port 3"), wxDefaultPosition, wxDefaultSize);
|
||||||
GCSIDeviceText[3] = new wxStaticText(GamecubePage, ID_GC_SIDEVICE_TEXT, wxT("Port 4"), wxDefaultPosition, wxDefaultSize);
|
GCSIDeviceText[3] = new wxStaticText(GamecubePage, ID_GC_SIDEVICE_TEXT, wxT("Port 4"), wxDefaultPosition, wxDefaultSize);
|
||||||
const wxString SIDevices[] = {wxT(DEV_DUMMY_STR),wxT(SIDEV_STDCONT_STR),wxT(SIDEV_GBA_STR),wxT(SIDEV_AM_BB_STR)};
|
const wxString SIDevices[] = {wxT(DEV_NONE_STR),wxT(SIDEV_STDCONT_STR),wxT(SIDEV_GBA_STR),wxT(SIDEV_AM_BB_STR)};
|
||||||
static const int numSIDevices = sizeof(SIDevices)/sizeof(wxString);
|
static const int numSIDevices = sizeof(SIDevices)/sizeof(wxString);
|
||||||
GCSIDevice[0] = new wxChoice(GamecubePage, ID_GC_SIDEVICE0, wxDefaultPosition, wxDefaultSize, numSIDevices, SIDevices, 0, wxDefaultValidator);
|
GCSIDevice[0] = new wxChoice(GamecubePage, ID_GC_SIDEVICE0, wxDefaultPosition, wxDefaultSize, numSIDevices, SIDevices, 0, wxDefaultValidator);
|
||||||
GCSIDevice[1] = new wxChoice(GamecubePage, ID_GC_SIDEVICE1, wxDefaultPosition, wxDefaultSize, numSIDevices, SIDevices, 0, wxDefaultValidator);
|
GCSIDevice[1] = new wxChoice(GamecubePage, ID_GC_SIDEVICE1, wxDefaultPosition, wxDefaultSize, numSIDevices, SIDevices, 0, wxDefaultValidator);
|
||||||
@ -793,7 +793,7 @@ void CConfigMain::ChooseSIDevice(std::string deviceName, int deviceNum)
|
|||||||
else if (!deviceName.compare(SIDEV_AM_BB_STR))
|
else if (!deviceName.compare(SIDEV_AM_BB_STR))
|
||||||
tempType = SI_AM_BASEBOARD;
|
tempType = SI_AM_BASEBOARD;
|
||||||
else
|
else
|
||||||
tempType = SI_DUMMY;
|
tempType = SI_NONE;
|
||||||
|
|
||||||
SConfig::GetInstance().m_SIDevice[deviceNum] = tempType;
|
SConfig::GetInstance().m_SIDevice[deviceNum] = tempType;
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ bool NetPlay::GetNetPads(u8 padnb, SPADStatus PadStatus, u32 *netValues)
|
|||||||
|
|
||||||
// Better disable unused ports
|
// Better disable unused ports
|
||||||
for (int i = m_numClients+1; i < 4; i++)
|
for (int i = m_numClients+1; i < 4; i++)
|
||||||
SerialInterface::ChangeDevice(SI_DUMMY, i);
|
SerialInterface::ChangeDevice(SI_NONE, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_timer.GetTimeDifference() > 1000)
|
if (m_timer.GetTimeDifference() > 1000)
|
||||||
|
@ -7,7 +7,7 @@ ifeq ($(strip $(DEVKITPPC)),)
|
|||||||
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
|
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
include $(DEVKITPPC)/gamecube_rules
|
include $(DEVKITPPC)/wii_rules
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# TARGET is the name of the output
|
# TARGET is the name of the output
|
||||||
@ -33,7 +33,7 @@ LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# any extra libraries we wish to link with the project
|
# any extra libraries we wish to link with the project
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
LIBS := -logc -lm
|
LIBS := -lfat -logc -lm
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# list of directories containing libraries, this must be the top level containing
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
@ -7,28 +7,106 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <fat.h>
|
||||||
|
|
||||||
|
#ifdef HW_RVL
|
||||||
|
#include <wiiuse/wpad.h>
|
||||||
|
#include <sdcard/wiisd_io.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static void *xfb;
|
static void *xfb;
|
||||||
static GXRModeObj *rmode;
|
static GXRModeObj *rmode;
|
||||||
|
|
||||||
void Initialise();
|
void Initialise();
|
||||||
|
void (*reboot)() = (void(*)())0x80001800;
|
||||||
|
static u32* const SI_REG = (u32*)0xCD006400;
|
||||||
|
static bool haveInit = false;
|
||||||
|
static int counter = 0;
|
||||||
|
static bool logWritten = false;
|
||||||
|
|
||||||
|
void AppendSDLog()
|
||||||
|
{
|
||||||
|
#ifdef HW_RVL
|
||||||
|
FILE *f = fopen("sd:/si_log.txt", "a");
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
fprintf(f, "\n-------------------------------------\n");
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
fprintf(f, "%i\tstatus: %x\t type:%x\n", i, SI_GetStatus(i), SI_GetType(i));
|
||||||
|
u32 x = 0;
|
||||||
|
fprintf(f, "-------------------------------------\n");
|
||||||
|
fprintf(f, "SI_CHANNEL_0_OUT\t%08x\n", SI_REG[x++]);
|
||||||
|
fprintf(f, "SI_CHANNEL_0_IN_HI\t%08x\n", SI_REG[x++]);
|
||||||
|
fprintf(f, "SI_CHANNEL_0_IN_LO\t%08x\n", SI_REG[x++]);
|
||||||
|
fprintf(f, "SI_CHANNEL_1_OUT\t%08x\n", SI_REG[x++]);
|
||||||
|
fprintf(f, "SI_CHANNEL_1_IN_HI\t%08x\n", SI_REG[x++]);
|
||||||
|
fprintf(f, "SI_CHANNEL_1_IN_LO\t%08x\n", SI_REG[x++]);
|
||||||
|
fprintf(f, "SI_CHANNEL_2_OUT\t%08x\n", SI_REG[x++]);
|
||||||
|
fprintf(f, "SI_CHANNEL_2_IN_HI\t%08x\n", SI_REG[x++]);
|
||||||
|
fprintf(f, "SI_CHANNEL_2_IN_LO\t%08x\n", SI_REG[x++]);
|
||||||
|
fprintf(f, "SI_CHANNEL_3_OUT\t%08x\n", SI_REG[x++]);
|
||||||
|
fprintf(f, "SI_CHANNEL_3_IN_HI\t%08x\n", SI_REG[x++]);
|
||||||
|
fprintf(f, "SI_CHANNEL_3_IN_LO\t%08x\n", SI_REG[x++]);
|
||||||
|
fprintf(f, "SI_POLL\t\t\t%08x\n", SI_REG[x++]);
|
||||||
|
fprintf(f, "SI_COM_CSR\t\t\t%08x\n", SI_REG[x++]);
|
||||||
|
fprintf(f, "SI_STATUS_REG\t\t%08x\n", SI_REG[x++]);
|
||||||
|
fprintf(f, "SI_EXI_CLOCK_COUNT\t%08x\n", SI_REG[x++]);
|
||||||
|
fprintf(f, "-------------------------------------\n");
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
Initialise();
|
Initialise();
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
PAD_ScanPads();
|
if (haveInit) PAD_ScanPads();
|
||||||
VIDEO_ClearFrameBuffer(rmode, xfb, 0);
|
|
||||||
std::cout<<"\x1b[0;0H"; // Position the cursor (at 0, 0)
|
VIDEO_ClearFrameBuffer(rmode, xfb, COLOR_BLACK);
|
||||||
|
|
||||||
|
printf("\x1b[4;0H");
|
||||||
|
|
||||||
for(int Chan = 0; Chan < 4; Chan++)
|
for(int Chan = 0; Chan < 4; Chan++)
|
||||||
|
printf("%i\tstatus: %x\t type:%x\n", Chan, SI_GetStatus(Chan), SI_GetType(Chan));
|
||||||
|
|
||||||
|
printf("SI Regs: (cc006000)\n");
|
||||||
|
for (u32 i = 0; i < 16/*num SI regs*/; ++i)
|
||||||
{
|
{
|
||||||
std::cout << "Chan " << Chan << std::endl;
|
printf("%08x ", SI_REG[i]);
|
||||||
std::cout << "Status is " << SI_GetStatus(Chan) << std::endl;
|
if ((i+1)%8==0) printf("\n");
|
||||||
std::cout << "Type is 0x" << std::setbase(16) << SI_GetType(Chan) << std::setbase(10) << std::endl << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (haveInit)
|
||||||
|
printf("\nPAD_Init\n");
|
||||||
|
|
||||||
VIDEO_WaitVSync();
|
VIDEO_WaitVSync();
|
||||||
|
|
||||||
|
if (haveInit)
|
||||||
|
{
|
||||||
|
if (PAD_ButtonsDown(0) & PAD_BUTTON_START)
|
||||||
|
{
|
||||||
|
AppendSDLog();
|
||||||
|
#ifdef HW_RVL
|
||||||
|
fatUnmount("sd");
|
||||||
|
__io_wiisd.shutdown();
|
||||||
|
#endif
|
||||||
|
reboot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
counter++;
|
||||||
|
AppendSDLog();
|
||||||
|
if (counter > 5 && !haveInit)
|
||||||
|
{
|
||||||
|
PAD_Init();
|
||||||
|
haveInit = true;
|
||||||
|
}
|
||||||
|
else if (haveInit && !logWritten)
|
||||||
|
{
|
||||||
|
logWritten = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -39,9 +117,6 @@ void Initialise()
|
|||||||
// Initialise the video system
|
// Initialise the video system
|
||||||
VIDEO_Init();
|
VIDEO_Init();
|
||||||
|
|
||||||
// This function initialises the attached controllers
|
|
||||||
PAD_Init();
|
|
||||||
|
|
||||||
// Obtain the preferred video mode from the system
|
// Obtain the preferred video mode from the system
|
||||||
// This will correspond to the settings in the Wii menu
|
// This will correspond to the settings in the Wii menu
|
||||||
rmode = VIDEO_GetPreferredMode(NULL);
|
rmode = VIDEO_GetPreferredMode(NULL);
|
||||||
@ -67,4 +142,10 @@ void Initialise()
|
|||||||
// Wait for Video setup to complete
|
// Wait for Video setup to complete
|
||||||
VIDEO_WaitVSync();
|
VIDEO_WaitVSync();
|
||||||
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
|
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
|
||||||
|
|
||||||
|
#ifdef HW_RVL
|
||||||
|
// Initialize FAT so we can write to SD.
|
||||||
|
__io_wiisd.startup();
|
||||||
|
fatMountSimple("sd", &__io_wiisd);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user