diff --git a/Source/Core/Core/Core.vcproj b/Source/Core/Core/Core.vcproj index 7732da0d93..5a18054a09 100644 --- a/Source/Core/Core/Core.vcproj +++ b/Source/Core/Core/Core.vcproj @@ -1,7 +1,7 @@ - - - - diff --git a/Source/Core/Core/Src/HW/GBAPipe.cpp b/Source/Core/Core/Src/HW/GBAPipe.cpp deleted file mode 100644 index 5852e9851b..0000000000 --- a/Source/Core/Core/Src/HW/GBAPipe.cpp +++ /dev/null @@ -1,164 +0,0 @@ -// 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/ - -#ifdef _WIN32 -#include -#endif - -#include "GBAPipe.h" - - -#ifdef _WIN32 - -namespace GBAPipe -{ - -HANDLE m_hPipe; -bool m_bIsServer; -bool m_bEnabled; - -#define PIPENAME "\\\\.\\pipe\\gbapipe" - - -void StartServer() -{ - if (m_bEnabled) - return; - - //TODO: error checking - m_hPipe = CreateNamedPipe( - PIPENAME, - PIPE_ACCESS_DUPLEX, // client and server can both r+w - PIPE_WAIT |/* PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,*/ PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, - 1, //maxinst - 0x1000, //outbufsize - 0x1000, //inbufsize - INFINITE, //timeout - 0); - - if (m_hPipe == INVALID_HANDLE_VALUE) - { - INFO_LOG(SERIALINTERFACE, "Failed to create pipe."); - } - else - { - INFO_LOG(SERIALINTERFACE, "Pipe %s created.", PIPENAME); - } - - m_bIsServer = true; - m_bEnabled = true; -} - -void ConnectAsClient() -{ - if (m_bEnabled) - return; - - //TODO: error checking - m_hPipe = CreateFile( - PIPENAME, - GENERIC_READ|GENERIC_WRITE, - 0, //share - NULL, - OPEN_EXISTING, - 0, - NULL); - - if (m_hPipe == INVALID_HANDLE_VALUE) - { - INFO_LOG(SERIALINTERFACE, "Failed to connect to pipe. %08x (2 = file not found)", GetLastError()); - } - - m_bEnabled = true; - m_bIsServer = false; -} - -void Stop() -{ - if (m_bEnabled) - { - if (m_bIsServer) - DisconnectNamedPipe(m_hPipe); - - CloseHandle(m_hPipe); - m_bEnabled = false; - } -} - -void Read(u8& data) -{ - if (!m_bEnabled) - return; - - u32 read; - memset(&data, 0x00, sizeof(data)); // pad with zeros for now - HRESULT result = ReadFile(m_hPipe, &data, sizeof(data), (LPDWORD)&read, FALSE); - if (FAILED(result)/* || read != sizeof(data)*/) - { - INFO_LOG(SERIALINTERFACE, "Failed to read pipe %s", PIPENAME); - Stop(); - } - else - { - INFO_LOG(SERIALINTERFACE, "read %x bytes: 0x%02x", read, data); - } -} - -void Write(u8 data) -{ - if (!m_bEnabled) - return; - - u32 written; - HRESULT result = WriteFile(m_hPipe, &data, sizeof(data), (LPDWORD)&written,FALSE); - if (FAILED(result)) - { - INFO_LOG(SERIALINTERFACE, "Failed to write to pipe %s", PIPENAME); - Stop(); - } - else - { - INFO_LOG(SERIALINTERFACE, "Wrote %x bytes: 0x%02x", written, data); - } -} - -bool IsEnabled() -{ - return m_bEnabled; -} - -bool IsServer() -{ - return m_bIsServer; -} - -} // namespace GBAPipe - -#else - -namespace GBAPipe -{ -void StartServer() { } -void ConnectAsClient() { } -void Stop() { } -void Read(u8& data) { } -void Write(u8 data) { } -bool IsEnabled() { return false; } -bool IsServer() { return false; } -} // namespace GBAPipe - -#endif diff --git a/Source/Core/Core/Src/HW/GBAPipe.h b/Source/Core/Core/Src/HW/GBAPipe.h deleted file mode 100644 index f8ac6b795e..0000000000 --- a/Source/Core/Core/Src/HW/GBAPipe.h +++ /dev/null @@ -1,51 +0,0 @@ -// 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/ -// Sets up and maintains interprocess communication to make it possible -// to easily compare any two cpu cores by running two instances of DolphinHLE and -// comparing them to each other. -// - -#ifndef _GBAPIPE_H -#define _GBAPIPE_H - -#include "Common.h" - -namespace GBAPipe -{ - -// start the server -void StartServer(); - -// connect as client -void ConnectAsClient(); - -// stop -void Stop(); - -// Transfer funcs -void Read(u8& data); -void Write(u8 data); - -// IsEnabled -bool IsEnabled(); - -// IsServer -bool IsServer(); - -} // namespace GBAPipe - -#endif diff --git a/Source/Core/Core/Src/HW/SI_DeviceGBA.cpp b/Source/Core/Core/Src/HW/SI_DeviceGBA.cpp index ec6983edaa..1e913fe6a9 100644 --- a/Source/Core/Core/Src/HW/SI_DeviceGBA.cpp +++ b/Source/Core/Core/Src/HW/SI_DeviceGBA.cpp @@ -17,135 +17,93 @@ #include "SI_Device.h" #include "SI_DeviceGBA.h" -#include "GBAPipe.h" +#include "SFML/Network.hpp" +#include -// --- GameBoy Advance --- - - -CSIDevice_GBA::CSIDevice_GBA(int _iDeviceNumber) : - ISIDevice(_iDeviceNumber) +// --- GameBoy Advance "Link Cable" --- +GBASockServer::GBASockServer() +{ + if (!server.Listen(8080)) + return; + + server.Accept(client, &client_addr); +} + +GBASockServer::~GBASockServer() +{ + client.Close(); + server.Close(); +} + +// Blocking, since GBA must always send lower byte of REG_JOYSTAT +void GBASockServer::Transfer(char* si_buffer) +{ + 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]; + + u8 cmd = *current_data; + + if (cmd == CMD_WRITE) + client.Send(current_data, sizeof(current_data)); + else + client.Send(current_data, 1); + + DEBUG_LOG(SERIALINTERFACE, "> cmd %02x %02x%02x%02x%02x", + (u8)current_data[0], (u8)current_data[1], (u8)current_data[2], + (u8)current_data[3], (u8)current_data[4]); + + memset(current_data, 0, sizeof(current_data)); + size_t num_received = 0; + client.Receive(current_data, sizeof(current_data), num_received); + + DEBUG_LOG(SERIALINTERFACE, "< %02x%02x%02x%02x%02x", + (u8)current_data[0], (u8)current_data[1], (u8)current_data[2], + (u8)current_data[3], (u8)current_data[4]); + +#ifdef _DEBUG + size_t num_expecting = 3; + if (cmd == CMD_READ) + num_expecting = 5; + else if (cmd == CMD_WRITE) + num_expecting = 1; + if (num_received != num_expecting) + ERROR_LOG(SERIALINTERFACE, "%x:%x:%x", (u8)cmd, num_received, 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]; +} + +CSIDevice_GBA::CSIDevice_GBA(int _iDeviceNumber) + : ISIDevice(_iDeviceNumber) + , GBASockServer() { - GBAPipe::StartServer(); - js.U16 = 0; } CSIDevice_GBA::~CSIDevice_GBA() { - GBAPipe::Stop(); } int CSIDevice_GBA::RunBuffer(u8* _pBuffer, int _iLength) { - // for debug logging only - ISIDevice::RunBuffer(_pBuffer, _iLength); - - int iPosition = 0; - - // read the command - EBufferCommands command = static_cast(_pBuffer[3]); - iPosition++; - - // handle it - switch(command) - { - // NOTE: All "Send/Recieve" mentioned here is from dolphin's perspective, - // NOT the GBA's - // This means the first "Send"s are seen as CMDs to the GBA, and are therefor IMPORTANT :p - // Also this means that we can randomly fill recieve bits and try for a fake gba... - // (try playing with the fake joystat) - // It seems like JOYSTAT is polled all the time, it's value may or may not matter - case CMD_RESET: - { - //Send 0xFF - GBAPipe::Write(CMD_RESET); - //Recieve 0x00 - //Recieve 0x04 - //Recieve from lower 8bits of JOYSTAT register - for (;iPosition < _iLength; ++iPosition) - GBAPipe::Read(_pBuffer[iPosition]); - - js.U16 = 0; // FAKE - js.stat_send = 1; // FAKE - *(u32*)&_pBuffer[0] |= SI_GBA | js.U16; // hax for now - WARN_LOG(SERIALINTERFACE, "GBA %i CMD_RESET", this->m_iDeviceNumber); - } - break; - case CMD_STATUS: - { - //Send 0x00 - GBAPipe::Write(CMD_STATUS); - //Recieve 0x00 - //Recieve 0x04 - //Recieve from lower 8bits of JOYSTAT register - for (;iPosition < _iLength; ++iPosition) - GBAPipe::Read(_pBuffer[iPosition]); - - js.U16 = 0; // FAKE - js.stat_rec = 1; // FAKE - *(u32*)&_pBuffer[0] |= SI_GBA | js.U16; // hax for now - WARN_LOG(SERIALINTERFACE, "GBA %i CMD_STATUS", this->m_iDeviceNumber); - } - break; - // Probably read and write belong in getdata and sendcommand - case CMD_WRITE: - { - //Send 0x15 - GBAPipe::Write(CMD_WRITE); - //Send to Lower 8bits of JOY_RECV_L - //Send to Upper 8bits of JOY_RECV_L - //Send to Lower 8bits of JOY_RECV_H - //Send to Upper 8bits of JOY_RECV_H - for (;iPosition < _iLength-1; ++iPosition) - GBAPipe::Write(_pBuffer[iPosition]); - //Receive from lower 8bits of JOYSTAT register - GBAPipe::Read(_pBuffer[++iPosition]); - - WARN_LOG(SERIALINTERFACE, "GBA %i CMD_WRITE", this->m_iDeviceNumber); - } - break; - case CMD_READ: - { - //Send 0x14 - GBAPipe::Write(CMD_READ); - //Receive from Lower 8bits of JOY_TRANS_L - //Receive from Upper 8bits of JOY_TRANS_L - //Receive from Lower 8bits of JOY_TRANS_H - //Receive from Upper 8bits of JOY_TRANS_H - //Receive from lower 8bits of JOYSTAT register - for (;iPosition < _iLength; ++iPosition) - GBAPipe::Read(_pBuffer[iPosition]); - - WARN_LOG(SERIALINTERFACE, "GBA %i CMD_READ", this->m_iDeviceNumber);; - } - break; - default: - { - WARN_LOG(SERIALINTERFACE, "GBA %i CMD_UNKNOWN (0x%x)", this->m_iDeviceNumber, command); - } - break; - } - INFO_LOG(SERIALINTERFACE, "GBA buffer %08x",*(u32*)&_pBuffer[0]); - - return iPosition; + Transfer((char*)_pBuffer); + return _iLength; } - -// GetData - -bool -CSIDevice_GBA::GetData(u32& _Hi, u32& _Low) +bool CSIDevice_GBA::GetData(u32& _Hi, u32& _Low) { - INFO_LOG(SERIALINTERFACE, "GBA %i GetData Hi: 0x%08x Low: 0x%08x", this->m_iDeviceNumber, _Hi, _Low); - + DEBUG_LOG(SERIALINTERFACE, "GBA %i GetData Hi: 0x%08x Low: 0x%08x", m_iDeviceNumber, _Hi, _Low); return true; } - -// SendCommand - -void -CSIDevice_GBA::SendCommand(u32 _Cmd, u8 _Poll) +void CSIDevice_GBA::SendCommand(u32 _Cmd, u8 _Poll) { - INFO_LOG(SERIALINTERFACE, "GBA %i SendCommand: (0x%08x)", this->m_iDeviceNumber, _Cmd); + DEBUG_LOG(SERIALINTERFACE, "GBA %i SendCommand: (0x%08x)", m_iDeviceNumber, _Cmd); } diff --git a/Source/Core/Core/Src/HW/SI_DeviceGBA.h b/Source/Core/Core/Src/HW/SI_DeviceGBA.h index ed09586235..c3da5e9528 100644 --- a/Source/Core/Core/Src/HW/SI_DeviceGBA.h +++ b/Source/Core/Core/Src/HW/SI_DeviceGBA.h @@ -18,63 +18,38 @@ #ifndef _SI_DEVICEGBA_H #define _SI_DEVICEGBA_H +#include "SFML/Network.hpp" -// GameBoy Advance +// GameBoy Advance "Link Cable" - -class CSIDevice_GBA : public ISIDevice +class GBASockServer : public sf::SocketTCP { -private: +public: + GBASockServer(); + ~GBASockServer(); - // Commands + void Transfer(char* si_buffer); + + char current_data[5]; + +private: enum EBufferCommands { - CMD_RESET = 0xFF, - CMD_STATUS = 0x00, - CMD_WRITE = 0x15, - CMD_READ = 0x14 + CMD_RESET = 0xff, + CMD_STATUS = 0x00, + CMD_READ = 0x14, + CMD_WRITE = 0x15 }; - union FAKE_JOYSTAT - { - u16 U16; - struct{ - unsigned :1; - unsigned stat_rec :1; // GBA-side reception status flag - unsigned :1; - unsigned stat_send :1; // GBA-side transmission status flag - unsigned gp0 :1; // General-purpose flag 0 - unsigned gp1 :1; // General-purpose flag 1 - unsigned :2; - - unsigned :8; - }; - }; - FAKE_JOYSTAT js; - - //0x4000158 - JOYSTAT - Receive Status Register (R/W) (ON THE GBA) - - // NOTE: there is a typo in GBATEK! - // in the JOY BUS command descriptions, SIOSTAT==JOYSTAT - //Bit Expl. - //0 Not used - //1 Receive Status Flag (0=Remote GBA is/was receiving) (Read Only?) - //2 Not used - //3 Send Status Flag (1=Remote GBA is/was sending) (Read Only?) - //4-5 General Purpose Flag (Not assigned, may be used for whatever purpose) - //6-15 Not used - //-------------------------------------- - //0b0000000000 00 0 0 0 0 - //______________________________________ - //Bit 1 is automatically set when writing to local JOY_TRANS. - //Bit 3 is automatically reset when reading from local JOY_RECV. + sf::SocketTCP server; + sf::SocketTCP client; + sf::IPAddress client_addr; +}; +class CSIDevice_GBA : public ISIDevice, private GBASockServer +{ public: - - // Constructor CSIDevice_GBA(int _iDeviceNumber); - - // Destructor ~CSIDevice_GBA(); // Run the SI Buffer @@ -86,4 +61,5 @@ public: // Send a command directly virtual void SendCommand(u32 _Cmd, u8 _Poll); }; + #endif diff --git a/Source/Dolphin.sln b/Source/Dolphin.sln index d272306500..d165e7e58c 100644 --- a/Source/Dolphin.sln +++ b/Source/Dolphin.sln @@ -6,6 +6,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Core", "Core\Core\Core.vcpr {DA4CA030-A741-4DDC-9DA8-B2F351F0F158} = {DA4CA030-A741-4DDC-9DA8-B2F351F0F158} {33546D62-7F34-4EA6-A88E-D538B36E16BF} = {33546D62-7F34-4EA6-A88E-D538B36E16BF} {3E03C179-8251-46E4-81F4-466F114BAC63} = {3E03C179-8251-46E4-81F4-466F114BAC63} + {823DDC98-42D5-4A38-88CF-9DC06C788AE4} = {823DDC98-42D5-4A38-88CF-9DC06C788AE4} {29C2ABC1-ADA5-42CD-A5FC-96022D52A510} = {29C2ABC1-ADA5-42CD-A5FC-96022D52A510} {C573CAF7-EE6A-458E-8049-16C0BF34C2E9} = {C573CAF7-EE6A-458E-8049-16C0BF34C2E9} {B7F1A9FB-BEA8-416E-9460-AE35A6A5165C} = {B7F1A9FB-BEA8-416E-9460-AE35A6A5165C}