experimental GBA stuff for XK :)

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2578 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Shawn Hoffman 2009-03-06 23:35:49 +00:00
parent 5ce9ffeab7
commit 95cf4cd86b
6 changed files with 341 additions and 82 deletions

View File

@ -0,0 +1,177 @@
// 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/
#ifdef _WIN32
#include <windows.h>
#endif
#include "Common.h"
#include "../Core.h"
#include "GBAPipe.h"
#include "../PowerPC/PowerPC.h"
#include "CommandProcessor.h"
#include "../Host.h"
#ifdef _WIN32
namespace GBAPipe
{
HANDLE m_hPipe;
bool m_bIsServer;
bool m_bEnabled;
u32 m_BlockStart;
#define PIPENAME "\\\\.\\pipe\\gbapipe"
void SetBlockStart(u32 addr)
{
m_BlockStart = addr;
}
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;
}
}
#else
namespace GBAPipe
{
void StartServer() { }
void ConnectAsClient() { }
void Stop() { }
void Read(u32& data){}
void Write(u32 data){}
bool IsEnabled() { return false; }
bool IsServer() { return false; }
}
// #error Provide a GBAPipe implementation or dummy it out, please
#endif

View File

@ -0,0 +1,51 @@
// 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/
// 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 _CPUCOMPARE_H
#define _CPUCOMPARE_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();
void SetBlockStart(u32 addr);
}
#endif

View File

