mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 05:47:56 -07:00
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:
parent
5ce9ffeab7
commit
95cf4cd86b
177
Source/Core/Core/Src/HW/GBAPipe.cpp
Normal file
177
Source/Core/Core/Src/HW/GBAPipe.cpp
Normal 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
|
51
Source/Core/Core/Src/HW/GBAPipe.h
Normal file
51
Source/Core/Core/Src/HW/GBAPipe.h
Normal 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
|
@ -533,9 +533,9 @@ void ChangeDeviceCallback(u64 userdata, int cyclesLate)
|
||||
{
|
||||
u8 channel = (u8)(userdata >> 32);
|
||||
// doubt this matters...
|
||||
// g_Channel[channel].m_Out.Hex = 0;
|
||||
// g_Channel[channel].m_InHi.Hex = 0;
|
||||
// g_Channel[channel].m_InLo.Hex = 0;
|
||||
g_Channel[channel].m_Out.Hex = 0;
|
||||
g_Channel[channel].m_InHi.Hex = 0;
|
||||
g_Channel[channel].m_InLo.Hex = 0;
|
||||
|
||||
// raise the NO RESPONSE error
|
||||
switch (channel)
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "SI_Device.h"
|
||||
#include "SI_DeviceGBA.h"
|
||||
#include "GBAPipe.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// --- GameBoy Advance ---
|
||||
@ -25,6 +26,13 @@
|
||||
CSIDevice_GBA::CSIDevice_GBA(int _iDeviceNumber) :
|
||||
ISIDevice(_iDeviceNumber)
|
||||
{
|
||||
GBAPipe::StartServer();
|
||||
js.U16 = 0;
|
||||
}
|
||||
|
||||
CSIDevice_GBA::~CSIDevice_GBA()
|
||||
{
|
||||
GBAPipe::Stop();
|
||||
}
|
||||
|
||||
int CSIDevice_GBA::RunBuffer(u8* _pBuffer, int _iLength)
|
||||
@ -33,80 +41,91 @@ int CSIDevice_GBA::RunBuffer(u8* _pBuffer, int _iLength)
|
||||
ISIDevice::RunBuffer(_pBuffer, _iLength);
|
||||
|
||||
int iPosition = 0;
|
||||
while(iPosition < _iLength)
|
||||
|
||||
// read the command
|
||||
EBufferCommands command = static_cast<EBufferCommands>(_pBuffer[3]);
|
||||
iPosition++;
|
||||
|
||||
// handle it
|
||||
switch(command)
|
||||
{
|
||||
// read the command
|
||||
EBufferCommands command = static_cast<EBufferCommands>(_pBuffer[iPosition ^ 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:
|
||||
{
|
||||
// NOTE: All "Send/Recieve" mentioned here is from dolphin's perspective,
|
||||
// NOT the GBA's
|
||||
// This means "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...
|
||||
// for example, the ORd bits in RESET and STATUS are just some values to play with
|
||||
case CMD_RESET:
|
||||
{
|
||||
//Device Reset
|
||||
//Send 0xFF
|
||||
//Recieve 0x00
|
||||
//Recieve 0x04
|
||||
//Recieve from lower 8bits of SIOSTAT register
|
||||
//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]);
|
||||
|
||||
*(u32*)&_pBuffer[0] = SI_GBA;//|2;
|
||||
iPosition = _iLength; // break the while loop
|
||||
INFO_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;
|
||||
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;
|
||||
}
|
||||
@ -117,7 +136,7 @@ int CSIDevice_GBA::RunBuffer(u8* _pBuffer, int _iLength)
|
||||
bool
|
||||
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;
|
||||
}
|
||||
@ -128,5 +147,5 @@ CSIDevice_GBA::GetData(u32& _Hi, u32& _Low)
|
||||
void
|
||||
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);
|
||||
}
|
||||
|
@ -35,19 +35,27 @@ private:
|
||||
CMD_READ = 0x14
|
||||
};
|
||||
|
||||
struct FAKE_JOYSTAT
|
||||
union FAKE_JOYSTAT
|
||||
{
|
||||
unsigned unused : 1;
|
||||
unsigned stat_rec : 1;
|
||||
unsigned unused2 : 1;
|
||||
unsigned stat_send : 1;
|
||||
unsigned genpurpose : 2;
|
||||
unsigned unused3 :10;
|
||||
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: 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.
|
||||
//0 Not used
|
||||
//1 Receive Status Flag (0=Remote GBA is/was receiving) (Read Only?)
|
||||
@ -66,6 +74,9 @@ public:
|
||||
// Constructor
|
||||
CSIDevice_GBA(int _iDeviceNumber);
|
||||
|
||||
// Destructor
|
||||
~CSIDevice_GBA();
|
||||
|
||||
// Run the SI Buffer
|
||||
virtual int RunBuffer(u8* _pBuffer, int _iLength);
|
||||
|
||||
|
@ -51,6 +51,7 @@ files = ["Console.cpp",
|
||||
"HW/SI.cpp",
|
||||
"HW/SI_Device.cpp",
|
||||
"HW/SI_DeviceGBA.cpp",
|
||||
"HW/GBAPipe.cpp", # TEMPORARY
|
||||
"HW/SI_DeviceGCController.cpp",
|
||||
"HW/StreamADPCM.cpp",
|
||||
"HW/SystemTimers.cpp",
|
||||
|
Loading…
Reference in New Issue
Block a user