Cleaned up GBA cable link (network).

Removed cable link speedhack as it is not needed.
Hard-coded timeouts.
This commit is contained in:
skidau 2015-04-05 07:59:01 +00:00
parent d1bdd8b566
commit d00e850b7b
3 changed files with 129 additions and 170 deletions

View File

@ -4225,6 +4225,10 @@ void CPULoop(int ticks)
} }
} }
#ifndef NO_LINK
if (GetLinkMode() != LINK_DISCONNECTED)
CheckLinkConnection();
#endif
} }
#ifdef TILED_RENDERING #ifdef TILED_RENDERING

View File

@ -34,6 +34,12 @@ const char *MakeInstanceFilename(const char *Input)
#ifndef NO_LINK #ifndef NO_LINK
enum
{
SENDING = false,
RECEIVING = true
};
// The usual min/max functions for built-in types. // The usual min/max functions for built-in types.
// //
// template<typename T> T min( T x, T y ) { return x < y ? x : y; } // template<typename T> T min( T x, T y ) { return x < y ? x : y; }
@ -205,7 +211,7 @@ static int GetSIOMode(u16, u16);
static ConnectionState InitSocket(); static ConnectionState InitSocket();
static void StartCableSocket(u16 siocnt); static void StartCableSocket(u16 siocnt);
static ConnectionState ConnectUpdateSocket(char * const message, size_t size); static ConnectionState ConnectUpdateSocket(char * const message, size_t size);
static void UpdateSocket(int ticks); static void UpdateCableSocket(int ticks);
static void CloseSocket(); static void CloseSocket();
const u64 TICKS_PER_FRAME = 16777216 / 60; const u64 TICKS_PER_FRAME = 16777216 / 60;
@ -332,7 +338,7 @@ static const LinkDriver linkDrivers[] =
{ LINK_RFU_IPC, InitIPC, NULL, StartRFU, UpdateRFUIPC, CloseIPC, false }, { LINK_RFU_IPC, InitIPC, NULL, StartRFU, UpdateRFUIPC, CloseIPC, false },
{ LINK_GAMEBOY, InitIPC, NULL, NULL, NULL, CloseIPC, false }, { LINK_GAMEBOY, InitIPC, NULL, NULL, NULL, CloseIPC, false },
#endif #endif
{ LINK_CABLE_SOCKET, InitSocket, ConnectUpdateSocket, StartCableSocket, UpdateSocket, CloseSocket, true }, { LINK_CABLE_SOCKET, InitSocket, ConnectUpdateSocket, StartCableSocket, UpdateCableSocket, CloseSocket, true },
{ LINK_GAMECUBE_DOLPHIN, JoyBusConnect, NULL, NULL, JoyBusUpdate, JoyBusShutdown, false } { LINK_GAMECUBE_DOLPHIN, JoyBusConnect, NULL, NULL, JoyBusUpdate, JoyBusShutdown, false }
}; };
@ -366,7 +372,6 @@ class lserver{
int counter; int counter;
int done; int done;
public: public:
int howmanytimes;
sf::TcpSocket tcpsocket[4]; sf::TcpSocket tcpsocket[4];
sf::IpAddress udpaddr[4]; sf::IpAddress udpaddr[4];
lserver(void); lserver(void);
@ -385,7 +390,7 @@ class lclient{
public: public:
sf::IpAddress serveraddr; sf::IpAddress serveraddr;
unsigned short serverport; unsigned short serverport;
int numtransfers; bool transferring;
lclient(void); lclient(void);
void Send(void); void Send(void);
void Recv(void); void Recv(void);
@ -398,7 +403,6 @@ static LANLINKDATA lanlink;
static u16 linkdata[4]; static u16 linkdata[4];
static lserver ls; static lserver ls;
static lclient lc; static lclient lc;
static bool oncewait = false, after = false;
// time to end of single GBA's transfer, in 16.78 MHz clock ticks // time to end of single GBA's transfer, in 16.78 MHz clock ticks
// first index is GBA # // first index is GBA #
@ -424,14 +428,14 @@ static const int trtimeend[3][4] = {
// Hodgepodge // Hodgepodge
static u8 tspeed = 3; static u8 tspeed = 3;
static u8 transfer = 0; static bool transfer_direction = false;
static int linkid = 0; static int linkid = 0;
#if (defined __WIN32__ || defined _WIN32) #if (defined __WIN32__ || defined _WIN32)
static HANDLE linksync[4]; static HANDLE linksync[4];
#else #else
static sem_t *linksync[4]; static sem_t *linksync[4];
#endif #endif
static int savedlinktime = 0; static int transfer_start_time_from_master = 0;
#if (defined __WIN32__ || defined _WIN32) #if (defined __WIN32__ || defined _WIN32)
static HANDLE mmf = NULL; static HANDLE mmf = NULL;
#else #else
@ -671,7 +675,7 @@ void LinkUpdate(int ticks)
void CheckLinkConnection() { void CheckLinkConnection() {
if (GetLinkMode() == LINK_CABLE_SOCKET) { if (GetLinkMode() == LINK_CABLE_SOCKET) {
if (linkid && lc.numtransfers == 0) { if (linkid && !lc.transferring) {
lc.CheckConn(); lc.CheckConn();
} }
} }
@ -694,23 +698,13 @@ lserver::lserver(void) {
u16inbuffer = (u16*)inbuffer; u16inbuffer = (u16*)inbuffer;
intoutbuffer = (s32*)outbuffer; intoutbuffer = (s32*)outbuffer;
u16outbuffer = (u16*)outbuffer; u16outbuffer = (u16*)outbuffer;
oncewait = false;
} }
void lserver::Send(void) { void lserver::Send(void) {
if(lanlink.type==0) { // TCP if(lanlink.type==0) { // TCP
if(savedlinktime==-1) {
outbuffer[0] = 4;
outbuffer[1] = -32; //0xe0
for(i=1;i<=lanlink.numslaves;i++) {
tcpsocket[i].send(outbuffer, 4);
size_t nr;
tcpsocket[i].receive(inbuffer, 4, nr);
}
}
outbuffer[1] = tspeed; outbuffer[1] = tspeed;
WRITE16LE(&u16outbuffer[1], linkdata[0]); WRITE16LE(&u16outbuffer[1], linkdata[0]);
WRITE32LE(&intoutbuffer[1], savedlinktime); WRITE32LE(&intoutbuffer[1], transfer_start_time_from_master);
if(lanlink.numslaves==1) { if(lanlink.numslaves==1) {
if(lanlink.type==0) { if(lanlink.type==0) {
outbuffer[0] = 8; outbuffer[0] = 8;
@ -741,26 +735,28 @@ void lserver::Send(void) {
return; return;
} }
// Receive data from all slaves to master
void lserver::Recv(void) { void lserver::Recv(void) {
int numbytes; int numbytes;
if(lanlink.type==0) { // TCP if(lanlink.type==0) { // TCP
fdset.clear(); fdset.clear();
for(i=0;i<lanlink.numslaves;i++) fdset.add(tcpsocket[i+1]);
// was linktimeout/1000 (i.e., drop ms part), but that's wrong for(i=0;i<lanlink.numslaves;i++)
if (fdset.wait(sf::seconds((float)(linktimeout / 1000.))) == 0) fdset.add(tcpsocket[i+1]);
if (fdset.wait(sf::milliseconds(50)) == 0)
{ {
return; return;
} }
howmanytimes++;
for(i=0;i<lanlink.numslaves;i++) { for(i=0;i<lanlink.numslaves;i++) {
numbytes = 0; numbytes = 0;
inbuffer[0] = 1; inbuffer[0] = 1;
while(numbytes<howmanytimes*inbuffer[0]) { while(numbytes<inbuffer[0]) {
size_t nr; size_t nr;
tcpsocket[i+1].receive(inbuffer+numbytes, howmanytimes*inbuffer[0]-numbytes, nr); tcpsocket[i+1].receive(inbuffer+numbytes, inbuffer[0]-numbytes, nr);
numbytes += nr; numbytes += nr;
} }
if(howmanytimes>1) memmove(inbuffer, inbuffer+inbuffer[0]*(howmanytimes-1), inbuffer[0]);
if(inbuffer[1]==-32) { if(inbuffer[1]==-32) {
char message[30]; char message[30];
sprintf(message, _("Player %d disconnected."), i+2); sprintf(message, _("Player %d disconnected."), i+2);
@ -778,9 +774,7 @@ void lserver::Recv(void) {
} }
linkdata[i+1] = READ16LE(&u16inbuffer[1]); linkdata[i+1] = READ16LE(&u16inbuffer[1]);
} }
howmanytimes = 0;
} }
after = false;
return; return;
} }
@ -790,7 +784,7 @@ lclient::lclient(void) {
u16inbuffer = (u16*)inbuffer; u16inbuffer = (u16*)inbuffer;
intoutbuffer = (s32*)outbuffer; intoutbuffer = (s32*)outbuffer;
u16outbuffer = (u16*)outbuffer; u16outbuffer = (u16*)outbuffer;
numtransfers = 0; transferring = false;
return; return;
} }
@ -810,8 +804,8 @@ void lclient::CheckConn(void) {
CloseLink(); CloseLink();
return; return;
} }
numtransfers = 1; transferring = true;
savedlinktime = 0; transfer_start_time_from_master = 0;
linkdata[0] = READ16LE(&u16inbuffer[1]); linkdata[0] = READ16LE(&u16inbuffer[1]);
tspeed = inbuffer[1] & 3; tspeed = inbuffer[1] & 3;
for(i=1, numbytes=4;i<=lanlink.numslaves;i++) for(i=1, numbytes=4;i<=lanlink.numslaves;i++)
@ -819,8 +813,6 @@ void lclient::CheckConn(void) {
linkdata[i] = READ16LE(&u16inbuffer[numbytes]); linkdata[i] = READ16LE(&u16inbuffer[numbytes]);
numbytes++; numbytes++;
} }
after = false;
oncewait = true;
} }
return; return;
} }
@ -830,9 +822,9 @@ void lclient::Recv(void) {
// old code used socket # instead of mask again // old code used socket # instead of mask again
fdset.add(lanlink.tcpsocket); fdset.add(lanlink.tcpsocket);
// old code stripped off ms again // old code stripped off ms again
if (fdset.wait(sf::seconds((float)(linktimeout / 1000.))) == 0) if (fdset.wait(sf::milliseconds(50)) == 0)
{ {
numtransfers = 0; transferring = false;
return; return;
} }
numbytes = 0; numbytes = 0;
@ -851,15 +843,13 @@ void lclient::Recv(void) {
} }
tspeed = inbuffer[1] & 3; tspeed = inbuffer[1] & 3;
linkdata[0] = READ16LE(&u16inbuffer[1]); linkdata[0] = READ16LE(&u16inbuffer[1]);
savedlinktime = (s32)READ32LE(&intinbuffer[1]); transfer_start_time_from_master = (s32)READ32LE(&intinbuffer[1]);
for(i=1, numbytes=4;i<lanlink.numslaves+1;i++) for (i = 1, numbytes = 4; i<lanlink.numslaves + 1; i++) {
if(i!=linkid) { if(i!=linkid) {
linkdata[i] = READ16LE(&u16inbuffer[numbytes]); linkdata[i] = READ16LE(&u16inbuffer[numbytes]);
numbytes++; numbytes++;
} }
numtransfers++; }
if(numtransfers==0) numtransfers = 2;
after = false;
} }
void lclient::Send() { void lclient::Send() {
@ -913,7 +903,7 @@ static ConnectionState ConnectUpdateSocket(char * const message, size_t size) {
sf::SocketSelector fdset; sf::SocketSelector fdset;
fdset.add(lanlink.tcplistener); fdset.add(lanlink.tcplistener);
if (fdset.wait(sf::seconds(0.1f))) { if (fdset.wait(sf::milliseconds(150))) {
int nextSlave = lanlink.connectedSlaves + 1; int nextSlave = lanlink.connectedSlaves + 1;
sf::Socket::Status st = lanlink.tcplistener.accept(ls.tcpsocket[nextSlave]); sf::Socket::Status st = lanlink.tcplistener.accept(ls.tcpsocket[nextSlave]);
@ -981,121 +971,52 @@ static ConnectionState ConnectUpdateSocket(char * const message, size_t size) {
sf::SocketSelector fdset; sf::SocketSelector fdset;
fdset.add(lanlink.tcpsocket); fdset.add(lanlink.tcpsocket);
fdset.wait(sf::seconds(0.1f)); fdset.wait(sf::milliseconds(150));
} }
} }
return newState; return newState;
} }
static void UpdateSocket(int ticks)
{
if (after)
{
if (linkid && linktime > 6044) {
lc.Recv();
oncewait = true;
}
else
return;
}
if (linkid && !transfer && lc.numtransfers > 0 && linktime >= savedlinktime)
{
linkdata[linkid] = READ16LE(&ioMem[COMM_SIODATA8]);
lc.Send();
UPDATE_REG(COMM_SIODATA32_L, linkdata[0]);
UPDATE_REG(COMM_SIOCNT, READ16LE(&ioMem[COMM_SIOCNT]) | 0x80);
transfer = 1;
if (lc.numtransfers==1)
linktime = 0;
else
linktime -= savedlinktime;
}
if (transfer && linktime >= trtimeend[lanlink.numslaves-1][tspeed])
{
if (READ16LE(&ioMem[COMM_SIOCNT]) & 0x4000)
{
IF |= 0x80;
UPDATE_REG(0x202, IF);
}
UPDATE_REG(COMM_SIOCNT, (READ16LE(&ioMem[COMM_SIOCNT]) & 0xff0f) | (linkid << 4));
transfer = 0;
linktime -= trtimeend[lanlink.numslaves-1][tspeed];
oncewait = false;
if (!lanlink.speed)
{
if (linkid)
lc.Recv();
else
ls.Recv(); // WTF is the point of this?
UPDATE_REG(COMM_SIOMULTI1, linkdata[1]);
UPDATE_REG(COMM_SIOMULTI2, linkdata[2]);
UPDATE_REG(COMM_SIOMULTI3, linkdata[3]);
oncewait = true;
} else {
after = true;
if (lanlink.numslaves == 1)
{
UPDATE_REG(COMM_SIOMULTI1, linkdata[1]);
UPDATE_REG(COMM_SIOMULTI2, linkdata[2]);
UPDATE_REG(COMM_SIOMULTI3, linkdata[3]);
}
}
}
}
void StartCableSocket(u16 value) void StartCableSocket(u16 value)
{ {
switch (GetSIOMode(value, READ16LE(&ioMem[COMM_RCNT]))) { switch (GetSIOMode(value, READ16LE(&ioMem[COMM_RCNT]))) {
case MULTIPLAYER: { case MULTIPLAYER: {
bool start = (value & 0x80) && !linkid && !transfer; bool start = (value & 0x80) && !linkid && !transfer_direction;
// clear start, seqno, si (RO on slave, start = pulse on master) // clear start, seqno, si (RO on slave, start = pulse on master)
value &= 0xff4b; value &= 0xff4b;
// get current si. This way, on slaves, it is low during xfer // get current si. This way, on slaves, it is low during xfer
if(linkid) { if(linkid) {
if(!transfer) if(!transfer_direction)
value |= 4; value |= 4;
else else
value |= READ16LE(&ioMem[COMM_SIOCNT]) & 4; value |= READ16LE(&ioMem[COMM_SIOCNT]) & 4;
} }
if (start) { if (start) {
linkdata[0] = READ16LE(&ioMem[COMM_SIODATA8]); linkdata[0] = READ16LE(&ioMem[COMM_SIODATA8]);
savedlinktime = linktime; transfer_start_time_from_master = linktime;
tspeed = value & 3; tspeed = value & 3;
ls.Send(); ls.Send();
transfer = 1; transfer_direction = RECEIVING;
linktime = 0; linktime = 0;
UPDATE_REG(COMM_SIOMULTI0, linkdata[0]); UPDATE_REG(COMM_SIOMULTI0, linkdata[0]);
UPDATE_REG(COMM_SIOMULTI1, 0xffff); UPDATE_REG(COMM_SIOMULTI1, 0xffff);
WRITE32LE(&ioMem[COMM_SIOMULTI2], 0xffffffff); WRITE32LE(&ioMem[COMM_SIOMULTI2], 0xffffffff);
if (lanlink.speed && oncewait == false)
ls.howmanytimes++;
after = false;
value &= ~0x40; value &= ~0x40;
} }
value |= (transfer != 0) << 7; value |= (transfer_direction ? 1 : 0) << 7;
value |= (linkid && !transfer ? 0xc : 8); // set SD (high), SI (low on master) value |= (linkid && !transfer_direction) ? 0x0c : 0x08; // set SD (high), SI (low on master)
value |= linkid << 4; // set seq value |= linkid << 4; // set seq
UPDATE_REG(COMM_SIOCNT, value); UPDATE_REG(COMM_SIOCNT, value);
if (linkid) if (linkid)
// SC low -> transfer in progress // SC low -> transfer in progress
// not sure why SO is low // not sure why SO is low
UPDATE_REG(COMM_RCNT, transfer ? 6 : 7); UPDATE_REG(COMM_RCNT, transfer_direction ? 6 : 7);
else else
// SI is always low on master // SI is always low on master
// SO, SC always low during transfer // SO, SC always low during transfer
// not sure why SO low otherwise // not sure why SO low otherwise
UPDATE_REG(COMM_RCNT, transfer ? 2 : 3); UPDATE_REG(COMM_RCNT, transfer_direction ? 2 : 3);
break; break;
} }
case NORMAL8: case NORMAL8:
@ -1107,6 +1028,49 @@ void StartCableSocket(u16 value)
} }
} }
static void UpdateCableSocket(int ticks)
{
if (linkid && transfer_direction == SENDING && lc.transferring && linktime >= transfer_start_time_from_master)
{
linkdata[linkid] = READ16LE(&ioMem[COMM_SIODATA8]);
lc.Send();
UPDATE_REG(COMM_SIODATA32_L, linkdata[0]);
UPDATE_REG(COMM_SIOCNT, READ16LE(&ioMem[COMM_SIOCNT]) | 0x80);
transfer_direction = RECEIVING;
linktime = 0;
}
if (transfer_direction == RECEIVING && linktime >= trtimeend[lanlink.numslaves-1][tspeed])
{
if (READ16LE(&ioMem[COMM_SIOCNT]) & 0x4000)
{
IF |= 0x80;
UPDATE_REG(0x202, IF);
}
UPDATE_REG(COMM_SIOCNT, (READ16LE(&ioMem[COMM_SIOCNT]) & 0xff0f) | (linkid << 4));
transfer_direction = SENDING;
linktime -= trtimeend[lanlink.numslaves-1][tspeed];
if (linkid)
{
lc.transferring = true;
lc.Recv();
}
else
{
ls.Recv(); // Receive data from all of the slaves
}
UPDATE_REG(COMM_SIOMULTI1, linkdata[1]);
UPDATE_REG(COMM_SIOMULTI2, linkdata[2]);
UPDATE_REG(COMM_SIOMULTI3, linkdata[3]);
}
}
static void CloseSocket() { static void CloseSocket() {
if(linkid) { if(linkid) {
char outbuffer[4]; char outbuffer[4];
@ -1401,12 +1365,12 @@ static void StartCableIPC(u16 value)
{ {
switch (GetSIOMode(value, READ16LE(&ioMem[COMM_RCNT]))) { switch (GetSIOMode(value, READ16LE(&ioMem[COMM_RCNT]))) {
case MULTIPLAYER: { case MULTIPLAYER: {
bool start = (value & 0x80) && !linkid && !transfer; bool start = (value & 0x80) && !linkid && !transfer_direction;
// clear start, seqno, si (RO on slave, start = pulse on master) // clear start, seqno, si (RO on slave, start = pulse on master)
value &= 0xff4b; value &= 0xff4b;
// get current si. This way, on slaves, it is low during xfer // get current si. This way, on slaves, it is low during xfer
if(linkid) { if(linkid) {
if(!transfer) if(!transfer_direction)
value |= 4; value |= 4;
else else
value |= READ16LE(&ioMem[COMM_SIOCNT]) & 4; value |= READ16LE(&ioMem[COMM_SIOCNT]) & 4;
@ -1449,7 +1413,7 @@ static void StartCableIPC(u16 value)
else else
linkmem->numtransfers = numtransfers; linkmem->numtransfers = numtransfers;
transfer = 1; transfer_direction = 1;
linktime = 0; linktime = 0;
tspeed = value & 3; tspeed = value & 3;
WRITE32LE(&ioMem[COMM_SIOMULTI0], 0xffffffff); WRITE32LE(&ioMem[COMM_SIOMULTI0], 0xffffffff);
@ -1459,19 +1423,19 @@ static void StartCableIPC(u16 value)
value |= 0x40; // comm error value |= 0x40; // comm error
} }
} }
value |= (transfer != 0) << 7; value |= (transfer_direction != 0) << 7;
value |= (linkid && !transfer ? 0xc : 8); // set SD (high), SI (low on master) value |= (linkid && !transfer_direction ? 0xc : 8); // set SD (high), SI (low on master)
value |= linkid << 4; // set seq value |= linkid << 4; // set seq
UPDATE_REG(COMM_SIOCNT, value); UPDATE_REG(COMM_SIOCNT, value);
if (linkid) if (linkid)
// SC low -> transfer in progress // SC low -> transfer in progress
// not sure why SO is low // not sure why SO is low
UPDATE_REG(COMM_RCNT, transfer ? 6 : 7); UPDATE_REG(COMM_RCNT, transfer_direction ? 6 : 7);
else else
// SI is always low on master // SI is always low on master
// SO, SC always low during transfer // SO, SC always low during transfer
// not sure why SO low otherwise // not sure why SO low otherwise
UPDATE_REG(COMM_RCNT, transfer ? 2 : 3); UPDATE_REG(COMM_RCNT, transfer_direction ? 2 : 3);
break; break;
} }
case NORMAL8: case NORMAL8:
@ -1507,13 +1471,13 @@ static void UpdateCableIPC(int ticks)
// and syncing clock with master (after first transfer) // and syncing clock with master (after first transfer)
// this will fail if > ~2 minutes have passed since last transfer due // this will fail if > ~2 minutes have passed since last transfer due
// to integer overflow // to integer overflow
if(!transfer && numtransfers && linktime < 0) { if(!transfer_direction && numtransfers && linktime < 0) {
linktime = 0; linktime = 0;
// there is a very, very, small chance that this will abort // there is a very, very, small chance that this will abort
// a transfer that was just started // a transfer that was just started
linkmem->numtransfers = numtransfers = 0; linkmem->numtransfers = numtransfers = 0;
} }
if (linkid && !transfer && linktime >= linkmem->lastlinktime && if (linkid && !transfer_direction && linktime >= linkmem->lastlinktime &&
linkmem->numtransfers != numtransfers) linkmem->numtransfers != numtransfers)
{ {
numtransfers = linkmem->numtransfers; numtransfers = linkmem->numtransfers;
@ -1523,7 +1487,7 @@ static void UpdateCableIPC(int ticks)
// if this or any previous machine was dropped, no transfer // if this or any previous machine was dropped, no transfer
// can take place // can take place
if(linkmem->trgbas <= linkid) { if(linkmem->trgbas <= linkid) {
transfer = 0; transfer_direction = 0;
numtransfers = 0; numtransfers = 0;
// if this is the one that was dropped, reconnect // if this is the one that was dropped, reconnect
if(!(linkmem->linkflags & (1 << linkid))) if(!(linkmem->linkflags & (1 << linkid)))
@ -1545,7 +1509,7 @@ static void UpdateCableIPC(int ticks)
case 'M': case 'M':
#endif #endif
tspeed = linkmem->linkcmd[0] & 3; tspeed = linkmem->linkcmd[0] & 3;
transfer = 1; transfer_direction = 1;
WRITE32LE(&ioMem[COMM_SIOMULTI0], 0xffffffff); WRITE32LE(&ioMem[COMM_SIOMULTI0], 0xffffffff);
WRITE32LE(&ioMem[COMM_SIOMULTI2], 0xffffffff); WRITE32LE(&ioMem[COMM_SIOMULTI2], 0xffffffff);
UPDATE_REG(COMM_SIOCNT, READ16LE(&ioMem[COMM_SIOCNT]) & ~0x40 | 0x80); UPDATE_REG(COMM_SIOCNT, READ16LE(&ioMem[COMM_SIOCNT]) & ~0x40 | 0x80);
@ -1555,39 +1519,39 @@ static void UpdateCableIPC(int ticks)
#endif #endif
} }
if (!transfer) if (!transfer_direction)
return; return;
if (transfer <= linkmem->trgbas && linktime >= trtimedata[transfer-1][tspeed]) if (transfer_direction <= linkmem->trgbas && linktime >= trtimedata[transfer_direction-1][tspeed])
{ {
// transfer #n -> wait for value n - 1 // transfer #n -> wait for value n - 1
if(transfer > 1 && linkid != transfer - 1) { if(transfer_direction > 1 && linkid != transfer_direction - 1) {
if(WaitForSingleObject(linksync[transfer - 1], linktimeout) == WAIT_TIMEOUT) { if(WaitForSingleObject(linksync[transfer_direction - 1], linktimeout) == WAIT_TIMEOUT) {
// assume slave has dropped off if timed out // assume slave has dropped off if timed out
if(!linkid) { if(!linkid) {
linkmem->trgbas = transfer - 1; linkmem->trgbas = transfer_direction - 1;
int f = linkmem->linkflags; int f = linkmem->linkflags;
f &= ~(1 << (transfer - 1)); f &= ~(1 << (transfer_direction - 1));
linkmem->linkflags = f; linkmem->linkflags = f;
if(f < (1 << transfer) - 1) if(f < (1 << transfer_direction) - 1)
linkmem->numgbas = transfer - 1; linkmem->numgbas = transfer_direction - 1;
char message[30]; char message[30];
sprintf(message, _("Player %d disconnected."), transfer - 1); sprintf(message, _("Player %d disconnected."), transfer_direction - 1);
systemScreenMessage(message); systemScreenMessage(message);
} }
transfer = linkmem->trgbas + 1; transfer_direction = linkmem->trgbas + 1;
// next cycle, transfer will finish up // next cycle, transfer will finish up
return; return;
} }
} }
// now that value is available, store it // now that value is available, store it
UPDATE_REG((COMM_SIOMULTI0 - 2) + (transfer<<1), linkmem->linkdata[transfer-1]); UPDATE_REG((COMM_SIOMULTI0 - 2) + (transfer_direction<<1), linkmem->linkdata[transfer_direction-1]);
// transfer machine's value at start of its transfer cycle // transfer machine's value at start of its transfer cycle
if(linkid == transfer) { if(linkid == transfer_direction) {
// skip if dropped // skip if dropped
if(linkmem->trgbas <= linkid) { if(linkmem->trgbas <= linkid) {
transfer = 0; transfer_direction = 0;
numtransfers = 0; numtransfers = 0;
// if this is the one that was dropped, reconnect // if this is the one that was dropped, reconnect
if(!(linkmem->linkflags & (1 << linkid))) if(!(linkmem->linkflags & (1 << linkid)))
@ -1600,23 +1564,23 @@ static void UpdateCableIPC(int ticks)
linkmem->linkdata[linkid] = READ16LE(&ioMem[COMM_SIODATA8]); linkmem->linkdata[linkid] = READ16LE(&ioMem[COMM_SIODATA8]);
ReleaseSemaphore(linksync[linkid], linkmem->numgbas-1, NULL); ReleaseSemaphore(linksync[linkid], linkmem->numgbas-1, NULL);
} }
if(linkid == transfer - 1) { if(linkid == transfer_direction - 1) {
// SO becomes low to begin next trasnfer // SO becomes low to begin next trasnfer
// may need to set DDR as well // may need to set DDR as well
UPDATE_REG(COMM_RCNT, 0x22); UPDATE_REG(COMM_RCNT, 0x22);
} }
// next cycle // next cycle
transfer++; transfer_direction++;
} }
if (transfer > linkmem->trgbas && linktime >= trtimeend[transfer-3][tspeed]) if (transfer_direction > linkmem->trgbas && linktime >= trtimeend[transfer_direction-3][tspeed])
{ {
// wait for slaves to finish // wait for slaves to finish
// this keeps unfinished slaves from screwing up last xfer // this keeps unfinished slaves from screwing up last xfer
// not strictly necessary; may just slow things down // not strictly necessary; may just slow things down
if(!linkid) { if(!linkid) {
for(int i = 2; i < transfer; i++) for(int i = 2; i < transfer_direction; i++)
if(WaitForSingleObject(linksync[0], linktimeout) == WAIT_TIMEOUT) { if(WaitForSingleObject(linksync[0], linktimeout) == WAIT_TIMEOUT) {
// impossible to determine which slave died // impossible to determine which slave died
// so leave them alone for now // so leave them alone for now
@ -1627,8 +1591,8 @@ static void UpdateCableIPC(int ticks)
} else if(linkmem->trgbas > linkid) } else if(linkmem->trgbas > linkid)
// signal master that this slave is finished // signal master that this slave is finished
ReleaseSemaphore(linksync[0], 1, NULL); ReleaseSemaphore(linksync[0], 1, NULL);
linktime -= trtimeend[transfer - 3][tspeed]; linktime -= trtimeend[transfer_direction - 3][tspeed];
transfer = 0; transfer_direction = 0;
u16 value = READ16LE(&ioMem[COMM_SIOCNT]); u16 value = READ16LE(&ioMem[COMM_SIOCNT]);
if(!linkid) if(!linkid)
value |= 4; // SI becomes high on slaves after xfer value |= 4; // SI becomes high on slaves after xfer
@ -1671,15 +1635,11 @@ static void StartRFU(u16 value)
} }
value &= 0xff7f; //Start bit.7 reset //may cause the game to retry sending again value &= 0xff7f; //Start bit.7 reset //may cause the game to retry sending again
//value |= 0x0008; //SO bit.3 set automatically upon transfer completion //value |= 0x0008; //SO bit.3 set automatically upon transfer completion
transfer = 0; transfer_direction = 0;
} }
return; return;
} }
if (!linkid && ls.howmanytimes>0) { //may not be needed? //Server, if previous data exchange not done yet don't initiate anymore data exchange
UPDATE_REG(COMM_SIOCNT, value);
return;
}
linktimeout = 1; linktimeout = 1;
@ -1695,7 +1655,7 @@ static void StartRFU(u16 value)
break; break;
case NORMAL32: case NORMAL32:
//don't do anything if previous cmd aren't sent yet, may fix Boktai2 Not Detecting wireless adapter //don't do anything if previous cmd aren't sent yet, may fix Boktai2 Not Detecting wireless adapter
if (transfer) if (transfer_direction)
{ {
UPDATE_REG(COMM_SIOCNT, value); UPDATE_REG(COMM_SIOCNT, value);
return; return;
@ -2587,7 +2547,7 @@ static void StartRFU(u16 value)
} }
break; break;
} }
transfer = 1; transfer_direction = 1;
PrevVAL = value; PrevVAL = value;
PrevDAT = CurDAT; PrevDAT = CurDAT;
@ -2619,7 +2579,7 @@ bool LinkRFUUpdate()
//if (IsLinkConnected()) { //if (IsLinkConnected()) {
//} //}
if (rfu_enabled) { if (rfu_enabled) {
if (transfer&&rfu_transfer_end <= 0) if (transfer_direction&&rfu_transfer_end <= 0)
{ {
if (rfu_waiting) { if (rfu_waiting) {
bool ok = false; bool ok = false;
@ -2690,9 +2650,9 @@ static void UpdateRFUIPC(int ticks)
if (LinkRFUUpdate()) if (LinkRFUUpdate())
{ {
if (transfer && rfu_transfer_end <= 0) if (transfer_direction && rfu_transfer_end <= 0)
{ {
transfer = 0; transfer_direction = 0;
u16 value = READ16LE(&ioMem[COMM_SIOCNT]); u16 value = READ16LE(&ioMem[COMM_SIOCNT]);
if (value & 0x4000) if (value & 0x4000)
{ {

View File

@ -1343,11 +1343,6 @@ BOOL VBA::OnIdle(LONG lCount)
if (!debugger) if (!debugger)
emulator.emuMain(emulator.emuCount); emulator.emuMain(emulator.emuCount);
#ifndef NO_LINK
if (GetLinkMode() != LINK_DISCONNECTED)
CheckLinkConnection();
#endif
if(rewindSaveNeeded && rewindMemory && emulator.emuWriteMemState) { if(rewindSaveNeeded && rewindMemory && emulator.emuWriteMemState) {
rewindCount++; rewindCount++;
if(rewindCount > 8) if(rewindCount > 8)