Expand Up
@@ -17,6 +17,7 @@
#include " SI_Device.h"
#include " SI_DeviceGBA.h"
#include " GBAPipe.h"
// ////////////////////////////////////////////////////////////////////////
// --- GameBoy Advance ---
Expand All
@@ -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)
Expand All
@@ -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[iPosition ^ 3 ]);
iPosition++;
// handle it
switch (command)
// 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 :
{
// 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
*(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 ;
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;
}
Expand All
@@ -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 ;
}
Expand All
@@ -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);
}