Ported AdamN's Game Link (Game Boy link) code from 1030e.
Seems to work better with a link timeout of 1. git-svn-id: https://svn.code.sf.net/p/vbam/code/trunk@1242 a31d4220-a93d-0410-bf67-fe4944624d44
This commit is contained in:
parent
1ca9a52821
commit
cc0101622a
|
@ -14,6 +14,7 @@
|
||||||
#include "gbSGB.h"
|
#include "gbSGB.h"
|
||||||
#include "gbSound.h"
|
#include "gbSound.h"
|
||||||
#include "../Util.h"
|
#include "../Util.h"
|
||||||
|
#include "../gba/GBALink.h"
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#define _stricmp strcasecmp
|
#define _stricmp strcasecmp
|
||||||
|
@ -801,9 +802,29 @@ void gbWriteMemory(register u16 address, register u8 value)
|
||||||
// serial control
|
// serial control
|
||||||
case 0x02: {
|
case 0x02: {
|
||||||
gbSerialOn = (value & 0x80);
|
gbSerialOn = (value & 0x80);
|
||||||
|
#ifndef NO_LINK
|
||||||
|
if (EmuReseted || (gbMemory[0xff02] & 0x7c) || (value & 0x7c) || (!(value & 0x81))) { //trying to detect whether the game has exited multiplay mode, pokemon blue start w/ 0x7e while pocket racing start w/ 0x7c
|
||||||
|
LinkFirstTime = true;
|
||||||
|
}
|
||||||
|
EmuReseted = false;
|
||||||
gbMemory[0xff02] = value;
|
gbMemory[0xff02] = value;
|
||||||
if (gbSerialOn) {
|
if (gbSerialOn) {
|
||||||
gbSerialTicks = GBSERIAL_CLOCK_TICKS;
|
gbSerialTicks = GBSERIAL_CLOCK_TICKS;
|
||||||
|
|
||||||
|
LinkIsWaiting = true;
|
||||||
|
|
||||||
|
//Do data exchange, master initiate the transfer
|
||||||
|
//may cause visual artifact if not processed immediately, is it due to IRQ stuff or invalid data being exchanged?
|
||||||
|
if ((value & 1) ) { //internal clock
|
||||||
|
if (gbSerialFunction) {
|
||||||
|
gbSIO_SC = value;
|
||||||
|
gbMemory[0xff01] = gbSerialFunction(gbMemory[0xff01]); //gbSerialFunction/gbStartLink/gbPrinter
|
||||||
|
}
|
||||||
|
else gbMemory[0xff01] = 0xff;
|
||||||
|
gbMemory[0xff02] &= 0x7f;
|
||||||
|
gbSerialOn = 0;
|
||||||
|
gbMemory[0xff0f] = register_IF |= 8;
|
||||||
|
}
|
||||||
#ifdef OLD_GB_LINK
|
#ifdef OLD_GB_LINK
|
||||||
if (linkConnected) {
|
if (linkConnected) {
|
||||||
if (value & 1) {
|
if (value & 1) {
|
||||||
|
@ -816,6 +837,7 @@ void gbWriteMemory(register u16 address, register u8 value)
|
||||||
|
|
||||||
gbSerialBits = 0;
|
gbSerialBits = 0;
|
||||||
return;
|
return;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x04: {
|
case 0x04: {
|
||||||
|
@ -2178,6 +2200,11 @@ void gbGetHardwareType()
|
||||||
|
|
||||||
void gbReset()
|
void gbReset()
|
||||||
{
|
{
|
||||||
|
#ifndef NO_LINK
|
||||||
|
EmuReseted = true;
|
||||||
|
gbLinkReset();
|
||||||
|
#endif
|
||||||
|
|
||||||
gbGetHardwareType();
|
gbGetHardwareType();
|
||||||
|
|
||||||
oldRegister_WY = 146;
|
oldRegister_WY = 146;
|
||||||
|
@ -5221,8 +5248,13 @@ void gbEmulate(int ticksToStop)
|
||||||
|
|
||||||
gbMemory[0xff41] = register_STAT;
|
gbMemory[0xff41] = register_STAT;
|
||||||
|
|
||||||
|
#ifndef NO_LINK
|
||||||
// serial emulation
|
// serial emulation
|
||||||
if(gbSerialOn) {
|
gbSerialOn = (gbMemory[0xff02] & 0x80);
|
||||||
|
static int SIOctr = 0;
|
||||||
|
SIOctr++;
|
||||||
|
if (SIOctr % 5)
|
||||||
|
if (gbSerialOn) { //Transfer Started
|
||||||
#ifdef OLD_GB_LINK
|
#ifdef OLD_GB_LINK
|
||||||
if (linkConnected) {
|
if (linkConnected) {
|
||||||
gbSerialTicks -= clockTicks;
|
gbSerialTicks -= clockTicks;
|
||||||
|
@ -5243,9 +5275,10 @@ void gbEmulate(int ticksToStop)
|
||||||
}
|
}
|
||||||
gbSerialTicks += GBSERIAL_CLOCK_TICKS;
|
gbSerialTicks += GBSERIAL_CLOCK_TICKS;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
#endif
|
#endif
|
||||||
if(gbMemory[0xff02] & 1) {
|
if (gbMemory[0xff02] & 1) { //internal clocks (master)
|
||||||
gbSerialTicks -= clockTicks;
|
gbSerialTicks -= clockTicks;
|
||||||
|
|
||||||
// overflow
|
// overflow
|
||||||
|
@ -5254,18 +5287,53 @@ void gbEmulate(int ticksToStop)
|
||||||
// gbMemory[0xff01] = 0x80 | (gbMemory[0xff01]>>1);
|
// gbMemory[0xff01] = 0x80 | (gbMemory[0xff01]>>1);
|
||||||
// increment number of shifted bits
|
// increment number of shifted bits
|
||||||
gbSerialBits++;
|
gbSerialBits++;
|
||||||
if(gbSerialBits == 8) {
|
if (gbSerialBits >= 8) {
|
||||||
// end of transmission
|
// end of transmission
|
||||||
if(gbSerialFunction) // external device
|
|
||||||
gbMemory[0xff01] = gbSerialFunction(gbMemory[0xff01]);
|
|
||||||
else
|
|
||||||
gbMemory[0xff01] = 0xff;
|
|
||||||
gbSerialTicks = 0;
|
gbSerialTicks = 0;
|
||||||
|
gbSerialBits = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gbSerialTicks += GBSERIAL_CLOCK_TICKS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //external clocks (slave)
|
||||||
|
{
|
||||||
|
gbSerialTicks -= clockTicks;
|
||||||
|
|
||||||
|
// overflow
|
||||||
|
while (gbSerialTicks <= 0) {
|
||||||
|
// shift serial byte to right and put a 1 bit in its place
|
||||||
|
// gbMemory[0xff01] = 0x80 | (gbMemory[0xff01]>>1);
|
||||||
|
// increment number of shifted bits
|
||||||
|
gbSerialBits++;
|
||||||
|
if (gbSerialBits >= 8) {
|
||||||
|
// end of transmission
|
||||||
|
u16 dat = 0;
|
||||||
|
if (LinkIsWaiting)
|
||||||
|
if (gbSerialFunction) { // external device
|
||||||
|
gbSIO_SC = gbMemory[0xff02];
|
||||||
|
if (!LinkFirstTime)
|
||||||
|
{
|
||||||
|
dat = (gbSerialFunction(gbMemory[0xff01]) << 8) | 1;
|
||||||
|
}
|
||||||
|
else //external clock not suppose to start a transfer, but there are time where both side using external clock and couldn't communicate properly
|
||||||
|
{
|
||||||
|
if (gbMemory)
|
||||||
|
gbSerialOn = (gbMemory[0xff02] & 0x80);
|
||||||
|
dat = gbLinkUpdate(gbMemory[0xff01], gbSerialOn);
|
||||||
|
}
|
||||||
|
gbMemory[0xff01] = (dat >> 8);
|
||||||
|
} //else
|
||||||
|
gbSerialTicks = 0;
|
||||||
|
if ((dat & 1) && (gbMemory[0xff02] & 0x80)) //(dat & 1)==1 when reply data received
|
||||||
|
{
|
||||||
gbMemory[0xff02] &= 0x7f;
|
gbMemory[0xff02] &= 0x7f;
|
||||||
gbSerialOn = 0;
|
gbSerialOn = 0;
|
||||||
gbMemory[0xff0f] = register_IF |= 8;
|
gbMemory[0xff0f] = register_IF |= 8;
|
||||||
|
}
|
||||||
gbSerialBits = 0;
|
gbSerialBits = 0;
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
gbSerialTicks += GBSERIAL_CLOCK_TICKS;
|
gbSerialTicks += GBSERIAL_CLOCK_TICKS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5273,7 +5341,7 @@ void gbEmulate(int ticksToStop)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
soundTicks -= clockTicks;
|
soundTicks -= clockTicks;
|
||||||
if ( !gbSpeed )
|
if ( !gbSpeed )
|
||||||
|
|
|
@ -244,7 +244,8 @@ static const LinkDriver linkDrivers[] =
|
||||||
{ LINK_CABLE_IPC, InitIPC, NULL, StartCableIPC, UpdateCableIPC, CloseIPC },
|
{ LINK_CABLE_IPC, InitIPC, NULL, StartCableIPC, UpdateCableIPC, CloseIPC },
|
||||||
{ LINK_CABLE_SOCKET, InitSocket, ConnectUpdateSocket, StartCableSocket, UpdateSocket, CloseSocket },
|
{ LINK_CABLE_SOCKET, InitSocket, ConnectUpdateSocket, StartCableSocket, UpdateSocket, CloseSocket },
|
||||||
{ LINK_RFU_IPC, InitIPC, NULL, StartRFU, UpdateRFUIPC, CloseIPC },
|
{ LINK_RFU_IPC, InitIPC, NULL, StartRFU, UpdateRFUIPC, CloseIPC },
|
||||||
{ LINK_GAMECUBE_DOLPHIN, JoyBusConnect, NULL, NULL, JoyBusUpdate, JoyBusShutdown }
|
{ LINK_GAMECUBE_DOLPHIN, JoyBusConnect, NULL, NULL, JoyBusUpdate, JoyBusShutdown },
|
||||||
|
{ LINK_GAMEBOY, InitIPC, NULL, NULL, NULL, CloseIPC }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -435,6 +436,11 @@ static const int trtimeend[3][4] = {
|
||||||
|
|
||||||
static int GetSIOMode(u16, u16);
|
static int GetSIOMode(u16, u16);
|
||||||
|
|
||||||
|
u8 gbSIO_SC = 0;
|
||||||
|
bool LinkIsWaiting = false;
|
||||||
|
bool LinkFirstTime = true;
|
||||||
|
bool EmuReseted = true;
|
||||||
|
|
||||||
// The GBA wireless RFU (see adapter3.txt)
|
// The GBA wireless RFU (see adapter3.txt)
|
||||||
static void StartRFU(u16 value)
|
static void StartRFU(u16 value)
|
||||||
{
|
{
|
||||||
|
@ -1906,7 +1912,7 @@ bool LinkRFUUpdate()
|
||||||
|
|
||||||
if (((rfu_cmd == 0x11 || rfu_cmd == 0x1a || rfu_cmd == 0x26) && (GetTickCount() - rfu_lasttime) < 16) ||
|
if (((rfu_cmd == 0x11 || rfu_cmd == 0x1a || rfu_cmd == 0x26) && (GetTickCount() - rfu_lasttime) < 16) ||
|
||||||
((rfu_cmd == 0xa5 || rfu_cmd == 0xb5) && (GetTickCount() - rfu_lasttime) < 16) ||
|
((rfu_cmd == 0xa5 || rfu_cmd == 0xb5) && (GetTickCount() - rfu_lasttime) < 16) ||
|
||||||
((rfu_cmd == 0xa7 || rfu_cmd == 0xb7) && (GetTickCount() - rfu_lasttime) < linktimeout))
|
((rfu_cmd == 0xa7 || rfu_cmd == 0xb7) && (GetTickCount() - rfu_lasttime) < (DWORD)linktimeout))
|
||||||
{
|
{
|
||||||
//c_s.Lock();
|
//c_s.Lock();
|
||||||
ok = (linkmem->rfu_listfront[vbaid] != linkmem->rfu_listback[vbaid]);
|
ok = (linkmem->rfu_listfront[vbaid] != linkmem->rfu_listback[vbaid]);
|
||||||
|
@ -2691,6 +2697,110 @@ void lclient::Send() {
|
||||||
lanlink.tcpsocket.Send(outbuffer, 4);
|
lanlink.tcpsocket.Send(outbuffer, 4);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void gbLinkReset()
|
||||||
|
{
|
||||||
|
LinkIsWaiting = false;
|
||||||
|
LinkFirstTime = true;
|
||||||
|
linkmem->linkcmd[linkid] = 0;
|
||||||
|
linkmem->linkdata[linkid] = 0xff;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 gbStartLink(u8 b) //used on internal clock
|
||||||
|
{
|
||||||
|
u8 dat = 0xff; //master (w/ internal clock) will gets 0xff if slave is turned off (or not ready yet also?)
|
||||||
|
//if(linkid) return 0xff; //b; //Slave shouldn't be sending from here
|
||||||
|
BOOL sent = false;
|
||||||
|
//int gbSerialOn = (gbMemory[0xff02] & 0x80); //not needed?
|
||||||
|
gba_link_enabled = true; //(gbMemory[0xff02]!=0); //not needed?
|
||||||
|
rfu_enabled = false;
|
||||||
|
|
||||||
|
if (!gba_link_enabled) return 0xff;
|
||||||
|
|
||||||
|
//Single Computer
|
||||||
|
if (!lanlink.active)
|
||||||
|
{
|
||||||
|
u32 tm = GetTickCount();
|
||||||
|
do {
|
||||||
|
WaitForSingleObject(linksync[linkid], 1);
|
||||||
|
ResetEvent(linksync[linkid]);
|
||||||
|
} while (linkmem->linkcmd[linkid] && (GetTickCount() - tm)<(u32)linktimeout);
|
||||||
|
linkmem->linkdata[linkid] = b;
|
||||||
|
linkmem->linkcmd[linkid] = 1;
|
||||||
|
SetEvent(linksync[linkid]);
|
||||||
|
|
||||||
|
LinkIsWaiting = false;
|
||||||
|
tm = GetTickCount();
|
||||||
|
do {
|
||||||
|
WaitForSingleObject(linksync[1 - linkid], 1);
|
||||||
|
ResetEvent(linksync[1 - linkid]);
|
||||||
|
} while (!linkmem->linkcmd[1 - linkid] && (GetTickCount() - tm)<(u32)linktimeout);
|
||||||
|
if (linkmem->linkcmd[1 - linkid]) {
|
||||||
|
dat = (u8)linkmem->linkdata[1 - linkid];
|
||||||
|
linkmem->linkcmd[1 - linkid] = 0;
|
||||||
|
} //else LinkIsWaiting = true;
|
||||||
|
SetEvent(linksync[1 - linkid]);
|
||||||
|
|
||||||
|
LinkFirstTime = true;
|
||||||
|
if (dat != 0xff/*||b==0x00||dat==0x00*/)
|
||||||
|
LinkFirstTime = false;
|
||||||
|
|
||||||
|
return dat;
|
||||||
|
}
|
||||||
|
return dat;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 gbLinkUpdate(u8 b, int gbSerialOn) //used on external clock
|
||||||
|
{
|
||||||
|
u8 dat = b; //0xff; //slave (w/ external clocks) won't be getting 0xff if master turned off
|
||||||
|
BOOL recvd = false;
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
gba_link_enabled = true; //(gbMemory[0xff02]!=0);
|
||||||
|
rfu_enabled = false;
|
||||||
|
|
||||||
|
if (gbSerialOn) {
|
||||||
|
if (gba_link_enabled)
|
||||||
|
//Single Computer
|
||||||
|
if (!lanlink.active)
|
||||||
|
{
|
||||||
|
u32 tm;// = GetTickCount();
|
||||||
|
//do {
|
||||||
|
WaitForSingleObject(linksync[1 - linkid], linktimeout);
|
||||||
|
ResetEvent(linksync[1 - linkid]);
|
||||||
|
//} while (!linkmem->linkcmd[1-linkid] && (GetTickCount()-tm)<(u32)linktimeout);
|
||||||
|
if (linkmem->linkcmd[1 - linkid]) {
|
||||||
|
dat = (u8)linkmem->linkdata[1 - linkid];
|
||||||
|
linkmem->linkcmd[1 - linkid] = 0;
|
||||||
|
recvd = true;
|
||||||
|
LinkIsWaiting = false;
|
||||||
|
}
|
||||||
|
else LinkIsWaiting = true;
|
||||||
|
SetEvent(linksync[1 - linkid]);
|
||||||
|
|
||||||
|
if (!LinkIsWaiting) {
|
||||||
|
tm = GetTickCount();
|
||||||
|
do {
|
||||||
|
WaitForSingleObject(linksync[linkid], 1);
|
||||||
|
ResetEvent(linksync[linkid]);
|
||||||
|
} while (linkmem->linkcmd[1 - linkid] && (GetTickCount() - tm)<(u32)linktimeout);
|
||||||
|
if (!linkmem->linkcmd[linkid]) {
|
||||||
|
linkmem->linkdata[linkid] = b;
|
||||||
|
linkmem->linkcmd[linkid] = 1;
|
||||||
|
}
|
||||||
|
SetEvent(linksync[linkid]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dat == 0xff/*||dat==0x00||b==0x00*/) //dat==0xff||dat==0x00
|
||||||
|
LinkFirstTime = true;
|
||||||
|
}
|
||||||
|
return ((dat << 8) | (recvd & (u8)0xff));
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
bool gba_joybus_active = false;
|
bool gba_joybus_active = false;
|
||||||
#endif
|
#endif
|
|
@ -10,7 +10,8 @@ enum LinkMode
|
||||||
LINK_CABLE_IPC,
|
LINK_CABLE_IPC,
|
||||||
LINK_CABLE_SOCKET,
|
LINK_CABLE_SOCKET,
|
||||||
LINK_RFU_IPC,
|
LINK_RFU_IPC,
|
||||||
LINK_GAMECUBE_DOLPHIN
|
LINK_GAMECUBE_DOLPHIN,
|
||||||
|
LINK_GAMEBOY
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -193,4 +194,12 @@ typedef struct {
|
||||||
u32 data[255];
|
u32 data[255];
|
||||||
} rfu_datarec;
|
} rfu_datarec;
|
||||||
|
|
||||||
|
extern u8 gbSIO_SC;
|
||||||
|
extern bool LinkIsWaiting;
|
||||||
|
extern bool LinkFirstTime;
|
||||||
|
extern bool EmuReseted;
|
||||||
|
extern void gbLinkReset();
|
||||||
|
extern u8 gbStartLink(u8 b);
|
||||||
|
extern u16 gbLinkUpdate(u8 b, int gbSerialOn);
|
||||||
|
|
||||||
#endif /* GBA_GBALINK_H */
|
#endif /* GBA_GBALINK_H */
|
||||||
|
|
|
@ -73,6 +73,7 @@ BOOL LinkOptions::OnInitDialog(){
|
||||||
AddMode("Cable - Network", LINK_CABLE_SOCKET);
|
AddMode("Cable - Network", LINK_CABLE_SOCKET);
|
||||||
AddMode("GameCube - Dolphin", LINK_GAMECUBE_DOLPHIN);
|
AddMode("GameCube - Dolphin", LINK_GAMECUBE_DOLPHIN);
|
||||||
AddMode("Wireless adapter - Single Computer", LINK_RFU_IPC);
|
AddMode("Wireless adapter - Single Computer", LINK_RFU_IPC);
|
||||||
|
AddMode("Game Link (Game Boy) - Single Computer", LINK_GAMEBOY);
|
||||||
|
|
||||||
sprintf(timeout, "%d", theApp.linkTimeout);
|
sprintf(timeout, "%d", theApp.linkTimeout);
|
||||||
|
|
||||||
|
|
|
@ -1024,7 +1024,11 @@ void MainWnd::OnOptionsGameboyPrinter()
|
||||||
if(theApp.winGbPrinterEnabled)
|
if(theApp.winGbPrinterEnabled)
|
||||||
gbSerialFunction = gbPrinterSend;
|
gbSerialFunction = gbPrinterSend;
|
||||||
else
|
else
|
||||||
|
#ifndef NO_LINK
|
||||||
|
gbSerialFunction = gbStartLink;
|
||||||
|
#else
|
||||||
gbSerialFunction = NULL;
|
gbSerialFunction = NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWnd::OnUpdateOptionsGameboyPrinter(CCmdUI* pCmdUI)
|
void MainWnd::OnUpdateOptionsGameboyPrinter(CCmdUI* pCmdUI)
|
||||||
|
|
|
@ -1567,7 +1567,11 @@ void VBA::loadSettings()
|
||||||
if(winGbPrinterEnabled)
|
if(winGbPrinterEnabled)
|
||||||
gbSerialFunction = gbPrinterSend;
|
gbSerialFunction = gbPrinterSend;
|
||||||
else
|
else
|
||||||
|
#ifndef NO_LINK
|
||||||
|
gbSerialFunction = gbStartLink;
|
||||||
|
#else
|
||||||
gbSerialFunction = NULL;
|
gbSerialFunction = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
pauseWhenInactive = regQueryDwordValue("pauseWhenInactive", 1) ?
|
pauseWhenInactive = regQueryDwordValue("pauseWhenInactive", 1) ?
|
||||||
true : false;
|
true : false;
|
||||||
|
|
Loading…
Reference in New Issue