diff --git a/Source/Core/Core/Core.vcproj b/Source/Core/Core/Core.vcproj index dc0f66f830..f83c42385d 100644 --- a/Source/Core/Core/Core.vcproj +++ b/Source/Core/Core/Core.vcproj @@ -583,6 +583,14 @@ RelativePath=".\Src\HW\EXI_DeviceEthernet.h" > + + + + diff --git a/Source/Core/Core/Src/HW/EXI_Channel.cpp b/Source/Core/Core/Src/HW/EXI_Channel.cpp index 2af1ae1e88..0d28c7ce08 100644 --- a/Source/Core/Core/Src/HW/EXI_Channel.cpp +++ b/Source/Core/Core/Src/HW/EXI_Channel.cpp @@ -233,13 +233,7 @@ void CEXIChannel::Write32(const u32 _iValue, const u32 _iRegister) { case EXI_READ: m_ImmData = pDevice->ImmRead(m_Control.TLEN + 1); break; case EXI_WRITE: pDevice->ImmWrite(m_ImmData, m_Control.TLEN + 1); break; - case EXI_READWRITE: - ERROR_LOG(SP1, "RW UNSUPPORTED"); -/* Only used by USBGecko? - pDevice->ImmWrite(m_ImmData, m_Control.TLEN + 1); - m_ImmData = pDevice->ImmRead(m_Control.TLEN + 1); */ - break; - + case EXI_READWRITE: pDevice->ImmReadWrite(m_ImmData, m_Control.TLEN + 1); break; default: _dbg_assert_msg_(EXPANSIONINTERFACE,0,"EXI Imm: Unknown transfer type %i", m_Control.RW); } m_Control.TSTART = 0; @@ -269,4 +263,4 @@ void CEXIChannel::Write32(const u32 _iValue, const u32 _iRegister) m_ImmData = _iValue; break; } -} +} \ No newline at end of file diff --git a/Source/Core/Core/Src/HW/EXI_Device.cpp b/Source/Core/Core/Src/HW/EXI_Device.cpp index ed7f560677..fc73f4e0d8 100644 --- a/Source/Core/Core/Src/HW/EXI_Device.cpp +++ b/Source/Core/Core/Src/HW/EXI_Device.cpp @@ -24,13 +24,14 @@ #include "EXI_DeviceMic.h" #include "EXI_DeviceEthernet.h" #include "EXI_DeviceAMBaseboard.h" +#include "EXI_DeviceGecko.h" #include "../Core.h" #include "../ConfigManager.h" // --- interface IEXIDevice --- -void IEXIDevice::ImmWrite(u32 _uData, u32 _uSize) +void IEXIDevice::ImmWrite(u32 _uData, u32 _uSize) { while (_uSize--) { @@ -137,6 +138,10 @@ IEXIDevice* EXIDevice_Create(TEXIDevices _EXIDevice) return new CEXIAMBaseboard(); break; + case EXIDEVICE_GECKO: + return new CEXIGecko(); + break; + case EXIDEVICE_NONE: default: return new IEXIDevice(); diff --git a/Source/Core/Core/Src/HW/EXI_Device.h b/Source/Core/Core/Src/HW/EXI_Device.h index 173cec0b25..4cc613950b 100644 --- a/Source/Core/Core/Src/HW/EXI_Device.h +++ b/Source/Core/Core/Src/HW/EXI_Device.h @@ -30,7 +30,8 @@ private: public: // Immediate copy functions virtual void ImmWrite(u32 _uData, u32 _uSize); - virtual u32 ImmRead(u32 _uSize); + virtual u32 ImmRead(u32 _uSize); + virtual void ImmReadWrite(u32 &/*_uData*/, u32 /*_uSize*/) {} // DMA copy functions virtual void DMAWrite(u32 _uAddr, u32 _uSize); @@ -59,6 +60,7 @@ enum TEXIDevices EXIDEVICE_MIC, EXIDEVICE_ETH, EXIDEVICE_AM_BASEBOARD, + EXIDEVICE_GECKO, EXIDEVICE_NONE = (u8)-1 }; diff --git a/Source/Core/Core/Src/HW/EXI_DeviceGecko.cpp b/Source/Core/Core/Src/HW/EXI_DeviceGecko.cpp new file mode 100644 index 0000000000..f331d9084f --- /dev/null +++ b/Source/Core/Core/Src/HW/EXI_DeviceGecko.cpp @@ -0,0 +1,170 @@ +// Copyright (C) 2003 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 "EXI_Device.h" +#include "EXI_DeviceGecko.h" + +#include "SFML/Network.hpp" +#include "Thread.h" +#include + +static Common::Thread *connectionThread = NULL; +static std::queue waiting_socks; +static Common::CriticalSection cs_gecko; +namespace { volatile bool server_running; } + +static THREAD_RETURN GeckoConnectionWaiter(void*) +{ + server_running = true; + + Common::SetCurrentThreadName("Gecko Connection Waiter"); + + sf::SocketTCP server; + // "dolphin gecko" + if (!server.Listen(0xd6ec)) + return 0; + + server.SetBlocking(false); + + sf::SocketTCP new_client; + while (server_running) + { + if (server.Accept(new_client) == sf::Socket::Done) + { + cs_gecko.Enter(); + waiting_socks.push(new_client); + cs_gecko.Leave(); + } + SLEEP(1); + } + server.Close(); + return 0; +} + +void GeckoConnectionWaiter_Shutdown() +{ + server_running = false; + if (connectionThread) + { + connectionThread->WaitForDeath(); + delete connectionThread; + connectionThread = NULL; + } +} + +static bool GetAvailableSock(sf::SocketTCP& sock_to_fill) +{ + bool sock_filled = false; + + cs_gecko.Enter(); + if (waiting_socks.size()) + { + sock_to_fill = waiting_socks.front(); + waiting_socks.pop(); + sock_filled = true; + } + cs_gecko.Leave(); + + return sock_filled; +} + +GeckoSockServer::GeckoSockServer() +{ + if (!connectionThread) + connectionThread = new Common::Thread(GeckoConnectionWaiter, (void*)0); +} + +GeckoSockServer::~GeckoSockServer() +{ + client.Close(); +} + +CEXIGecko::CEXIGecko() + : m_uPosition(0) + , recv_fifo(false) +{ +} + +void CEXIGecko::SetCS(int cs) +{ + if (cs) + m_uPosition = 0; +} + +bool CEXIGecko::IsPresent() +{ + return true; +} + +void CEXIGecko::ImmReadWrite(u32 &_uData, u32 _uSize) +{ + if (!client.IsValid()) + if (!GetAvailableSock(client)) + ;// TODO nothing for now + + // for debug + u32 oldval = _uData; + // TODO do we really care about _uSize? + + u8 data = 0; + std::size_t got; + + switch (_uData >> 28) + { + // maybe do something fun later + case CMD_LED_OFF: + break; + case CMD_LED_ON: + break; + // maybe should only | 2bytes? + case CMD_INIT: + _uData = ident; + break; + // PC -> Gecko + case CMD_RECV: + // TODO recv + client.Receive((char*)&data, sizeof(data), got); + recv_fifo = !!got; + if (recv_fifo) + _uData = 0x08000000 | (data << 16); + break; + // Gecko -> PC + case CMD_SEND: + data = (_uData >> 20) & 0xff; + // TODO send + client.Send((char*)&data, sizeof(data)); + // If successful + _uData |= 0x04000000; + break; + // Check if ok for Gecko -> PC, or FIFO full + // |= 0x04000000 if FIFO is not full + case CMD_CHK_TX: + _uData = 0x04000000; + break; + // Check if data in FIFO for PC -> Gecko, or FIFO empty + // |= 0x04000000 if data in recv FIFO + case CMD_CHK_RX: + //_uData = recv_fifo ? 0x04000000 : 0; + _uData = 0x04000000; + break; + default: + ERROR_LOG(EXPANSIONINTERFACE, "Uknown USBGecko command %x", _uData); + break; + } + + if (_uData) { ERROR_LOG(EXPANSIONINTERFACE, "rw %x %08x %08x", oldval, _uData, _uSize); } +} diff --git a/Source/Core/Core/Src/HW/EXI_DeviceGecko.h b/Source/Core/Core/Src/HW/EXI_DeviceGecko.h new file mode 100644 index 0000000000..38c57ab517 --- /dev/null +++ b/Source/Core/Core/Src/HW/EXI_DeviceGecko.h @@ -0,0 +1,63 @@ +// Copyright (C) 2003 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 _EXIDEVICE_GECKO_H +#define _EXIDEVICE_GECKO_H + +#include "SFML/Network.hpp" + +class GeckoSockServer + : public sf::SocketTCP +{ +public: + GeckoSockServer(); + ~GeckoSockServer(); + +//private: + sf::SocketTCP client; +}; + +class CEXIGecko + : public IEXIDevice + , private GeckoSockServer +{ +public: + CEXIGecko(); + void SetCS(int _iCS); + bool IsPresent(); + void ImmReadWrite(u32 &_uData, u32 _uSize); + +private: + enum + { + CMD_LED_OFF = 0x7, + CMD_LED_ON = 0x8, + CMD_INIT = 0x9, + CMD_RECV = 0xa, + CMD_SEND = 0xb, + CMD_CHK_TX = 0xc, + CMD_CHK_RX = 0xd, + }; + + u32 m_uPosition; + bool recv_fifo; + + static const u32 ident = 0x04700000; +}; + +#endif + diff --git a/Source/Core/Core/Src/HW/SI_DeviceGBA.cpp b/Source/Core/Core/Src/HW/SI_DeviceGBA.cpp index 7df516d8a2..17b069bc85 100644 --- a/Source/Core/Core/Src/HW/SI_DeviceGBA.cpp +++ b/Source/Core/Core/Src/HW/SI_DeviceGBA.cpp @@ -25,7 +25,7 @@ static Common::Thread *connectionThread = NULL; static std::queue waiting_socks; static Common::CriticalSection cs_gba; -volatile bool server_running; +namespace { volatile bool server_running; } // --- GameBoy Advance "Link Cable" --- @@ -36,6 +36,7 @@ THREAD_RETURN GBAConnectionWaiter(void*) Common::SetCurrentThreadName("GBA Connection Waiter"); sf::SocketTCP server; + // "dolphin gba" if (!server.Listen(0xd6ba)) return 0; @@ -101,11 +102,8 @@ void GBASockServer::Transfer(char* si_buffer) if (!GetAvailableSock(client)) return; - current_data[0] = si_buffer[3]; - current_data[1] = si_buffer[2]; - current_data[2] = si_buffer[1]; - current_data[3] = si_buffer[0]; - current_data[4] = si_buffer[7]; + for (int i = 0; i < 5; i++) + current_data[i] = si_buffer[i ^ 3]; u8 cmd = *current_data; @@ -138,11 +136,8 @@ void GBASockServer::Transfer(char* si_buffer) (unsigned int)num_received, (unsigned int)num_expecting); #endif - si_buffer[0] = current_data[3]; - si_buffer[1] = current_data[2]; - si_buffer[2] = current_data[1]; - si_buffer[3] = current_data[0]; - si_buffer[7] = current_data[4]; + for (int i = 0; i < 5; i++) + si_buffer[i ^ 3] = current_data[i]; } CSIDevice_GBA::CSIDevice_GBA(int _iDeviceNumber) diff --git a/Source/Core/DolphinWX/Src/ConfigMain.cpp b/Source/Core/DolphinWX/Src/ConfigMain.cpp index b768b1146e..021b347e93 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.cpp +++ b/Source/Core/DolphinWX/Src/ConfigMain.cpp @@ -75,6 +75,7 @@ static const wxLanguage langIds[] = #define EXIDEV_MIC_STR _trans("Mic") #define EXIDEV_BBA_STR "BBA" #define EXIDEV_AM_BB_STR _trans("AM-Baseboard") +#define EXIDEV_GECKO_STR "USBGecko" #ifdef WIN32 //only used with xgettext to be picked up as translatable string. @@ -564,7 +565,7 @@ void CConfigMain::CreateGUIControls() GCEXIDeviceText[0] = new wxStaticText(GamecubePage, ID_GC_EXIDEVICE_SLOTA_TEXT, wxT("Slot A"), wxDefaultPosition, wxDefaultSize); GCEXIDeviceText[1] = new wxStaticText(GamecubePage, ID_GC_EXIDEVICE_SLOTB_TEXT, wxT("Slot B"), wxDefaultPosition, wxDefaultSize); GCEXIDeviceText[2] = new wxStaticText(GamecubePage, ID_GC_EXIDEVICE_SP1_TEXT, wxT("SP1 "), wxDefaultPosition, wxDefaultSize); - const wxString SlotDevices[] = {_(DEV_NONE_STR), _(DEV_DUMMY_STR), _(EXIDEV_MEMCARD_STR) + const wxString SlotDevices[] = {_(DEV_NONE_STR), _(DEV_DUMMY_STR), _(EXIDEV_MEMCARD_STR), _(EXIDEV_GECKO_STR) #if HAVE_PORTAUDIO , _(EXIDEV_MIC_STR) #endif @@ -591,7 +592,7 @@ void CConfigMain::CreateGUIControls() isMemcard = GCEXIDevice[i]->SetStringSelection(SlotDevices[2]); break; case EXIDEVICE_MIC: - GCEXIDevice[i]->SetStringSelection(SlotDevices[3]); + GCEXIDevice[i]->SetStringSelection(SlotDevices[4]); break; case EXIDEVICE_ETH: GCEXIDevice[i]->SetStringSelection(SP1Devices[2]); @@ -599,6 +600,9 @@ void CConfigMain::CreateGUIControls() case EXIDEVICE_AM_BASEBOARD: GCEXIDevice[i]->SetStringSelection(SP1Devices[3]); break; + case EXIDEVICE_GECKO: + GCEXIDevice[i]->SetStringSelection(SlotDevices[3]); + break; case EXIDEVICE_DUMMY: default: GCEXIDevice[i]->SetStringSelection(SlotDevices[1]); @@ -1039,6 +1043,8 @@ void CConfigMain::ChooseEXIDevice(std::string deviceName, int deviceNum) tempType = EXIDEVICE_ETH; else if (!deviceName.compare(EXIDEV_AM_BB_STR)) tempType = EXIDEVICE_AM_BASEBOARD; + else if (!deviceName.compare(EXIDEV_GECKO_STR)) + tempType = EXIDEVICE_GECKO; else if (!deviceName.compare(DEV_NONE_STR)) tempType = EXIDEVICE_NONE; else