Preliminary update to the GameCube to GBA link cable emulation. Fixes Zelda Wind Waker's Tingle Tuner connection, Pac-Man Vs, Final Fantasy: Crystal Chronicles multiplayer, and most other Gamecube to GBA link cable games.

* Changed the SI buffer processing so that transfers do not have to be completed instantly
* Added a second socket at port 49420 (0xc10c) which sends clock information to the GBA slaves
* Handled disconnections from the GBA and GC
* Made the transfers asynchronous
* Blocks the socket before the connection times out

Requires VBA-M SVN 1235 or later.
This commit is contained in:
skidau committed 2015-03-20 12:43:55 +11:00
1 parent 337f89959b
commit c3344eaa88
5 files changed
+353 -77

No files matched your search

+44 -21
View File
@@ -23,8 +23,9 @@ namespace SerialInterface
{
static int changeDevice;
static int et_transfer_pending;
void RunSIBuffer();
void RunSIBuffer(u64 userdata, int cyclesLate);
void UpdateInterrupts();
// SI Interrupt Types
@@ -274,6 +275,7 @@ void Init()
memset(g_SIBuffer, 0, 128);
changeDevice = CoreTiming::RegisterEvent("ChangeSIDevice", ChangeDeviceCallback);
et_transfer_pending = CoreTiming::RegisterEvent("SITransferPending", RunSIBuffer);
}
void Shutdown()
@@ -346,8 +348,18 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
if (tmpComCSR.TCINT) g_ComCSR.TCINT = 0;
// be careful: run si-buffer after updating the INT flags
if (tmpComCSR.TSTART) RunSIBuffer();
UpdateInterrupts();
if (tmpComCSR.TSTART)
{
g_ComCSR.TSTART = 1;
RunSIBuffer(0, 0);
}
else if (g_ComCSR.TSTART)
{
CoreTiming::RemoveEvent(et_transfer_pending);
}
if (!g_ComCSR.TSTART)
UpdateInterrupts();
})
);
@@ -519,29 +531,40 @@ SIDevices GetDeviceType(int channel)
return g_Channel[channel].m_pDevice->GetDeviceType();
}
void RunSIBuffer()
void RunSIBuffer(u64 userdata, int cyclesLate)
{
// Math inLength
int inLength = g_ComCSR.INLNGTH;
if (inLength == 0)
inLength = 128;
else
inLength++;
if (g_ComCSR.TSTART)
{
// Math inLength
int inLength = g_ComCSR.INLNGTH;
if (inLength == 0)
inLength = 128;
else
inLength++;
// Math outLength
int outLength = g_ComCSR.OUTLNGTH;
if (outLength == 0)
outLength = 128;
else
outLength++;
// Math outLength
int outLength = g_ComCSR.OUTLNGTH;
if (outLength == 0)
outLength = 128;
else
outLength++;
int numOutput = g_Channel[g_ComCSR.CHANNEL].m_pDevice->RunBuffer(g_SIBuffer, inLength);
int numOutput = 0;
DEBUG_LOG(SERIALINTERFACE, "RunSIBuffer (intLen: %i outLen: %i) (processed: %i)", inLength, outLength, numOutput);
numOutput = g_Channel[g_ComCSR.CHANNEL].m_pDevice->RunBuffer(g_SIBuffer, inLength);
// Transfer completed
GenerateSIInterrupt(INT_TCINT);
g_ComCSR.TSTART = 0;
DEBUG_LOG(SERIALINTERFACE, "RunSIBuffer chan: %d inLen: %i outLen: %i processed: %i", g_ComCSR.CHANNEL, inLength, outLength, numOutput);
if (numOutput != 0)
{
g_ComCSR.TSTART = 0;
GenerateSIInterrupt(INT_TCINT);
}
else
{
CoreTiming::ScheduleEvent(g_Channel[g_ComCSR.CHANNEL].m_pDevice->TransferInterval() - cyclesLate, et_transfer_pending);
}
}
}
int GetTicksToNextSIPoll()