commit current GBA link cable work. no touching (unless you're skid_au or ask first) :P

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5096 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Shawn Hoffman 2010-02-21 18:50:44 +00:00
parent f7bf29a528
commit b6a3df2fcf
6 changed files with 101 additions and 389 deletions

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9,00"
Version="9.00"
Name="Core"
ProjectGUID="{F0B874CB-4476-4199-9315-8343D05AE684}"
RootNamespace="Core"
@ -45,7 +45,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua"
AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua;..\..\..\Externals\SFML\include"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@ -115,7 +115,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua"
AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua;..\..\..\Externals\SFML\include"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
@ -189,7 +189,7 @@
FavorSizeOrSpeed="1"
OmitFramePointers="true"
EnableFiberSafeOptimizations="false"
AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua"
AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua;..\..\..\Externals\SFML\include"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
StringPooling="true"
RuntimeLibrary="0"
@ -265,7 +265,7 @@
OmitFramePointers="true"
EnableFiberSafeOptimizations="false"
WholeProgramOptimization="false"
AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua"
AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua;..\..\..\Externals\SFML\include"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
StringPooling="true"
RuntimeLibrary="0"
@ -339,7 +339,7 @@
FavorSizeOrSpeed="1"
OmitFramePointers="true"
EnableFiberSafeOptimizations="false"
AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua"
AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua;..\..\..\Externals\SFML\include"
PreprocessorDefinitions="NDEBUG;_LIB;DEBUGFAST;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
RuntimeLibrary="0"
BufferSecurityCheck="true"
@ -413,7 +413,7 @@
FavorSizeOrSpeed="1"
OmitFramePointers="true"
EnableFiberSafeOptimizations="false"
AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua"
AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib;..\..\..\Externals\Lua;..\..\..\Externals\SFML\include"
PreprocessorDefinitions="NDEBUG;_LIB;DEBUGFAST;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0"
RuntimeLibrary="0"
BufferSecurityCheck="false"
@ -616,14 +616,6 @@
<Filter
Name="SI - Serial Interface"
>
<File
RelativePath=".\Src\HW\GBAPipe.cpp"
>
</File>
<File
RelativePath=".\Src\HW\GBAPipe.h"
>
</File>
<File
RelativePath=".\Src\HW\SI.cpp"
>

View File

@ -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 <windows.h>
#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

View File

@ -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

View File

@ -17,135 +17,93 @@
#include "SI_Device.h"
#include "SI_DeviceGBA.h"
#include "GBAPipe.h"
#include "SFML/Network.hpp"
#include <algorithm>
// --- 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<EBufferCommands>(_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);
}

View File

@ -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

View File

@ -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}