diff --git a/Source/Core/Core/Core.vcproj b/Source/Core/Core/Core.vcproj
index d1075b7a21..552b8d27cc 100644
--- a/Source/Core/Core/Core.vcproj
+++ b/Source/Core/Core/Core.vcproj
@@ -607,19 +607,35 @@
Name="SI - Serial Interface"
>
+
+
+
+
+
+
+
+
diff --git a/Source/Core/Core/Src/HW/HW.cpp b/Source/Core/Core/Src/HW/HW.cpp
index 1321e6786f..a59452476b 100644
--- a/Source/Core/Core/Src/HW/HW.cpp
+++ b/Source/Core/Core/Src/HW/HW.cpp
@@ -29,7 +29,7 @@
#include "Memmap.h"
#include "PeripheralInterface.h"
#include "PixelEngine.h"
-#include "SerialInterface.h"
+#include "SI.h"
#include "AudioInterface.h"
#include "VideoInterface.h"
#include "WII_IPC.h"
diff --git a/Source/Core/Core/Src/HW/Memmap.cpp b/Source/Core/Core/Src/HW/Memmap.cpp
index a59fa816e1..5e630e6152 100644
--- a/Source/Core/Core/Src/HW/Memmap.cpp
+++ b/Source/Core/Core/Src/HW/Memmap.cpp
@@ -31,7 +31,7 @@
#include "DVDInterface.h"
#include "GPFifo.h"
#include "VideoInterface.h"
-#include "SerialInterface.h"
+#include "SI.h"
#include "EXI.h"
#include "PixelEngine.h"
#include "CommandProcessor.h"
diff --git a/Source/Core/Core/Src/HW/SerialInterface.cpp b/Source/Core/Core/Src/HW/SI.cpp
similarity index 96%
rename from Source/Core/Core/Src/HW/SerialInterface.cpp
rename to Source/Core/Core/Src/HW/SI.cpp
index 5757f4e0a7..fb1fe3741b 100644
--- a/Source/Core/Core/Src/HW/SerialInterface.cpp
+++ b/Source/Core/Core/Src/HW/SI.cpp
@@ -1,557 +1,553 @@
-// Copyright (C) 2003-2008 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#include
-
-#include "Common.h"
-#include "ChunkFile.h"
-
-#include "SerialInterface.h"
-#include "SerialInterface_Devices.h"
-
-#include "PeripheralInterface.h"
-#include "CPU.h"
-
-#include "../PowerPC/PowerPC.h"
-#include "../Plugins/Plugin_PAD.h"
-
-namespace SerialInterface
-{
-
-// SI Interrupt Types
-enum SIInterruptType
-{
- INT_RDSTINT = 0,
- INT_TCINT = 1,
-};
-
-// SI number of channels
-enum
-{
- NUMBER_OF_CHANNELS = 0x04
-};
-
-// SI Internal Hardware Addresses
-enum
-{
- SI_CHANNEL_0_OUT = 0x00,
- SI_CHANNEL_0_IN_HI = 0x04,
- SI_CHANNEL_0_IN_LO = 0x08,
- SI_CHANNEL_1_OUT = 0x0C,
- SI_CHANNEL_1_IN_HI = 0x10,
- SI_CHANNEL_1_IN_LO = 0x14,
- SI_CHANNEL_2_OUT = 0x18,
- SI_CHANNEL_2_IN_HI = 0x1C,
- SI_CHANNEL_2_IN_LO = 0x20,
- SI_CHANNEL_3_OUT = 0x24,
- SI_CHANNEL_3_IN_HI = 0x28,
- SI_CHANNEL_3_IN_LO = 0x2C,
- SI_POLL = 0x30,
- SI_COM_CSR = 0x34,
- SI_STATUS_REG = 0x38,
- SI_EXI_CLOCK_COUNT = 0x3C,
-};
-
-// SI Channel Output
-union USIChannelOut
-{
- u32 Hex;
- struct
- {
- unsigned OUTPUT1 : 8;
- unsigned OUTPUT0 : 8;
- unsigned CMD : 8;
- unsigned : 8;
- };
-};
-
-// SI Channel Input High u32
-union USIChannelIn_Hi
-{
- u32 Hex;
- struct
- {
- unsigned INPUT3 : 8;
- unsigned INPUT2 : 8;
- unsigned INPUT1 : 8;
- unsigned INPUT0 : 6;
- unsigned ERRLATCH : 1; // 0: no error 1: Error latched. Check SISR.
- unsigned ERRSTAT : 1; // 0: no error 1: error on last transfer
- };
-};
-
-// SI Channel Input Low u32
-union USIChannelIn_Lo
-{
- u32 Hex;
- struct
- {
- unsigned INPUT7 : 8;
- unsigned INPUT6 : 8;
- unsigned INPUT5 : 8;
- unsigned INPUT4 : 8;
- };
-};
-
-// SI Channel
-struct SSIChannel
-{
- USIChannelOut m_Out;
- USIChannelIn_Hi m_InHi;
- USIChannelIn_Lo m_InLo;
- ISIDevice* m_pDevice;
-};
-
-// SI Poll: Controls how often a device is polled
-union USIPoll
-{
- u32 Hex;
- struct
- {
- unsigned VBCPY3 : 1;
- unsigned VBCPY2 : 1;
- unsigned VBCPY1 : 1;
- unsigned VBCPY0 : 1;
- unsigned EN3 : 1;
- unsigned EN2 : 1;
- unsigned EN1 : 1;
- unsigned EN0 : 1;
- unsigned Y : 10;
- unsigned X : 10;
- unsigned : 6;
- };
-};
-
-// SI Communication Control Status Register
-union USIComCSR
-{
- u32 Hex;
- struct
- {
- unsigned TSTART : 1;
- unsigned CHANNEL : 2; // determines which SI channel will be used the communication interface.
- unsigned : 5;
- unsigned INLNGTH : 7;
- unsigned : 1;
- unsigned OUTLNGTH : 7; // Communication Channel Output Length in bytes
- unsigned : 4;
- unsigned RDSTINTMSK : 1; // Read Status Interrupt Status Mask
- unsigned RDSTINT : 1; // Read Status Interrupt Status
- unsigned COMERR : 1; // Communication Error (set 0)
- unsigned TCINTMSK : 1; // Transfer Complete Interrupt Mask
- unsigned TCINT : 1; // Transfer Complete Interrupt
- };
- USIComCSR() {Hex = 0;}
- USIComCSR(u32 _hex) {Hex = _hex;}
-};
-
-// SI Status Register
-union USIStatusReg
-{
- u32 Hex;
- struct
- {
- unsigned 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
- unsigned COLL3 : 1; // (RWC) write 1: bit cleared read 1 collision error
- unsigned NOREP3 : 1; // (RWC) write 1: bit cleared read 1 response error
- unsigned WRST3 : 1; // (R) 1: buffer channel0 not copied
- unsigned RDST3 : 1; // (R) 1: new Data available
- unsigned : 2; // 7:6
- unsigned 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
- unsigned COLL2 : 1; // (RWC) write 1: bit cleared read 1 collision error
- unsigned NOREP2 : 1; // (RWC) write 1: bit cleared read 1 response error
- unsigned WRST2 : 1; // (R) 1: buffer channel0 not copied
- unsigned RDST2 : 1; // (R) 1: new Data available
- unsigned : 2; // 15:14
- unsigned 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
- unsigned COLL1 : 1; // (RWC) write 1: bit cleared read 1 collision error
- unsigned NOREP1 : 1; // (RWC) write 1: bit cleared read 1 response error
- unsigned WRST1 : 1; // (R) 1: buffer channel0 not copied
- unsigned RDST1 : 1; // (R) 1: new Data available
- unsigned : 2; // 23:22
- unsigned 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
- unsigned COLL0 : 1; // (RWC) write 1: bit cleared read 1 collision error
- unsigned NOREP0 : 1; // (RWC) write 1: bit cleared read 1 response error
- unsigned WRST0 : 1; // (R) 1: buffer channel0 not copied
- unsigned RDST0 : 1; // (R) 1: new Data available
- unsigned : 1;
- unsigned WR : 1; // (RW) write 1 start copy, read 0 copy done
- };
- USIStatusReg() {Hex = 0;}
- USIStatusReg(u32 _hex) {Hex = _hex;}
-};
-
-// SI EXI Clock Count
-union USIEXIClockCount
-{
- u32 Hex;
- struct
- {
- unsigned LOCK : 1;
- unsigned : 30;
- };
-};
-
-// STATE_TO_SAVE
-static SSIChannel g_Channel[NUMBER_OF_CHANNELS];
-static USIPoll g_Poll;
-static USIComCSR g_ComCSR;
-static USIStatusReg g_StatusReg;
-static USIEXIClockCount g_EXIClockCount;
-static u8 g_SIBuffer[128];
-
-void DoState(PointerWrap &p)
-{
- // p.DoArray(g_Channel);
- p.Do(g_Poll);
- p.Do(g_ComCSR);
- p.Do(g_StatusReg);
- p.Do(g_EXIClockCount);
- p.Do(g_SIBuffer);
-}
-
-static void GenerateSIInterrupt(SIInterruptType _SIInterrupt);
-void RunSIBuffer();
-void UpdateInterrupts();
-
-void Init()
-{
- for (int i = 0; i < NUMBER_OF_CHANNELS; i++)
- {
- g_Channel[i].m_Out.Hex = 0;
- g_Channel[i].m_InHi.Hex = 0;
- g_Channel[i].m_InLo.Hex = 0;
- }
-
- unsigned int AttachedPadMask = PluginPAD::PAD_GetAttachedPads ? PluginPAD::PAD_GetAttachedPads() : 1;
- for (int i = 0; i < 4; i++)
- {
- if (AttachedPadMask & (1 << i))
- g_Channel[i].m_pDevice = new CSIDevice_GCController(i);
- else
- g_Channel[i].m_pDevice = new CSIDevice_Dummy(i);
- }
-
- g_Poll.Hex = 0;
- g_ComCSR.Hex = 0;
- g_StatusReg.Hex = 0;
- g_EXIClockCount.Hex = 0;
- memset(g_SIBuffer, 0xce, 128);
-}
-
-void Shutdown()
-{
- for (int i = 0; i < NUMBER_OF_CHANNELS; i++)
- {
- delete g_Channel[i].m_pDevice;
- g_Channel[i].m_pDevice = NULL;
- }
-}
-
-void Read32(u32& _uReturnValue, const u32 _iAddress)
-{
- LOGV(SERIALINTERFACE, 3, "(r32): 0x%08x", _iAddress);
-
- // SIBuffer
- if ((_iAddress >= 0xCC006480 && _iAddress < 0xCC006500) ||
- (_iAddress >= 0xCD006480 && _iAddress < 0xCD006500))
- {
- _uReturnValue = *(u32*)&g_SIBuffer[_iAddress & 0x7F];
- return;
- }
-
- // registers
- switch (_iAddress & 0x3FF)
- {
- //===================================================================================================
- // Channel 0
- //===================================================================================================
- case SI_CHANNEL_0_OUT:
- _uReturnValue = g_Channel[0].m_Out.Hex;
- return;
-
- case SI_CHANNEL_0_IN_HI:
- g_StatusReg.RDST0 = 0;
- UpdateInterrupts();
- _uReturnValue = g_Channel[0].m_InHi.Hex;
- return;
-
- case SI_CHANNEL_0_IN_LO:
- g_StatusReg.RDST0 = 0;
- UpdateInterrupts();
- _uReturnValue = g_Channel[0].m_InLo.Hex;
- return;
-
- //===================================================================================================
- // Channel 1
- //===================================================================================================
- case SI_CHANNEL_1_OUT:
- _uReturnValue = g_Channel[1].m_Out.Hex;
- return;
-
- case SI_CHANNEL_1_IN_HI:
- g_StatusReg.RDST1 = 0;
- UpdateInterrupts();
- _uReturnValue = g_Channel[1].m_InHi.Hex;
- return;
-
- case SI_CHANNEL_1_IN_LO:
- g_StatusReg.RDST1 = 0;
- UpdateInterrupts();
- _uReturnValue = g_Channel[1].m_InLo.Hex;
- return;
-
- //===================================================================================================
- // Channel 2
- //===================================================================================================
- case SI_CHANNEL_2_OUT:
- _uReturnValue = g_Channel[2].m_Out.Hex;
- return;
-
- case SI_CHANNEL_2_IN_HI:
- g_StatusReg.RDST2 = 0;
- UpdateInterrupts();
- _uReturnValue = g_Channel[2].m_InHi.Hex;
- return;
-
- case SI_CHANNEL_2_IN_LO:
- g_StatusReg.RDST2 = 0;
- UpdateInterrupts();
- _uReturnValue = g_Channel[2].m_InLo.Hex;
- return;
-
- //===================================================================================================
- // Channel 3
- //===================================================================================================
- case SI_CHANNEL_3_OUT:
- _uReturnValue = g_Channel[3].m_Out.Hex;
- return;
-
- case SI_CHANNEL_3_IN_HI:
- g_StatusReg.RDST3 = 0;
- UpdateInterrupts();
- _uReturnValue = g_Channel[3].m_InHi.Hex;
- return;
-
- case SI_CHANNEL_3_IN_LO:
- g_StatusReg.RDST3 = 0;
- UpdateInterrupts();
- _uReturnValue = g_Channel[3].m_InLo.Hex;
- return;
-
- case SI_POLL: _uReturnValue = g_Poll.Hex; return;
- case SI_COM_CSR: _uReturnValue = g_ComCSR.Hex; return;
- case SI_STATUS_REG: _uReturnValue = g_StatusReg.Hex; return;
-
- case SI_EXI_CLOCK_COUNT: _uReturnValue = g_EXIClockCount.Hex; return;
-
- default:
- LOG(SERIALINTERFACE, "(r32-unk): 0x%08x", _iAddress);
- _dbg_assert_(SERIALINTERFACE,0);
- break;
- }
-
- // error
- _uReturnValue = 0xdeadbeef;
-}
-
-void Write32(const u32 _iValue, const u32 _iAddress)
-{
- LOGV(SERIALINTERFACE, 3, "(w32): 0x%08x 0x%08x", _iValue,_iAddress);
-
- // SIBuffer
- if ((_iAddress >= 0xCC006480 && _iAddress < 0xCC006500) ||
- (_iAddress >= 0xCD006480 && _iAddress < 0xCD006500))
- {
- *(u32*)&g_SIBuffer[_iAddress & 0x7F] = _iValue;
- return;
- }
-
- // registers
- switch (_iAddress & 0x3FF)
- {
- case SI_CHANNEL_0_OUT: g_Channel[0].m_Out.Hex = _iValue; break;
- case SI_CHANNEL_0_IN_HI: g_Channel[0].m_InHi.Hex = _iValue; break;
- case SI_CHANNEL_0_IN_LO: g_Channel[0].m_InLo.Hex = _iValue; break;
- case SI_CHANNEL_1_OUT: g_Channel[1].m_Out.Hex = _iValue; break;
- case SI_CHANNEL_1_IN_HI: g_Channel[1].m_InHi.Hex = _iValue; break;
- case SI_CHANNEL_1_IN_LO: g_Channel[1].m_InLo.Hex = _iValue; break;
- case SI_CHANNEL_2_OUT: g_Channel[2].m_Out.Hex = _iValue; break;
- case SI_CHANNEL_2_IN_HI: g_Channel[2].m_InHi.Hex = _iValue; break;
- case SI_CHANNEL_2_IN_LO: g_Channel[2].m_InLo.Hex = _iValue; break;
- case SI_CHANNEL_3_OUT: g_Channel[3].m_Out.Hex = _iValue; break;
- case SI_CHANNEL_3_IN_HI: g_Channel[3].m_InHi.Hex = _iValue; break;
- case SI_CHANNEL_3_IN_LO: g_Channel[3].m_InLo.Hex = _iValue; break;
-
- case SI_POLL:
- g_Poll.Hex = _iValue;
- break;
-
- case SI_COM_CSR:
- {
- USIComCSR tmpComCSR(_iValue);
-
- g_ComCSR.CHANNEL = tmpComCSR.CHANNEL;
- g_ComCSR.INLNGTH = tmpComCSR.INLNGTH;
- g_ComCSR.OUTLNGTH = tmpComCSR.OUTLNGTH;
- g_ComCSR.RDSTINTMSK = tmpComCSR.RDSTINTMSK;
- g_ComCSR.TCINTMSK = tmpComCSR.TCINTMSK;
-
- g_ComCSR.COMERR = 0;
-
- if (tmpComCSR.RDSTINT) g_ComCSR.RDSTINT = 0;
- if (tmpComCSR.TCINT) g_ComCSR.TCINT = 0;
-
- // be careful: runsi-buffer after updating the INT flags
- if (tmpComCSR.TSTART) RunSIBuffer();
- UpdateInterrupts();
- }
- break;
-
- case SI_STATUS_REG:
- {
- 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;
-
- 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;
-
- 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;
-
- 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;
-
- // 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.WRST0 = 0;
- g_StatusReg.WRST1 = 0;
- g_StatusReg.WRST2 = 0;
- g_StatusReg.WRST3 = 0;
- }
- }
- break;
-
- case SI_EXI_CLOCK_COUNT:
- g_EXIClockCount.Hex = _iValue;
- break;
-
- case 0x80:
- LOG(SERIALINTERFACE, "WII something at 0xCD006480");
- break;
-
- default:
- _dbg_assert_(SERIALINTERFACE,0);
- break;
- }
-}
-
-void UpdateInterrupts()
-{
- // check if we have to update the RDSTINT flag
- if (g_StatusReg.RDST0 || g_StatusReg.RDST1 ||
- g_StatusReg.RDST2 || g_StatusReg.RDST3)
- g_ComCSR.RDSTINT = 1;
- else
- g_ComCSR.RDSTINT = 0;
-
- // check if we have to generate an interrupt
- if ((g_ComCSR.RDSTINT & g_ComCSR.RDSTINTMSK) ||
- (g_ComCSR.TCINT & g_ComCSR.TCINTMSK))
- {
- CPeripheralInterface::SetInterrupt(CPeripheralInterface::INT_CAUSE_SI, true);
- }
- else
- {
- CPeripheralInterface::SetInterrupt(CPeripheralInterface::INT_CAUSE_SI, false);
- }
-}
-
-void GenerateSIInterrupt(SIInterruptType _SIInterrupt)
-{
- switch(_SIInterrupt)
- {
- case INT_RDSTINT: g_ComCSR.RDSTINT = 1; break;
- case INT_TCINT: g_ComCSR.TCINT = 1; break;
- }
-
- UpdateInterrupts();
-}
-
-void UpdateDevices()
-{
- // update channels
- 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.RDST1 = g_Channel[1].m_pDevice->GetData(g_Channel[1].m_InHi.Hex, g_Channel[1].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) ? 1 : 0;
- g_StatusReg.RDST3 = g_Channel[3].m_pDevice->GetData(g_Channel[3].m_InHi.Hex, g_Channel[3].m_InLo.Hex) ? 1 : 0;
-
- // update interrupts
- UpdateInterrupts();
-}
-
-void RunSIBuffer()
-{
- // math inLength
- int inLength = g_ComCSR.INLNGTH;
- if (inLength == 0)
- inLength = 128;
- else
- inLength++;
-
- // math outLength
- int outLength = g_ComCSR.OUTLNGTH;
- if (outLength == 0)
- outLength = 128;
- else
- outLength++;
-
-#ifdef LOGGING
- int numOutput =
-#endif
- g_Channel[g_ComCSR.CHANNEL].m_pDevice->RunBuffer(g_SIBuffer, inLength);
- LOGV(SERIALINTERFACE, 2, "RunSIBuffer (intLen: %i outLen: %i) (processed: %i)", inLength, outLength, numOutput);
-
- // Transfer completed
- GenerateSIInterrupt(INT_TCINT);
- g_ComCSR.TSTART = 0;
-}
-
-} // end of namespace SerialInterface
-
+// Copyright (C) 2003-2008 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "Common.h"
+#include "ChunkFile.h"
+
+#include "PeripheralInterface.h"
+
+#include "../Plugins/Plugin_PAD.h"
+
+#include "SI.h"
+#include "SI_Device.h"
+#include "SI_DeviceGCController.h"
+
+namespace SerialInterface
+{
+
+// SI Interrupt Types
+enum SIInterruptType
+{
+ INT_RDSTINT = 0,
+ INT_TCINT = 1,
+};
+
+// SI number of channels
+enum
+{
+ NUMBER_OF_CHANNELS = 0x04
+};
+
+// SI Internal Hardware Addresses
+enum
+{
+ SI_CHANNEL_0_OUT = 0x00,
+ SI_CHANNEL_0_IN_HI = 0x04,
+ SI_CHANNEL_0_IN_LO = 0x08,
+ SI_CHANNEL_1_OUT = 0x0C,
+ SI_CHANNEL_1_IN_HI = 0x10,
+ SI_CHANNEL_1_IN_LO = 0x14,
+ SI_CHANNEL_2_OUT = 0x18,
+ SI_CHANNEL_2_IN_HI = 0x1C,
+ SI_CHANNEL_2_IN_LO = 0x20,
+ SI_CHANNEL_3_OUT = 0x24,
+ SI_CHANNEL_3_IN_HI = 0x28,
+ SI_CHANNEL_3_IN_LO = 0x2C,
+ SI_POLL = 0x30,
+ SI_COM_CSR = 0x34,
+ SI_STATUS_REG = 0x38,
+ SI_EXI_CLOCK_COUNT = 0x3C,
+};
+
+// SI Channel Output
+union USIChannelOut
+{
+ u32 Hex;
+ struct
+ {
+ unsigned OUTPUT1 : 8;
+ unsigned OUTPUT0 : 8;
+ unsigned CMD : 8;
+ unsigned : 8;
+ };
+};
+
+// SI Channel Input High u32
+union USIChannelIn_Hi
+{
+ u32 Hex;
+ struct
+ {
+ unsigned INPUT3 : 8;
+ unsigned INPUT2 : 8;
+ unsigned INPUT1 : 8;
+ unsigned INPUT0 : 6;
+ unsigned ERRLATCH : 1; // 0: no error 1: Error latched. Check SISR.
+ unsigned ERRSTAT : 1; // 0: no error 1: error on last transfer
+ };
+};
+
+// SI Channel Input Low u32
+union USIChannelIn_Lo
+{
+ u32 Hex;
+ struct
+ {
+ unsigned INPUT7 : 8;
+ unsigned INPUT6 : 8;
+ unsigned INPUT5 : 8;
+ unsigned INPUT4 : 8;
+ };
+};
+
+// SI Channel
+struct SSIChannel
+{
+ USIChannelOut m_Out;
+ USIChannelIn_Hi m_InHi;
+ USIChannelIn_Lo m_InLo;
+ ISIDevice* m_pDevice;
+};
+
+// SI Poll: Controls how often a device is polled
+union USIPoll
+{
+ u32 Hex;
+ struct
+ {
+ unsigned VBCPY3 : 1;
+ unsigned VBCPY2 : 1;
+ unsigned VBCPY1 : 1;
+ unsigned VBCPY0 : 1;
+ unsigned EN3 : 1;
+ unsigned EN2 : 1;
+ unsigned EN1 : 1;
+ unsigned EN0 : 1;
+ unsigned Y : 10;
+ unsigned X : 10;
+ unsigned : 6;
+ };
+};
+
+// SI Communication Control Status Register
+union USIComCSR
+{
+ u32 Hex;
+ struct
+ {
+ unsigned TSTART : 1;
+ unsigned CHANNEL : 2; // determines which SI channel will be used the communication interface.
+ unsigned : 5;
+ unsigned INLNGTH : 7;
+ unsigned : 1;
+ unsigned OUTLNGTH : 7; // Communication Channel Output Length in bytes
+ unsigned : 4;
+ unsigned RDSTINTMSK : 1; // Read Status Interrupt Status Mask
+ unsigned RDSTINT : 1; // Read Status Interrupt Status
+ unsigned COMERR : 1; // Communication Error (set 0)
+ unsigned TCINTMSK : 1; // Transfer Complete Interrupt Mask
+ unsigned TCINT : 1; // Transfer Complete Interrupt
+ };
+ USIComCSR() {Hex = 0;}
+ USIComCSR(u32 _hex) {Hex = _hex;}
+};
+
+// SI Status Register
+union USIStatusReg
+{
+ u32 Hex;
+ struct
+ {
+ unsigned 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
+ unsigned COLL3 : 1; // (RWC) write 1: bit cleared read 1 collision error
+ unsigned NOREP3 : 1; // (RWC) write 1: bit cleared read 1 response error
+ unsigned WRST3 : 1; // (R) 1: buffer channel0 not copied
+ unsigned RDST3 : 1; // (R) 1: new Data available
+ unsigned : 2; // 7:6
+ unsigned 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
+ unsigned COLL2 : 1; // (RWC) write 1: bit cleared read 1 collision error
+ unsigned NOREP2 : 1; // (RWC) write 1: bit cleared read 1 response error
+ unsigned WRST2 : 1; // (R) 1: buffer channel0 not copied
+ unsigned RDST2 : 1; // (R) 1: new Data available
+ unsigned : 2; // 15:14
+ unsigned 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
+ unsigned COLL1 : 1; // (RWC) write 1: bit cleared read 1 collision error
+ unsigned NOREP1 : 1; // (RWC) write 1: bit cleared read 1 response error
+ unsigned WRST1 : 1; // (R) 1: buffer channel0 not copied
+ unsigned RDST1 : 1; // (R) 1: new Data available
+ unsigned : 2; // 23:22
+ unsigned 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
+ unsigned COLL0 : 1; // (RWC) write 1: bit cleared read 1 collision error
+ unsigned NOREP0 : 1; // (RWC) write 1: bit cleared read 1 response error
+ unsigned WRST0 : 1; // (R) 1: buffer channel0 not copied
+ unsigned RDST0 : 1; // (R) 1: new Data available
+ unsigned : 1;
+ unsigned WR : 1; // (RW) write 1 start copy, read 0 copy done
+ };
+ USIStatusReg() {Hex = 0;}
+ USIStatusReg(u32 _hex) {Hex = _hex;}
+};
+
+// SI EXI Clock Count
+union USIEXIClockCount
+{
+ u32 Hex;
+ struct
+ {
+ unsigned LOCK : 1;
+ unsigned : 30;
+ };
+};
+
+// STATE_TO_SAVE
+static SSIChannel g_Channel[NUMBER_OF_CHANNELS];
+static USIPoll g_Poll;
+static USIComCSR g_ComCSR;
+static USIStatusReg g_StatusReg;
+static USIEXIClockCount g_EXIClockCount;
+static u8 g_SIBuffer[128];
+
+void DoState(PointerWrap &p)
+{
+ // p.DoArray(g_Channel);
+ p.Do(g_Poll);
+ p.Do(g_ComCSR);
+ p.Do(g_StatusReg);
+ p.Do(g_EXIClockCount);
+ p.Do(g_SIBuffer);
+}
+
+static void GenerateSIInterrupt(SIInterruptType _SIInterrupt);
+void RunSIBuffer();
+void UpdateInterrupts();
+
+void Init()
+{
+ for (int i = 0; i < NUMBER_OF_CHANNELS; i++)
+ {
+ g_Channel[i].m_Out.Hex = 0;
+ g_Channel[i].m_InHi.Hex = 0;
+ g_Channel[i].m_InLo.Hex = 0;
+ }
+
+ unsigned int AttachedPadMask = PluginPAD::PAD_GetAttachedPads ? PluginPAD::PAD_GetAttachedPads() : 1;
+ for (int i = 0; i < 4; i++)
+ {
+ if (AttachedPadMask & (1 << i))
+ g_Channel[i].m_pDevice = new CSIDevice_GCController(i);
+ else
+ g_Channel[i].m_pDevice = new CSIDevice_Dummy(i);
+ }
+
+ g_Poll.Hex = 0;
+ g_ComCSR.Hex = 0;
+ g_StatusReg.Hex = 0;
+ g_EXIClockCount.Hex = 0;
+ memset(g_SIBuffer, 0xce, 128);
+}
+
+void Shutdown()
+{
+ for (int i = 0; i < NUMBER_OF_CHANNELS; i++)
+ {
+ delete g_Channel[i].m_pDevice;
+ g_Channel[i].m_pDevice = NULL;
+ }
+}
+
+void Read32(u32& _uReturnValue, const u32 _iAddress)
+{
+ LOGV(SERIALINTERFACE, 3, "(r32): 0x%08x", _iAddress);
+
+ // SIBuffer
+ if ((_iAddress >= 0xCC006480 && _iAddress < 0xCC006500) ||
+ (_iAddress >= 0xCD006480 && _iAddress < 0xCD006500))
+ {
+ _uReturnValue = *(u32*)&g_SIBuffer[_iAddress & 0x7F];
+ return;
+ }
+
+ // registers
+ switch (_iAddress & 0x3FF)
+ {
+ //===================================================================================================
+ // Channel 0
+ //===================================================================================================
+ case SI_CHANNEL_0_OUT:
+ _uReturnValue = g_Channel[0].m_Out.Hex;
+ return;
+
+ case SI_CHANNEL_0_IN_HI:
+ g_StatusReg.RDST0 = 0;
+ UpdateInterrupts();
+ _uReturnValue = g_Channel[0].m_InHi.Hex;
+ return;
+
+ case SI_CHANNEL_0_IN_LO:
+ g_StatusReg.RDST0 = 0;
+ UpdateInterrupts();
+ _uReturnValue = g_Channel[0].m_InLo.Hex;
+ return;
+
+ //===================================================================================================
+ // Channel 1
+ //===================================================================================================
+ case SI_CHANNEL_1_OUT:
+ _uReturnValue = g_Channel[1].m_Out.Hex;
+ return;
+
+ case SI_CHANNEL_1_IN_HI:
+ g_StatusReg.RDST1 = 0;
+ UpdateInterrupts();
+ _uReturnValue = g_Channel[1].m_InHi.Hex;
+ return;
+
+ case SI_CHANNEL_1_IN_LO:
+ g_StatusReg.RDST1 = 0;
+ UpdateInterrupts();
+ _uReturnValue = g_Channel[1].m_InLo.Hex;
+ return;
+
+ //===================================================================================================
+ // Channel 2
+ //===================================================================================================
+ case SI_CHANNEL_2_OUT:
+ _uReturnValue = g_Channel[2].m_Out.Hex;
+ return;
+
+ case SI_CHANNEL_2_IN_HI:
+ g_StatusReg.RDST2 = 0;
+ UpdateInterrupts();
+ _uReturnValue = g_Channel[2].m_InHi.Hex;
+ return;
+
+ case SI_CHANNEL_2_IN_LO:
+ g_StatusReg.RDST2 = 0;
+ UpdateInterrupts();
+ _uReturnValue = g_Channel[2].m_InLo.Hex;
+ return;
+
+ //===================================================================================================
+ // Channel 3
+ //===================================================================================================
+ case SI_CHANNEL_3_OUT:
+ _uReturnValue = g_Channel[3].m_Out.Hex;
+ return;
+
+ case SI_CHANNEL_3_IN_HI:
+ g_StatusReg.RDST3 = 0;
+ UpdateInterrupts();
+ _uReturnValue = g_Channel[3].m_InHi.Hex;
+ return;
+
+ case SI_CHANNEL_3_IN_LO:
+ g_StatusReg.RDST3 = 0;
+ UpdateInterrupts();
+ _uReturnValue = g_Channel[3].m_InLo.Hex;
+ return;
+
+ case SI_POLL: _uReturnValue = g_Poll.Hex; return;
+ case SI_COM_CSR: _uReturnValue = g_ComCSR.Hex; return;
+ case SI_STATUS_REG: _uReturnValue = g_StatusReg.Hex; return;
+
+ case SI_EXI_CLOCK_COUNT: _uReturnValue = g_EXIClockCount.Hex; return;
+
+ default:
+ LOG(SERIALINTERFACE, "(r32-unk): 0x%08x", _iAddress);
+ _dbg_assert_(SERIALINTERFACE,0);
+ break;
+ }
+
+ // error
+ _uReturnValue = 0xdeadbeef;
+}
+
+void Write32(const u32 _iValue, const u32 _iAddress)
+{
+ LOGV(SERIALINTERFACE, 3, "(w32): 0x%08x 0x%08x", _iValue,_iAddress);
+
+ // SIBuffer
+ if ((_iAddress >= 0xCC006480 && _iAddress < 0xCC006500) ||
+ (_iAddress >= 0xCD006480 && _iAddress < 0xCD006500))
+ {
+ *(u32*)&g_SIBuffer[_iAddress & 0x7F] = _iValue;
+ return;
+ }
+
+ // registers
+ switch (_iAddress & 0x3FF)
+ {
+ case SI_CHANNEL_0_OUT: g_Channel[0].m_Out.Hex = _iValue; break;
+ case SI_CHANNEL_0_IN_HI: g_Channel[0].m_InHi.Hex = _iValue; break;
+ case SI_CHANNEL_0_IN_LO: g_Channel[0].m_InLo.Hex = _iValue; break;
+ case SI_CHANNEL_1_OUT: g_Channel[1].m_Out.Hex = _iValue; break;
+ case SI_CHANNEL_1_IN_HI: g_Channel[1].m_InHi.Hex = _iValue; break;
+ case SI_CHANNEL_1_IN_LO: g_Channel[1].m_InLo.Hex = _iValue; break;
+ case SI_CHANNEL_2_OUT: g_Channel[2].m_Out.Hex = _iValue; break;
+ case SI_CHANNEL_2_IN_HI: g_Channel[2].m_InHi.Hex = _iValue; break;
+ case SI_CHANNEL_2_IN_LO: g_Channel[2].m_InLo.Hex = _iValue; break;
+ case SI_CHANNEL_3_OUT: g_Channel[3].m_Out.Hex = _iValue; break;
+ case SI_CHANNEL_3_IN_HI: g_Channel[3].m_InHi.Hex = _iValue; break;
+ case SI_CHANNEL_3_IN_LO: g_Channel[3].m_InLo.Hex = _iValue; break;
+
+ case SI_POLL:
+ g_Poll.Hex = _iValue;
+ break;
+
+ case SI_COM_CSR:
+ {
+ USIComCSR tmpComCSR(_iValue);
+
+ g_ComCSR.CHANNEL = tmpComCSR.CHANNEL;
+ g_ComCSR.INLNGTH = tmpComCSR.INLNGTH;
+ g_ComCSR.OUTLNGTH = tmpComCSR.OUTLNGTH;
+ g_ComCSR.RDSTINTMSK = tmpComCSR.RDSTINTMSK;
+ g_ComCSR.TCINTMSK = tmpComCSR.TCINTMSK;
+
+ g_ComCSR.COMERR = 0;
+
+ if (tmpComCSR.RDSTINT) g_ComCSR.RDSTINT = 0;
+ if (tmpComCSR.TCINT) g_ComCSR.TCINT = 0;
+
+ // be careful: runsi-buffer after updating the INT flags
+ if (tmpComCSR.TSTART) RunSIBuffer();
+ UpdateInterrupts();
+ }
+ break;
+
+ case SI_STATUS_REG:
+ {
+ 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;
+
+ 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;
+
+ 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;
+
+ 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;
+
+ // 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.WRST0 = 0;
+ g_StatusReg.WRST1 = 0;
+ g_StatusReg.WRST2 = 0;
+ g_StatusReg.WRST3 = 0;
+ }
+ }
+ break;
+
+ case SI_EXI_CLOCK_COUNT:
+ g_EXIClockCount.Hex = _iValue;
+ break;
+
+ case 0x80:
+ LOG(SERIALINTERFACE, "WII something at 0xCD006480");
+ break;
+
+ default:
+ _dbg_assert_(SERIALINTERFACE,0);
+ break;
+ }
+}
+
+void UpdateInterrupts()
+{
+ // check if we have to update the RDSTINT flag
+ if (g_StatusReg.RDST0 || g_StatusReg.RDST1 ||
+ g_StatusReg.RDST2 || g_StatusReg.RDST3)
+ g_ComCSR.RDSTINT = 1;
+ else
+ g_ComCSR.RDSTINT = 0;
+
+ // check if we have to generate an interrupt
+ if ((g_ComCSR.RDSTINT & g_ComCSR.RDSTINTMSK) ||
+ (g_ComCSR.TCINT & g_ComCSR.TCINTMSK))
+ {
+ CPeripheralInterface::SetInterrupt(CPeripheralInterface::INT_CAUSE_SI, true);
+ }
+ else
+ {
+ CPeripheralInterface::SetInterrupt(CPeripheralInterface::INT_CAUSE_SI, false);
+ }
+}
+
+void GenerateSIInterrupt(SIInterruptType _SIInterrupt)
+{
+ switch(_SIInterrupt)
+ {
+ case INT_RDSTINT: g_ComCSR.RDSTINT = 1; break;
+ case INT_TCINT: g_ComCSR.TCINT = 1; break;
+ }
+
+ UpdateInterrupts();
+}
+
+void UpdateDevices()
+{
+ // update channels
+ 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.RDST1 = g_Channel[1].m_pDevice->GetData(g_Channel[1].m_InHi.Hex, g_Channel[1].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) ? 1 : 0;
+ g_StatusReg.RDST3 = g_Channel[3].m_pDevice->GetData(g_Channel[3].m_InHi.Hex, g_Channel[3].m_InLo.Hex) ? 1 : 0;
+
+ // update interrupts
+ UpdateInterrupts();
+}
+
+void RunSIBuffer()
+{
+ // math inLength
+ int inLength = g_ComCSR.INLNGTH;
+ if (inLength == 0)
+ inLength = 128;
+ else
+ inLength++;
+
+ // math outLength
+ int outLength = g_ComCSR.OUTLNGTH;
+ if (outLength == 0)
+ outLength = 128;
+ else
+ outLength++;
+
+#ifdef LOGGING
+ int numOutput =
+#endif
+ g_Channel[g_ComCSR.CHANNEL].m_pDevice->RunBuffer(g_SIBuffer, inLength);
+ LOGV(SERIALINTERFACE, 2, "RunSIBuffer (intLen: %i outLen: %i) (processed: %i)", inLength, outLength, numOutput);
+
+ // Transfer completed
+ GenerateSIInterrupt(INT_TCINT);
+ g_ComCSR.TSTART = 0;
+}
+
+} // end of namespace SerialInterface
diff --git a/Source/Core/Core/Src/HW/SerialInterface.h b/Source/Core/Core/Src/HW/SI.h
similarity index 96%
rename from Source/Core/Core/Src/HW/SerialInterface.h
rename to Source/Core/Core/Src/HW/SI.h
index 4bfb59c2ff..36a1967344 100644
--- a/Source/Core/Core/Src/HW/SerialInterface.h
+++ b/Source/Core/Core/Src/HW/SI.h
@@ -1,39 +1,36 @@
-// Copyright (C) 2003-2008 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#ifndef _SERIALINTERFACE_H
-#define _SERIALINTERFACE_H
-
-#include "Common.h"
-class PointerWrap;
-
-namespace SerialInterface
-{
-
-void Init();
-void Shutdown();
-void DoState(PointerWrap &p);
-
-void UpdateDevices();
-
-void HWCALL Read32(u32& _uReturnValue, const u32 _iAddress);
-void HWCALL Write32(const u32 _iValue, const u32 _iAddress);
-
-}; // end of namespace SerialInterface
-
-#endif
-
+// Copyright (C) 2003-2008 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+#ifndef _SERIALINTERFACE_H
+#define _SERIALINTERFACE_H
+
+#include "Common.h"
+class PointerWrap;
+
+namespace SerialInterface
+{
+
+void Init();
+void Shutdown();
+void DoState(PointerWrap &p);
+
+void UpdateDevices();
+
+void HWCALL Read32(u32& _uReturnValue, const u32 _iAddress);
+void HWCALL Write32(const u32 _iValue, const u32 _iAddress);
+
+}; // end of namespace SerialInterface
+#endif
diff --git a/Source/Core/Core/Src/HW/SI_Device.cpp b/Source/Core/Core/Src/HW/SI_Device.cpp
new file mode 100644
index 0000000000..2f05c2729c
--- /dev/null
+++ b/Source/Core/Core/Src/HW/SI_Device.cpp
@@ -0,0 +1,70 @@
+// Copyright (C) 2003-2008 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "SI_Device.h"
+
+// =====================================================================================================
+// --- base class ---
+// =====================================================================================================
+
+int ISIDevice::RunBuffer(u8* _pBuffer, int _iLength)
+{
+#ifdef _DEBUG
+ LOG(SERIALINTERFACE, "Send Data Device(%i) - Length(%i) ", ISIDevice::m_iDeviceNumber,_iLength);
+
+ char szTemp[256] = "";
+ int num = 0;
+ while(num < _iLength)
+ {
+ char szTemp2[128] = "";
+ sprintf(szTemp2, "0x%02x ", _pBuffer[num^3]);
+ strcat(szTemp, szTemp2);
+ num++;
+
+ if ((num % 8) == 0)
+ {
+ LOG(SERIALINTERFACE, szTemp);
+ szTemp[0] = '\0';
+ }
+ }
+ LOG(SERIALINTERFACE, szTemp);
+#endif
+ return 0;
+};
+
+// =====================================================================================================
+// --- dummy device ---
+// =====================================================================================================
+
+CSIDevice_Dummy::CSIDevice_Dummy(int _iDeviceNumber) :
+ ISIDevice(_iDeviceNumber)
+{}
+
+int CSIDevice_Dummy::RunBuffer(u8* _pBuffer, int _iLength)
+{
+ reinterpret_cast(_pBuffer)[0] = 0x00000000; // no device
+ return 4;
+}
+
+bool CSIDevice_Dummy::GetData(u32& _Hi, u32& _Low)
+{
+ return false;
+}
+
+void CSIDevice_Dummy::SendCommand(u32 _Cmd)
+{
+}
diff --git a/Source/Core/Core/Src/HW/SI_Device.h b/Source/Core/Core/Src/HW/SI_Device.h
new file mode 100644
index 0000000000..b38e9df2b4
--- /dev/null
+++ b/Source/Core/Core/Src/HW/SI_Device.h
@@ -0,0 +1,108 @@
+// Copyright (C) 2003-2008 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#ifndef _SIDEVICE_H
+#define _SIDEVICE_H
+
+#include "Common.h"
+
+#define SI_ERROR_NO_RESPONSE 0x0008 // nothing is attached
+#define SI_ERROR_UNKNOWN 0x0040 // unknown device is attached
+#define SI_ERROR_BUSY 0x0080 // still detecting
+
+// Device types
+#define SI_TYPE_MASK 0x18000000u
+#define SI_TYPE_N64 0x00000000u
+#define SI_TYPE_GC 0x08000000u
+
+// GameCube
+#define SI_GC_WIRELESS 0x80000000u
+#define SI_GC_NOMOTOR 0x20000000u // no rumble motor
+#define SI_GC_STANDARD 0x01000000u
+
+// WaveBird
+#define SI_WIRELESS_RECEIVED 0x40000000u // 0: no wireless unit
+#define SI_WIRELESS_IR 0x04000000u // 0: IR 1: RF
+#define SI_WIRELESS_STATE 0x02000000u // 0: variable 1: fixed
+#define SI_WIRELESS_ORIGIN 0x00200000u // 0: invalid 1: valid
+#define SI_WIRELESS_FIX_ID 0x00100000u // 0: not fixed 1: fixed
+#define SI_WIRELESS_TYPE 0x000f0000u
+#define SI_WIRELESS_LITE_MASK 0x000c0000u // 0: normal 1: lite controller
+#define SI_WIRELESS_LITE 0x00040000u // 0: normal 1: lite controller
+#define SI_WIRELESS_CONT_MASK 0x00080000u // 0: non-controller 1: non-controller
+#define SI_WIRELESS_CONT 0x00000000u
+#define SI_WIRELESS_ID 0x00c0ff00u
+#define SI_WIRELESS_TYPE_ID (SI_WIRELESS_TYPE | SI_WIRELESS_ID)
+
+// "Complete" IDs
+#define SI_N64_CONTROLLER (SI_TYPE_N64 | 0x05000000)
+#define SI_N64_MIC (SI_TYPE_N64 | 0x00010000)
+#define SI_N64_KEYBOARD (SI_TYPE_N64 | 0x00020000)
+#define SI_N64_MOUSE (SI_TYPE_N64 | 0x02000000)
+#define SI_GBA (SI_TYPE_N64 | 0x00040000)
+#define SI_GC_CONTROLLER (SI_TYPE_GC | SI_GC_STANDARD)
+#define SI_GC_RECEIVER (SI_TYPE_GC | SI_GC_WIRELESS)
+#define SI_GC_WAVEBIRD (SI_TYPE_GC | SI_GC_WIRELESS | SI_GC_STANDARD | SI_WIRELESS_STATE | SI_WIRELESS_FIX_ID)
+#define SI_GC_KEYBOARD (SI_TYPE_GC | 0x00200000)
+#define SI_GC_STEERING (SI_TYPE_GC | 0x00000000)
+
+
+class ISIDevice
+{
+protected:
+ int m_iDeviceNumber;
+
+public:
+
+ // constructor
+ ISIDevice(int _iDeviceNumber) :
+ m_iDeviceNumber(_iDeviceNumber)
+ { }
+ virtual ~ISIDevice() { }
+
+ // run the SI Buffer
+ virtual int RunBuffer(u8* _pBuffer, int _iLength);
+
+ // return true on new data
+ virtual bool GetData(u32& _Hi, u32& _Low) = 0;
+
+ // send a command directly (no detour per buffer)
+ virtual void SendCommand(u32 _Cmd) = 0;
+};
+
+// =====================================================================================================
+// dummy - no device attached
+// =====================================================================================================
+
+class CSIDevice_Dummy : public ISIDevice
+{
+public:
+
+ // constructor
+ CSIDevice_Dummy(int _iDeviceNumber);
+
+ // run the SI Buffer
+ virtual int RunBuffer(u8* _pBuffer, int _iLength);
+
+ // return true on new data
+ virtual bool GetData(u32& _Hi, u32& _Low);
+
+ // send a command directly
+ virtual void SendCommand(u32 _Cmd);
+};
+
+#endif
diff --git a/Source/Core/Core/Src/HW/SerialInterface_Devices.cpp b/Source/Core/Core/Src/HW/SI_DeviceGCController.cpp
similarity index 70%
rename from Source/Core/Core/Src/HW/SerialInterface_Devices.cpp
rename to Source/Core/Core/Src/HW/SI_DeviceGCController.cpp
index 1719fb83fc..e767fa0c2f 100644
--- a/Source/Core/Core/Src/HW/SerialInterface_Devices.cpp
+++ b/Source/Core/Core/Src/HW/SI_DeviceGCController.cpp
@@ -1,238 +1,171 @@
-// Copyright (C) 2003-2008 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#include
-#include
-
-#include "SerialInterface_Devices.h"
-
-#include "EXI_Device.h"
-#include "EXI_DeviceMic.h"
-
-#include "../Plugins/Plugin_PAD.h"
-
-#include "../PowerPC/PowerPC.h"
-#include "CPU.h"
-
-#define SI_TYPE_GC 0x08000000u
-
-#define SI_GC_STANDARD 0x01000000u // dolphin standard controller
-#define SI_GC_NOMOTOR 0x20000000u // no rumble motor
-
-#define SI_GC_KEYBOARD (SI_TYPE_GC | 0x00200000)
-#define SI_GC_CONTROLLER (SI_TYPE_GC | SI_GC_STANDARD)
-
-#define SI_MAX_COMCSR_INLNGTH 128
-#define SI_MAX_COMCSR_OUTLNGTH 128
-
-// =====================================================================================================
-// --- base class ---
-// =====================================================================================================
-
-int ISIDevice::RunBuffer(u8* _pBuffer, int _iLength)
-{
-#ifdef _DEBUG
- LOG(SERIALINTERFACE, "Send Data Device(%i) - Length(%i) ", ISIDevice::m_iDeviceNumber,_iLength);
-
- char szTemp[256] = "";
- int num = 0;
- while(num < _iLength)
- {
- char szTemp2[128] = "";
- sprintf(szTemp2, "0x%02x ", _pBuffer[num^3]);
- strcat(szTemp, szTemp2);
- num++;
-
- if ((num % 8) == 0)
- {
- LOG(SERIALINTERFACE, szTemp);
- szTemp[0] = '\0';
- }
- }
- LOG(SERIALINTERFACE, szTemp);
-#endif
- return 0;
-};
-
-// =====================================================================================================
-// --- standard gamecube controller ---
-// =====================================================================================================
-
-CSIDevice_GCController::CSIDevice_GCController(int _iDeviceNumber) :
- ISIDevice(_iDeviceNumber)
-{
- memset(&m_origin, 0, sizeof(SOrigin));
-
- m_origin.uCommand = 0x41;
- m_origin.uOriginStickX = 0x80;
- m_origin.uOriginStickY = 0x80;
- m_origin.uSubStickStickX = 0x80;
- m_origin.uSubStickStickY = 0x80;
- m_origin.uTrigger_L = 0x1F;
- m_origin.uTrigger_R = 0x1F;
-}
-
-int CSIDevice_GCController::RunBuffer(u8* _pBuffer, int _iLength)
-{
- // for debug logging only
- ISIDevice::RunBuffer(_pBuffer, _iLength);
-
- int iPosition = 0;
- while(iPosition < _iLength)
- {
- // read the command
- EBufferCommands command = static_cast(_pBuffer[iPosition ^ 3]);
- iPosition++;
-
- // handle it
- switch(command)
- {
- case CMD_RESET:
- {
- *(u32*)&_pBuffer[0] = SI_GC_CONTROLLER; // | SI_GC_NOMOTOR;
- iPosition = _iLength; // break the while loop
- }
- break;
-
- case CMD_ORIGIN:
- {
- LOG(SERIALINTERFACE, "SI - Get Origin");
- u8* pCalibration = reinterpret_cast(&m_origin);
- for (int i = 0; i < (int)sizeof(SOrigin); i++)
- {
- _pBuffer[i ^ 3] = *pCalibration++;
- }
- }
- iPosition = _iLength;
- break;
-
- // Recalibrate (FiRES: i am not 100 percent sure about this)
- case CMD_RECALIBRATE:
- {
- LOG(SERIALINTERFACE, "SI - Recalibrate");
- u8* pCalibration = reinterpret_cast(&m_origin);
- for (int i = 0; i < (int)sizeof(SOrigin); i++)
- {
- _pBuffer[i ^ 3] = *pCalibration++;
- }
- }
- iPosition = _iLength;
- break;
-
- // WII Something
- case 0xCE:
- LOG(SERIALINTERFACE, "Unknown Wii SI Command");
- break;
-
- // DEFAULT
- default:
- {
- LOG(SERIALINTERFACE, "unknown SI command (0x%x)", command);
- PanicAlert("SI: Unknown command");
- iPosition = _iLength;
- }
- break;
- }
- }
-
- return iPosition;
-}
-
-// __________________________________________________________________________________________________
-// GetData
-//
-// return true on new data (max 7 Bytes and 6 bits ;)
-//
-bool
-CSIDevice_GCController::GetData(u32& _Hi, u32& _Low)
-{
- SPADStatus PadStatus;
- memset(&PadStatus, 0 ,sizeof(PadStatus));
- PluginPAD::PAD_GetStatus(ISIDevice::m_iDeviceNumber, &PadStatus);
-
- _Hi = (u32)((u8)PadStatus.stickY);
- _Hi |= (u32)((u8)PadStatus.stickX << 8);
- _Hi |= (u32)((u16)PadStatus.button << 16);
-
- _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);
-
- // 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;
-
- return true;
-}
-
-// __________________________________________________________________________________________________
-// SendCommand
-//
-void
-CSIDevice_GCController::SendCommand(u32 _Cmd)
-{
- UCommand command(_Cmd);
- switch(command.Command)
- {
- // Costis sent it in some demos :)
- case 0x00:
- break;
-
- case CMD_RUMBLE:
- {
- unsigned int uType = command.Parameter1; // 0 = stop, 1 = rumble, 2 = stop hard
- unsigned int uStrength = command.Parameter2;
- if (PluginPAD::PAD_Rumble)
- PluginPAD::PAD_Rumble(ISIDevice::m_iDeviceNumber, uType, uStrength);
- }
- break;
-
- default:
- {
- LOG(SERIALINTERFACE, "unknown direct command (0x%x)", _Cmd);
- PanicAlert("SI: Unknown direct command");
- }
- break;
- }
-}
-
-// =====================================================================================================
-// --- dummy device ---
-// =====================================================================================================
-
-CSIDevice_Dummy::CSIDevice_Dummy(int _iDeviceNumber) :
- ISIDevice(_iDeviceNumber)
-{}
-
-int CSIDevice_Dummy::RunBuffer(u8* _pBuffer, int _iLength)
-{
- reinterpret_cast(_pBuffer)[0] = 0x00000000; // no device
- return 4;
-}
-
-bool CSIDevice_Dummy::GetData(u32& _Hi, u32& _Low)
-{
- return false;
-}
-
-void CSIDevice_Dummy::SendCommand(u32 _Cmd)
-{
-}
-
+// Copyright (C) 2003-2008 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include
+#include
+
+#include "SI_Device.h"
+#include "SI_DeviceGCController.h"
+#include "../Plugins/Plugin_PAD.h"
+
+#include "EXI_Device.h"
+#include "EXI_DeviceMic.h"
+
+// =====================================================================================================
+// --- standard gamecube controller ---
+// =====================================================================================================
+
+CSIDevice_GCController::CSIDevice_GCController(int _iDeviceNumber) :
+ ISIDevice(_iDeviceNumber)
+{
+ memset(&m_origin, 0, sizeof(SOrigin));
+
+ m_origin.uCommand = 0x41;
+ m_origin.uOriginStickX = 0x80;
+ m_origin.uOriginStickY = 0x80;
+ m_origin.uSubStickStickX = 0x80;
+ m_origin.uSubStickStickY = 0x80;
+ m_origin.uTrigger_L = 0x1F;
+ m_origin.uTrigger_R = 0x1F;
+}
+
+int CSIDevice_GCController::RunBuffer(u8* _pBuffer, int _iLength)
+{
+ // for debug logging only
+ ISIDevice::RunBuffer(_pBuffer, _iLength);
+
+ int iPosition = 0;
+ while(iPosition < _iLength)
+ {
+ // read the command
+ EBufferCommands command = static_cast(_pBuffer[iPosition ^ 3]);
+ iPosition++;
+
+ // handle it
+ switch(command)
+ {
+ case CMD_RESET:
+ {
+ *(u32*)&_pBuffer[0] = SI_GC_CONTROLLER; // | SI_GC_NOMOTOR;
+ iPosition = _iLength; // break the while loop
+ }
+ break;
+
+ case CMD_ORIGIN:
+ {
+ LOG(SERIALINTERFACE, "PAD - Get Origin");
+ u8* pCalibration = reinterpret_cast(&m_origin);
+ for (int i = 0; i < (int)sizeof(SOrigin); i++)
+ {
+ _pBuffer[i ^ 3] = *pCalibration++;
+ }
+ }
+ iPosition = _iLength;
+ break;
+
+ // Recalibrate (FiRES: i am not 100 percent sure about this)
+ case CMD_RECALIBRATE:
+ {
+ LOG(SERIALINTERFACE, "PAD - Recalibrate");
+ u8* pCalibration = reinterpret_cast(&m_origin);
+ for (int i = 0; i < (int)sizeof(SOrigin); i++)
+ {
+ _pBuffer[i ^ 3] = *pCalibration++;
+ }
+ }
+ iPosition = _iLength;
+ break;
+
+ // WII Something
+ case 0xCE:
+ LOG(SERIALINTERFACE, "Unknown Wii SI Command");
+ break;
+
+ // DEFAULT
+ default:
+ {
+ LOG(SERIALINTERFACE, "unknown SI command (0x%x)", command);
+ PanicAlert("SI: Unknown command");
+ iPosition = _iLength;
+ }
+ break;
+ }
+ }
+
+ return iPosition;
+}
+
+// __________________________________________________________________________________________________
+// GetData
+//
+// return true on new data (max 7 Bytes and 6 bits ;)
+//
+bool
+CSIDevice_GCController::GetData(u32& _Hi, u32& _Low)
+{
+ SPADStatus PadStatus;
+ memset(&PadStatus, 0 ,sizeof(PadStatus));
+ PluginPAD::PAD_GetStatus(ISIDevice::m_iDeviceNumber, &PadStatus);
+
+ _Hi = (u32)((u8)PadStatus.stickY);
+ _Hi |= (u32)((u8)PadStatus.stickX << 8);
+ _Hi |= (u32)((u16)PadStatus.button << 16);
+
+ _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);
+
+ // 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;
+
+ return true;
+}
+
+// __________________________________________________________________________________________________
+// SendCommand
+//
+void
+CSIDevice_GCController::SendCommand(u32 _Cmd)
+{
+ UCommand command(_Cmd);
+ switch(command.Command)
+ {
+ // Costis sent it in some demos :)
+ case 0x00:
+ break;
+
+ case CMD_RUMBLE:
+ {
+ unsigned int uType = command.Parameter1; // 0 = stop, 1 = rumble, 2 = stop hard
+ unsigned int uStrength = command.Parameter2;
+ if (PluginPAD::PAD_Rumble)
+ PluginPAD::PAD_Rumble(ISIDevice::m_iDeviceNumber, uType, uStrength);
+ }
+ break;
+
+ default:
+ {
+ LOG(SERIALINTERFACE, "unknown direct command (0x%x)", _Cmd);
+ PanicAlert("SI: Unknown direct command");
+ }
+ break;
+ }
+}
diff --git a/Source/Core/Core/Src/HW/SerialInterface_Devices.h b/Source/Core/Core/Src/HW/SI_DeviceGCController.h
similarity index 64%
rename from Source/Core/Core/Src/HW/SerialInterface_Devices.h
rename to Source/Core/Core/Src/HW/SI_DeviceGCController.h
index cae353d456..b7d9029fc5 100644
--- a/Source/Core/Core/Src/HW/SerialInterface_Devices.h
+++ b/Source/Core/Core/Src/HW/SI_DeviceGCController.h
@@ -1,139 +1,90 @@
-// Copyright (C) 2003-2008 Dolphin Project.
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 2.0.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License 2.0 for more details.
-
-// A copy of the GPL 2.0 should have been included with the program.
-// If not, see http://www.gnu.org/licenses/
-
-// Official SVN repository and contact information can be found at
-// http://code.google.com/p/dolphin-emu/
-
-#ifndef _SERIALINTERFACE_DEVICES_H
-#define _SERIALINTERFACE_DEVICES_H
-
-#include "Common.h"
-class PointerWrap;
-
-class ISIDevice
-{
-protected:
- int m_iDeviceNumber;
-
-public:
-
- // constructor
- ISIDevice(int _iDeviceNumber) :
- m_iDeviceNumber(_iDeviceNumber)
- { }
- virtual ~ISIDevice() { }
-
- // run the SI Buffer
- virtual int RunBuffer(u8* _pBuffer, int _iLength);
-
- // return true on new data
- virtual bool GetData(u32& _Hi, u32& _Low) = 0;
-
- // send a command directly (no detour per buffer)
- virtual void SendCommand(u32 _Cmd) = 0;
-};
-
-// =====================================================================================================
-// standard gamecube controller
-// =====================================================================================================
-
-class CSIDevice_GCController : public ISIDevice
-{
-private:
-
- // commands
- enum EBufferCommands
- {
- CMD_INVALID = 0xFFFFFFFF,
- CMD_RESET = 0x00,
- CMD_ORIGIN = 0x41,
- CMD_RECALIBRATE = 0x42,
- };
-
- struct SOrigin
- {
- u8 uCommand;
- u8 unk_1;
- u8 uOriginStickX;
- u8 uOriginStickY;
- u8 uSubStickStickX; // ???
- u8 uSubStickStickY; // ???
- u8 uTrigger_L; // ???
- u8 uTrigger_R; // ???
- u8 unk_4;
- u8 unk_5;
- u8 unk_6;
- u8 unk_7;
- };
-
- enum EDirectCommands
- {
- CMD_RUMBLE = 0x40
- };
-
- union UCommand
- {
- u32 Hex;
- struct
- {
- unsigned Parameter1 : 8;
- unsigned Parameter2 : 8;
- unsigned Command : 8;
- unsigned : 8;
- };
- UCommand() {Hex = 0;}
- UCommand(u32 _iValue) {Hex = _iValue;}
- };
-
- SOrigin m_origin;
- int DeviceNum;
-
-public:
-
- // constructor
- CSIDevice_GCController(int _iDeviceNumber);
-
- // run the SI Buffer
- virtual int RunBuffer(u8* _pBuffer, int _iLength);
-
- // return true on new data
- virtual bool GetData(u32& _Hi, u32& _Low);
-
- // send a command directly
- virtual void SendCommand(u32 _Cmd);
-};
-
-// =====================================================================================================
-// dummy - no device attached
-// =====================================================================================================
-
-class CSIDevice_Dummy : public ISIDevice
-{
-public:
-
- // constructor
- CSIDevice_Dummy(int _iDeviceNumber);
-
- // run the SI Buffer
- virtual int RunBuffer(u8* _pBuffer, int _iLength);
-
- // return true on new data
- virtual bool GetData(u32& _Hi, u32& _Low);
-
- // send a command directly
- virtual void SendCommand(u32 _Cmd);
-};
-
-#endif
-
+// Copyright (C) 2003-2008 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#ifndef _SI_DEVICEGCCONTROLLER_H
+#define _SI_DEVICEGCCONTROLLER_H
+
+// =====================================================================================================
+// standard gamecube controller
+// =====================================================================================================
+
+class CSIDevice_GCController : public ISIDevice
+{
+private:
+
+ // commands
+ enum EBufferCommands
+ {
+ CMD_INVALID = 0xFFFFFFFF,
+ CMD_RESET = 0x00,
+ CMD_ORIGIN = 0x41,
+ CMD_RECALIBRATE = 0x42,
+ };
+
+ struct SOrigin
+ {
+ u8 uCommand;
+ u8 unk_1;
+ u8 uOriginStickX;
+ u8 uOriginStickY;
+ u8 uSubStickStickX; // ???
+ u8 uSubStickStickY; // ???
+ u8 uTrigger_L; // ???
+ u8 uTrigger_R; // ???
+ u8 unk_4;
+ u8 unk_5;
+ u8 unk_6;
+ u8 unk_7;
+ };
+
+ enum EDirectCommands
+ {
+ CMD_RUMBLE = 0x40
+ };
+
+ union UCommand
+ {
+ u32 Hex;
+ struct
+ {
+ unsigned Parameter1 : 8;
+ unsigned Parameter2 : 8;
+ unsigned Command : 8;
+ unsigned : 8;
+ };
+ UCommand() {Hex = 0;}
+ UCommand(u32 _iValue) {Hex = _iValue;}
+ };
+
+ SOrigin m_origin;
+ int DeviceNum;
+
+public:
+
+ // constructor
+ CSIDevice_GCController(int _iDeviceNumber);
+
+ // run the SI Buffer
+ virtual int RunBuffer(u8* _pBuffer, int _iLength);
+
+ // return true on new data
+ virtual bool GetData(u32& _Hi, u32& _Low);
+
+ // send a command directly
+ virtual void SendCommand(u32 _Cmd);
+};
+#endif
diff --git a/Source/Core/Core/Src/HW/SystemTimers.cpp b/Source/Core/Core/Src/HW/SystemTimers.cpp
index 79f1dc60ce..d9ec74be3e 100644
--- a/Source/Core/Core/Src/HW/SystemTimers.cpp
+++ b/Source/Core/Core/Src/HW/SystemTimers.cpp
@@ -23,7 +23,7 @@
#include "../HW/DSP.h"
#include "../HW/AudioInterface.h"
#include "../HW/VideoInterface.h"
-#include "../HW/SerialInterface.h"
+#include "../HW/SI.h"
#include "../HW/CommandProcessor.h" // for DC watchdog hack
#include "../HW/EXI_DeviceIPL.h"
#include "../PowerPC/PowerPC.h"
diff --git a/Source/Core/Core/Src/SConscript b/Source/Core/Core/Src/SConscript
index caeabf4ae9..e042d11bd8 100644
--- a/Source/Core/Core/Src/SConscript
+++ b/Source/Core/Core/Src/SConscript
@@ -46,7 +46,10 @@ files = ["Console.cpp",
"HW/PeripheralInterface.cpp",
"HW/PixelEngine.cpp",
"HW/SerialInterface.cpp",
- "HW/SerialInterface_Devices.cpp",
+ "HW/SI.cpp",
+ "HW/SI_Device.cpp",
+ "HW/SI_DeviceGBA.cpp",
+ "HW/SI_DeviceGCController.cpp",
"HW/StreamADPCM.cpp",
"HW/SystemTimers.cpp",
"HW/VideoInterface.cpp",
diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp
index f9968ed5e4..6c81d96cd6 100644
--- a/Source/Core/DolphinWX/Src/FrameTools.cpp
+++ b/Source/Core/DolphinWX/Src/FrameTools.cpp
@@ -134,9 +134,10 @@ void CFrame::CreateMenu()
wxMenu* pOptionsMenu = new wxMenu;
m_pPluginOptions = pOptionsMenu->Append(IDM_CONFIG_MAIN, _T("Co&nfigure..."));
pOptionsMenu->AppendSeparator();
- pOptionsMenu->Append(IDM_CONFIG_GFX_PLUGIN, _T("&Toolbar_PluginGFX settings"));
- pOptionsMenu->Append(IDM_CONFIG_DSP_PLUGIN, _T("&Toolbar_PluginDSP settings"));
- pOptionsMenu->Append(IDM_CONFIG_PAD_PLUGIN, _T("&Toolbar_PluginPAD settings"));
+ pOptionsMenu->Append(IDM_CONFIG_GFX_PLUGIN, _T("&GFX settings"));
+ pOptionsMenu->Append(IDM_CONFIG_DSP_PLUGIN, _T("&DSP settings"));
+ pOptionsMenu->Append(IDM_CONFIG_PAD_PLUGIN, _T("&PAD settings"));
+ pOptionsMenu->Append(IDM_CONFIG_WIIMOTE_PLUGIN, _T("&Wiimote settings"));
#ifdef _WIN32
pOptionsMenu->AppendSeparator();
pOptionsMenu->Append(IDM_TOGGLE_FULLSCREEN, _T("&Fullscreen\tAlt+Enter"));