@ -533,9 +533,9 @@ void ChangeDeviceCallback(u64 userdata, int cyclesLate)
{ {
u8 channel = (u8)(userdata >> 32); u8 channel = (u8)(userdata >> 32);
// doubt this matters... // doubt this matters...
// g_Channel[channel].m_Out.Hex = 0; g_Channel[channel].m_Out.Hex = 0;
// g_Channel[channel].m_InHi.Hex = 0; g_Channel[channel].m_InHi.Hex = 0;
// g_Channel[channel].m_InLo.Hex = 0; g_Channel[channel].m_InLo.Hex = 0;
// raise the NO RESPONSE error // raise the NO RESPONSE error
switch (channel) switch (channel)

View File

@ -17,6 +17,7 @@
#include "SI_Device.h" #include "SI_Device.h"
#include "SI_DeviceGBA.h" #include "SI_DeviceGBA.h"
#include "GBAPipe.h"
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// --- GameBoy Advance --- // --- GameBoy Advance ---
@ -25,6 +26,13 @@
CSIDevice_GBA::CSIDevice_GBA(int _iDeviceNumber) : CSIDevice_GBA::CSIDevice_GBA(int _iDeviceNumber) :
ISIDevice(_iDeviceNumber) ISIDevice(_iDeviceNumber)
{ {
GBAPipe::StartServer();
js.U16 = 0;
}
CSIDevice_GBA::~CSIDevice_GBA()
{
GBAPipe::Stop();
} }
int CSIDevice_GBA::RunBuffer(u8* _pBuffer, int _iLength) int CSIDevice_GBA::RunBuffer(u8* _pBuffer, int _iLength)
@ -33,80 +41,91 @@ int CSIDevice_GBA::RunBuffer(u8* _pBuffer, int _iLength)
ISIDevice::RunBuffer(_pBuffer, _iLength); ISIDevice::RunBuffer(_pBuffer, _iLength);
int iPosition = 0; int iPosition = 0;
while(iPosition < _iLength)
// read the command
EBufferCommands command = static_cast<EBufferCommands>(_pBuffer[3]);
iPosition++;
// handle it
switch(command)
{ {
// read the command // NOTE: All "Send/Recieve" mentioned here is from dolphin's perspective,
EBufferCommands command = static_cast<EBufferCommands>(_pBuffer[iPosition ^ 3]); // NOT the GBA's
iPosition++; // 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...
// handle it // (try playing with the fake joystat)
switch(command) // It seems like JOYSTAT is polled all the time, it's value may or may not matter
case CMD_RESET:
{ {
// NOTE: All "Send/Recieve" mentioned here is from dolphin's perspective, //Send 0xFF
// NOT the GBA's GBAPipe::Write(CMD_RESET);
// This means "Send"s are seen as CMDs to the GBA, and are therefor IMPORTANT :p //Recieve 0x00
// Also this means that we can randomly fill recieve bits and try for a fake gba... //Recieve 0x04
// for example, the ORd bits in RESET and STATUS are just some values to play with //Recieve from lower 8bits of JOYSTAT register
case CMD_RESET: for (;iPosition < _iLength; ++iPosition)
{ GBAPipe::Read(_pBuffer[iPosition]);
//Device Reset
//Send 0xFF
//Recieve 0x00
//Recieve 0x04
//Recieve from lower 8bits of SIOSTAT register
*(u32*)&_pBuffer[0] = SI_GBA;//|2; js.U16 = 0; // FAKE
iPosition = _iLength; // break the while loop js.stat_send = 1; // FAKE
INFO_LOG(SERIALINTERFACE, "GBA %i CMD_RESET", this->m_iDeviceNumber); *(u32*)&_pBuffer[0] |= SI_GBA | js.U16; // hax for now
} WARN_LOG(SERIALINTERFACE, "GBA %i CMD_RESET", this->m_iDeviceNumber);
break;
case CMD_STATUS:
{
//Type/Status Data Request
//Send 0x00
//Recieve 0x00
//Recieve 0x04
//Recieve from lower 8bits of SIOSTAT register
*(u32*)&_pBuffer[0] = SI_GBA;//|8;
iPosition = _iLength; // break the while loop
INFO_LOG(SERIALINTERFACE, "GBA %i CMD_STATUS", this->m_iDeviceNumber);
}
break;
case CMD_WRITE:
{
//GBA Data Write (to GBA)
//Send 0x15
//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
//Receive from lower 8bits of SIOSTAT register
INFO_LOG(SERIALINTERFACE, "GBA %i CMD_WRITE", this->m_iDeviceNumber);
}
break;
case CMD_READ:
{
//GBA Data Read (from GBA)
//Send 0x14
//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 SIOSTAT register
INFO_LOG(SERIALINTERFACE, "GBA CMD_READ");
}
break;
default:
{
WARN_LOG(SERIALINTERFACE, "GBA %i unknown command (0x%x)", this->m_iDeviceNumber, command);
iPosition = _iLength;
}
break;
} }
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; return iPosition;
} }
@ -117,7 +136,7 @@ int CSIDevice_GBA::RunBuffer(u8* _pBuffer, int _iLength)
bool bool
CSIDevice_GBA::GetData(u32& _Hi, u32& _Low) CSIDevice_GBA::GetData(u32& _Hi, u32& _Low)
{ {
INFO_LOG(SERIALINTERFACE, "GBA %i GetData Hi: 0x%x Low: 0x%x", this->m_iDeviceNumber, _Hi, _Low); INFO_LOG(SERIALINTERFACE, "GBA %i GetData Hi: 0x%08x Low: 0x%08x", this->m_iDeviceNumber, _Hi, _Low);
return true; return true;
} }
@ -128,5 +147,5 @@ CSIDevice_GBA::GetData(u32& _Hi, u32& _Low)
void void
CSIDevice_GBA::SendCommand(u32 _Cmd) CSIDevice_GBA::SendCommand(u32 _Cmd)
{ {
INFO_LOG(SERIALINTERFACE, "GBA %i SendCommand: (0x%x)", this->m_iDeviceNumber, _Cmd); INFO_LOG(SERIALINTERFACE, "GBA %i SendCommand: (0x%08x)", this->m_iDeviceNumber, _Cmd);
} }

View File

@ -35,19 +35,27 @@ private:
CMD_READ = 0x14 CMD_READ = 0x14
}; };
struct FAKE_JOYSTAT union FAKE_JOYSTAT
{ {
unsigned unused : 1; u16 U16;
unsigned stat_rec : 1; struct{
unsigned unused2 : 1; unsigned :1;
unsigned stat_send : 1; unsigned stat_rec :1; // GBA-side reception status flag
unsigned genpurpose : 2; unsigned :1;
unsigned unused3 :10; 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) //0x4000158 - JOYSTAT - Receive Status Register (R/W) (ON THE GBA)
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// NOTE: I am guessing that JOYSTAT == SIOSTAT, may be wrong // NOTE: there is a typo in GBATEK!
// in the JOY BUS command descriptions, SIOSTAT==JOYSTAT
//Bit Expl. //Bit Expl.
//0 Not used //0 Not used
//1 Receive Status Flag (0=Remote GBA is/was receiving) (Read Only?) //1 Receive Status Flag (0=Remote GBA is/was receiving) (Read Only?)
@ -66,6 +74,9 @@ public:
// Constructor // Constructor
CSIDevice_GBA(int _iDeviceNumber); CSIDevice_GBA(int _iDeviceNumber);
// Destructor
~CSIDevice_GBA();
// Run the SI Buffer // Run the SI Buffer
virtual int RunBuffer(u8* _pBuffer, int _iLength); virtual int RunBuffer(u8* _pBuffer, int _iLength);

View File

@ -51,6 +51,7 @@ files = ["Console.cpp",
"HW/SI.cpp", "HW/SI.cpp",
"HW/SI_Device.cpp", "HW/SI_Device.cpp",
"HW/SI_DeviceGBA.cpp", "HW/SI_DeviceGBA.cpp",
"HW/GBAPipe.cpp", # TEMPORARY
"HW/SI_DeviceGCController.cpp", "HW/SI_DeviceGCController.cpp",
"HW/StreamADPCM.cpp", "HW/StreamADPCM.cpp",
"HW/SystemTimers.cpp", "HW/SystemTimers.cpp",