ipx-update (h-a-l-9000)
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@2291
This commit is contained in:
parent
147e30b948
commit
2428a80321
1 changed files with 167 additions and 289 deletions
|
@ -16,7 +16,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: ipx.cpp,v 1.7 2005-07-30 10:02:39 qbix79 Exp $ */
|
||||
/* $Id: ipx.cpp,v 1.8 2005-08-26 19:16:20 c2woody Exp $ */
|
||||
|
||||
#include "dosbox.h"
|
||||
|
||||
|
@ -28,7 +28,6 @@
|
|||
#include "cross.h"
|
||||
#include "support.h"
|
||||
#include "cpu.h"
|
||||
#include "SDL_net.h"
|
||||
#include "regs.h"
|
||||
#include "inout.h"
|
||||
#include "setup.h"
|
||||
|
@ -45,20 +44,16 @@
|
|||
|
||||
#define SOCKTABLESIZE 150 // DOS IPX driver was limited to 150 open sockets
|
||||
|
||||
|
||||
struct ipxnetaddr {
|
||||
Uint8 netnum[4]; // Both are big endian
|
||||
Uint8 netnode[6];
|
||||
} localIpxAddr;
|
||||
|
||||
|
||||
|
||||
Bit32u tcpPort;
|
||||
bool isIpxServer;
|
||||
bool isIpxConnected;
|
||||
IPaddress ipxClientIp; // IPAddress for client connection to server
|
||||
IPaddress ipxServConnIp; // IPAddress for client connection to server
|
||||
//TCPsocket ipxTCPClientSocket;
|
||||
UDPsocket ipxClientSocket;
|
||||
int UDPChannel; // Channel used by UDP connection
|
||||
Bit8u recvBuffer[IPXBUFFERSIZE]; // Incoming packet buffer
|
||||
|
@ -67,10 +62,11 @@ static RealPt ipx_callback;
|
|||
|
||||
SDLNet_SocketSet clientSocketSet;
|
||||
|
||||
static bool ESRnotificationRequired = false;
|
||||
|
||||
packetBuffer incomingPacket;
|
||||
|
||||
static Bit16u socketCount;
|
||||
static Bit16u opensockets[SOCKTABLESIZE];
|
||||
|
||||
static Bit16u swapByte(Bit16u sockNum) {
|
||||
return (((sockNum>> 8)) | (sockNum << 8));
|
||||
}
|
||||
|
@ -166,7 +162,6 @@ RealPt ECBClass::getESRAddr(void) {
|
|||
|
||||
void ECBClass::NotifyESR(void) {
|
||||
Bit32u ESRval = real_readd(RealSeg(ECBAddr), RealOff(ECBAddr)+4);
|
||||
|
||||
if(ESRval) {
|
||||
#ifdef IPX_DEBUGMSG
|
||||
LOG_MSG("ECB: SN%7d to be notified.", SerialNumber);
|
||||
|
@ -227,8 +222,7 @@ ECBClass::~ECBClass() {
|
|||
}
|
||||
}
|
||||
|
||||
static Bit16u socketCount;
|
||||
static Bit16u opensockets[SOCKTABLESIZE];
|
||||
|
||||
|
||||
static bool sockInUse(Bit16u sockNum) {
|
||||
for(Bitu i=0;i<socketCount;i++) {
|
||||
|
@ -292,6 +286,7 @@ static void CloseSocket(void) {
|
|||
tmp2ECB = tmpECB->nextECB;
|
||||
if(tmpECB->getSocket()==sockNum) {
|
||||
tmpECB->setCompletionFlag(COMP_CANCELLED);
|
||||
tmpECB->setInUseFlag(USEFLAG_AVAILABLE);
|
||||
delete tmpECB;
|
||||
}
|
||||
tmpECB = tmp2ECB;
|
||||
|
@ -311,7 +306,6 @@ static bool IPX_Multiplex(void) {
|
|||
return true;
|
||||
}
|
||||
|
||||
//static void sendPackets();
|
||||
static void sendPacket(ECBClass* sendecb);
|
||||
|
||||
static void handleIpxRequest(void) {
|
||||
|
@ -320,10 +314,14 @@ static void handleIpxRequest(void) {
|
|||
switch (reg_bx) {
|
||||
case 0x0000: // Open socket
|
||||
OpenSocket();
|
||||
#ifdef IPX_DEBUGMSG
|
||||
LOG_MSG("IPX: Open socket %4x", swapByte(reg_dx));
|
||||
#endif
|
||||
break;
|
||||
case 0x0001: // Close socket
|
||||
#ifdef IPX_DEBUGMSG
|
||||
LOG_MSG("IPX: Close socket %4x", swapByte(reg_dx));
|
||||
#endif
|
||||
CloseSocket();
|
||||
break;
|
||||
case 0x0002: // get local target
|
||||
|
@ -332,26 +330,24 @@ static void handleIpxRequest(void) {
|
|||
|
||||
case 0x0003: // Send packet
|
||||
if(!incomingPacket.connected) {
|
||||
tmpECB = new ECBClass(SegValue(es),reg_si);//CreateECB(RealMake(SegValue(es), reg_si),true);
|
||||
tmpECB = new ECBClass(SegValue(es),reg_si);
|
||||
tmpECB->setInUseFlag(USEFLAG_AVAILABLE);
|
||||
tmpECB->setCompletionFlag(COMP_UNDELIVERABLE);
|
||||
delete tmpECB; // not notify?
|
||||
//DeleteECB(tmpECB);
|
||||
reg_al = 0xff; // Failure
|
||||
} else {
|
||||
tmpECB = new ECBClass(SegValue(es),reg_si);//CreateECB(RealMake(SegValue(es), reg_si),true);
|
||||
tmpECB = new ECBClass(SegValue(es),reg_si);
|
||||
tmpECB->setInUseFlag(USEFLAG_SENDING);
|
||||
//LOG_MSG("IPX: Sending packet on %4x", tmpECB->getSocket());
|
||||
reg_al = 0x00; // Success
|
||||
sendPacket(tmpECB);
|
||||
}
|
||||
|
||||
//sendPackets();
|
||||
|
||||
break;
|
||||
case 0x0004: // Listen for packet
|
||||
tmpECB = new ECBClass(SegValue(es),reg_si);//CreateECB(RealMake(SegValue(es), reg_si),false);
|
||||
if(!sockInUse(tmpECB->getSocket())) {
|
||||
reg_al = 0xff; // Socket is not open
|
||||
tmpECB = new ECBClass(SegValue(es),reg_si);
|
||||
if(!sockInUse(tmpECB->getSocket())) { // Socket is not open
|
||||
reg_al = 0xff;
|
||||
tmpECB->setInUseFlag(USEFLAG_AVAILABLE);
|
||||
tmpECB->setCompletionFlag(COMP_HARDWAREERROR);
|
||||
delete tmpECB;
|
||||
|
@ -374,14 +370,18 @@ static void handleIpxRequest(void) {
|
|||
while(tmpECB) {
|
||||
tmp2ECB=tmpECB->nextECB;
|
||||
if(tmpECB->ECBAddr == ecbaddress) {
|
||||
delete tmpECB; // TODO: invoke flags... check if it can be canceled
|
||||
tmpECB->setInUseFlag(USEFLAG_AVAILABLE);
|
||||
tmpECB->setCompletionFlag(COMP_CANCELLED);
|
||||
delete tmpECB;
|
||||
reg_al=0; // Success
|
||||
#ifdef IPX_DEBUGMSG
|
||||
LOG_MSG("IPX: ECB canceled.");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
tmpECB=tmp2ECB;
|
||||
}
|
||||
reg_al=0; // Success
|
||||
reg_al=0xff; // Fail
|
||||
break;
|
||||
}
|
||||
case 0x0008: // Get interval marker
|
||||
|
@ -389,12 +389,11 @@ static void handleIpxRequest(void) {
|
|||
break;
|
||||
case 0x0009: // Get internetwork address
|
||||
{
|
||||
#ifdef IPX_DEBUGMSG
|
||||
LOG_MSG("IPX: Get internetwork address %2x:%2x:%2x:%2x:%2x:%2x", localIpxAddr.netnode[5], localIpxAddr.netnode[4], localIpxAddr.netnode[3], localIpxAddr.netnode[2], localIpxAddr.netnode[1], localIpxAddr.netnode[0]);
|
||||
Bit8u * addrptr;
|
||||
Bits i;
|
||||
|
||||
addrptr = (Bit8u *)&localIpxAddr;
|
||||
for(i=0;i<10;i++) {
|
||||
#endif
|
||||
Bit8u * addrptr = (Bit8u *)&localIpxAddr;
|
||||
for(Bit16u i=0;i<10;i++) {
|
||||
real_writeb(SegValue(es),reg_si+i,addrptr[i]);
|
||||
}
|
||||
break;
|
||||
|
@ -426,12 +425,6 @@ Bitu IPX_IntHandler(void) {
|
|||
return CBRET_NONE;
|
||||
}
|
||||
|
||||
static void disconnectServer(bool unexpected) {
|
||||
// There is no Timer remove code, hence this has to be done manually
|
||||
incomingPacket.connected = false;
|
||||
if(unexpected) LOG_MSG("IPX: Server disconnected unexpectedly");
|
||||
}
|
||||
|
||||
static void pingAck(IPaddress retAddr) {
|
||||
IPXHeader regHeader;
|
||||
UDPpacket regPacket;
|
||||
|
@ -503,7 +496,7 @@ static void receivePacket(Bit8u *buffer, Bit16s bufSize) {
|
|||
// Check to see if ping packet
|
||||
if(useSocket == 0x2) {
|
||||
// Is this a broadcast?
|
||||
if((tmpHeader->dest.addr.byIP.host == 0xffffffff) && (tmpHeader->dest.addr.byIP.port = 0xffff)) {
|
||||
if((tmpHeader->dest.addr.byIP.host == 0xffffffff) && (tmpHeader->dest.addr.byIP.port == 0xffff)) {
|
||||
// Yes. We should return the ping back to the sender
|
||||
IPaddress tmpAddr;
|
||||
UnpackIP(tmpHeader->src.addr.byIP, &tmpAddr);
|
||||
|
@ -530,13 +523,10 @@ static void receivePacket(Bit8u *buffer, Bit16s bufSize) {
|
|||
useECB->setCompletionFlag(COMP_SUCCESS);
|
||||
useECB->setImmAddress(&buffer[22]); // Write in source node
|
||||
hostaddr = *((Bit32u *)&buffer[24]);
|
||||
|
||||
#ifdef IPX_DEBUGMSG
|
||||
LOG_MSG("IPX: Received packet of %d bytes from %d.%d.%d.%d (%x CRC)", bufSize, CONVIP(hostaddr), packetCRC(&buffer[30], bufSize-30));
|
||||
#endif
|
||||
|
||||
#endif
|
||||
useECB->NotifyESR();
|
||||
//DeleteECB(useECB);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -544,7 +534,6 @@ static void receivePacket(Bit8u *buffer, Bit16s bufSize) {
|
|||
if(bufoffset < bufSize) {
|
||||
useECB->setCompletionFlag(COMP_MALFORMED);
|
||||
useECB->NotifyESR();
|
||||
//DeleteECB(useECB);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -556,7 +545,7 @@ static void receivePacket(Bit8u *buffer, Bit16s bufSize) {
|
|||
#endif
|
||||
}
|
||||
|
||||
static void IPX_UDPClientLoop(void) {
|
||||
static void IPX_ClientLoop(void) {
|
||||
int numrecv;
|
||||
UDPpacket inPacket;
|
||||
inPacket.data = (Uint8 *)recvBuffer;
|
||||
|
@ -570,190 +559,127 @@ static void IPX_UDPClientLoop(void) {
|
|||
if(numrecv) receivePacket(inPacket.data, inPacket.len);
|
||||
|
||||
//}while(numrecv>0);
|
||||
|
||||
}
|
||||
// don't waste time scanning the list
|
||||
static void sendPacket(ECBClass* sendecb) {
|
||||
char outbuffer[IPXBUFFERSIZE];
|
||||
fragmentDescriptor tmpFrag;
|
||||
Bit16u i, fragCount,t;
|
||||
Bit16s packetsize;
|
||||
Bit16u *wordptr;
|
||||
Bits result;
|
||||
UDPpacket outPacket;
|
||||
|
||||
//if(useECB->getInUseFlag() == USEFLAG_SENDING)
|
||||
// {
|
||||
sendecb->setInUseFlag(USEFLAG_AVAILABLE);
|
||||
packetsize = 0;
|
||||
fragCount = sendecb->getFragCount();
|
||||
for(i=0;i<fragCount;i++) {
|
||||
sendecb->getFragDesc(i,&tmpFrag);
|
||||
if(i==0) {
|
||||
// Fragment containing IPX header
|
||||
// Must put source address into header
|
||||
Bit8u * addrptr;
|
||||
Bits m;
|
||||
|
||||
addrptr = (Bit8u *)&localIpxAddr.netnode;
|
||||
for(m=0;m<6;m++) {
|
||||
real_writeb(tmpFrag.segment,tmpFrag.offset+m+22,addrptr[m]);
|
||||
}
|
||||
}
|
||||
for(t=0;t<tmpFrag.size;t++) {
|
||||
outbuffer[packetsize] = real_readb(tmpFrag.segment, tmpFrag.offset + t);
|
||||
packetsize++;
|
||||
if(packetsize>=IPXBUFFERSIZE) {
|
||||
LOG_MSG("IPX: Packet size to be sent greater than %d bytes.", IPXBUFFERSIZE);
|
||||
sendecb->setCompletionFlag(COMP_UNDELIVERABLE);
|
||||
sendecb->NotifyESR();
|
||||
//DeleteECB(useECB);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add length and source socket to IPX header
|
||||
wordptr = (Bit16u *)&outbuffer[0];
|
||||
// Blank CRC
|
||||
wordptr[0] = 0xffff;
|
||||
// Length
|
||||
wordptr[1] = swapByte(packetsize);
|
||||
// Source socket
|
||||
wordptr[14] = swapByte(sendecb->getSocket());
|
||||
|
||||
outPacket.channel = UDPChannel;
|
||||
outPacket.data = (Uint8 *)&outbuffer[0];
|
||||
outPacket.len = packetsize;
|
||||
outPacket.maxlen = packetsize;
|
||||
// Since we're using a channel, we won't send the IP address again
|
||||
result = SDLNet_UDP_Send(ipxClientSocket, UDPChannel, &outPacket);
|
||||
if(result == 0) {
|
||||
LOG_MSG("IPX: Could not send packet: %s", SDLNet_GetError());
|
||||
sendecb->setCompletionFlag(COMP_UNDELIVERABLE);
|
||||
sendecb->NotifyESR();
|
||||
//DeleteECB(useECB);
|
||||
disconnectServer(true);
|
||||
//return;
|
||||
} else {
|
||||
sendecb->setInUseFlag(USEFLAG_AVAILABLE);
|
||||
sendecb->setCompletionFlag(COMP_SUCCESS);
|
||||
#ifdef IPX_DEBUGMSG
|
||||
LOG_MSG("Packet sent: size: %d",packetsize);
|
||||
#endif
|
||||
sendecb->NotifyESR();
|
||||
}
|
||||
//}
|
||||
}
|
||||
static void sendPackets() {
|
||||
ECBClass *useECB;
|
||||
ECBClass *nextECB;
|
||||
char outbuffer[IPXBUFFERSIZE];
|
||||
fragmentDescriptor tmpFrag;
|
||||
Bit16u i, fragCount,t;
|
||||
Bit16s packetsize;
|
||||
Bit16u *wordptr;
|
||||
Bits result;
|
||||
UDPpacket outPacket;
|
||||
|
||||
useECB = ECBList;
|
||||
while(useECB != NULL) {
|
||||
nextECB = useECB->nextECB;
|
||||
if(useECB->getInUseFlag() == USEFLAG_SENDING) {
|
||||
useECB->setInUseFlag(USEFLAG_AVAILABLE);
|
||||
packetsize = 0;
|
||||
fragCount = useECB->getFragCount();
|
||||
for(i=0;i<fragCount;i++) {
|
||||
useECB->getFragDesc(i,&tmpFrag);
|
||||
if(i==0) {
|
||||
// Fragment containing IPX header
|
||||
// Must put source address into header
|
||||
Bit8u * addrptr;
|
||||
Bits m;
|
||||
|
||||
addrptr = (Bit8u *)&localIpxAddr.netnode;
|
||||
for(m=0;m<6;m++) {
|
||||
real_writeb(tmpFrag.segment,tmpFrag.offset+m+22,addrptr[m]);
|
||||
}
|
||||
}
|
||||
for(t=0;t<tmpFrag.size;t++) {
|
||||
outbuffer[packetsize] = real_readb(tmpFrag.segment, tmpFrag.offset + t);
|
||||
packetsize++;
|
||||
if(packetsize>=IPXBUFFERSIZE) {
|
||||
LOG_MSG("IPX: Packet size to be sent greater than %d bytes.", IPXBUFFERSIZE);
|
||||
useECB->setCompletionFlag(COMP_UNDELIVERABLE);
|
||||
useECB->NotifyESR();
|
||||
//DeleteECB(useECB);
|
||||
goto nextECB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add length and source socket to IPX header
|
||||
wordptr = (Bit16u *)&outbuffer[0];
|
||||
// Blank CRC
|
||||
wordptr[0] = 0xffff;
|
||||
// Length
|
||||
wordptr[1] = swapByte(packetsize);
|
||||
// Source socket
|
||||
wordptr[14] = swapByte(useECB->getSocket());
|
||||
|
||||
outPacket.channel = UDPChannel;
|
||||
outPacket.data = (Uint8 *)&outbuffer[0];
|
||||
outPacket.len = packetsize;
|
||||
outPacket.maxlen = packetsize;
|
||||
// Since we're using a channel, we won't send the IP address again
|
||||
result = SDLNet_UDP_Send(ipxClientSocket, UDPChannel, &outPacket);
|
||||
if(result == 0) {
|
||||
LOG_MSG("IPX: Could not send packet: %s", SDLNet_GetError());
|
||||
useECB->setCompletionFlag(COMP_UNDELIVERABLE);
|
||||
useECB->NotifyESR();
|
||||
//DeleteECB(useECB);
|
||||
disconnectServer(true);
|
||||
//return;
|
||||
} else {
|
||||
useECB->setInUseFlag(USEFLAG_AVAILABLE);
|
||||
useECB->setCompletionFlag(COMP_SUCCESS);
|
||||
//LOG_MSG("Packet sent: size: %d",packetsize);
|
||||
useECB->NotifyESR();
|
||||
//DeleteECB(useECB);
|
||||
}
|
||||
}
|
||||
nextECB:
|
||||
useECB = nextECB;
|
||||
void DisconnectFromServer(bool unexpected) {
|
||||
if(unexpected) LOG_MSG("IPX: Server disconnected unexpectedly");
|
||||
if(incomingPacket.connected) {
|
||||
incomingPacket.connected = false;
|
||||
TIMER_DelTickHandler(&IPX_ClientLoop);
|
||||
SDLNet_UDP_Close(ipxClientSocket);
|
||||
}
|
||||
}
|
||||
|
||||
//RealPt ESRJmpDisplacementAddr;
|
||||
//RealPt ESRTargetAddr;
|
||||
//RealPt ESRDummyRetAddr;
|
||||
/*
|
||||
void repeatESR(bool rep)
|
||||
{
|
||||
if(rep) real_writeb(
|
||||
RealSeg(ESRJmpDisplacementAddr),
|
||||
RealOff(ESRJmpDisplacementAddr),
|
||||
(Bit8u)0xF5);
|
||||
else real_writeb(
|
||||
RealSeg(ESRJmpDisplacementAddr),
|
||||
RealOff(ESRJmpDisplacementAddr),
|
||||
(Bit8u)0);
|
||||
}
|
||||
*/
|
||||
ECBClass* ESRHANDLER_useECB;
|
||||
static void IPX_ClientLoop(void) {
|
||||
static void sendPacket(ECBClass* sendecb) {
|
||||
Bit8u outbuffer[IPXBUFFERSIZE];
|
||||
fragmentDescriptor tmpFrag;
|
||||
Bit16u i, fragCount,t;
|
||||
Bit16s packetsize;
|
||||
Bit16u *wordptr;
|
||||
Bits result;
|
||||
UDPpacket outPacket;
|
||||
|
||||
sendecb->setInUseFlag(USEFLAG_AVAILABLE);
|
||||
packetsize = 0;
|
||||
fragCount = sendecb->getFragCount();
|
||||
for(i=0;i<fragCount;i++) {
|
||||
sendecb->getFragDesc(i,&tmpFrag);
|
||||
if(i==0) {
|
||||
// Fragment containing IPX header
|
||||
// Must put source address into header
|
||||
Bit8u * addrptr;
|
||||
|
||||
addrptr = (Bit8u *)&localIpxAddr.netnum;
|
||||
for(Bit16u m=0;m<4;m++) {
|
||||
real_writeb(tmpFrag.segment,tmpFrag.offset+m+18,addrptr[m]);
|
||||
}
|
||||
addrptr = (Bit8u *)&localIpxAddr.netnode;
|
||||
for(Bit16u m=0;m<6;m++) {
|
||||
real_writeb(tmpFrag.segment,tmpFrag.offset+m+22,addrptr[m]);
|
||||
}
|
||||
}
|
||||
for(t=0;t<tmpFrag.size;t++) {
|
||||
outbuffer[packetsize] = real_readb(tmpFrag.segment, tmpFrag.offset + t);
|
||||
packetsize++;
|
||||
if(packetsize>=IPXBUFFERSIZE) {
|
||||
LOG_MSG("IPX: Packet size to be sent greater than %d bytes.", IPXBUFFERSIZE);
|
||||
sendecb->setCompletionFlag(COMP_UNDELIVERABLE);
|
||||
sendecb->NotifyESR();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add length and source socket to IPX header
|
||||
wordptr = (Bit16u *)&outbuffer[0];
|
||||
// Blank CRC
|
||||
wordptr[0] = 0xffff;
|
||||
// Length
|
||||
wordptr[1] = swapByte(packetsize);
|
||||
// Source socket
|
||||
wordptr[14] = swapByte(sendecb->getSocket());
|
||||
|
||||
IPX_UDPClientLoop();
|
||||
// Send outgoing packets
|
||||
//sendPackets();
|
||||
}
|
||||
// filter out broadcasts and local loopbacks
|
||||
// ok, the situation is:
|
||||
// Warcraft1 is allergic to having broadcast packets looped back.
|
||||
// C&C1 is allergic to not having broadcast packets looped back.
|
||||
// Warcraft1 broadcasts to 00 00 00 00 : FF FF FF FF FF FF
|
||||
// C&C1 broadcasts to FF FF FF FF : FF FF FF FF FF FF
|
||||
// Some other games don't care.
|
||||
// I assume FF... does local loopback, 00... doesn't.
|
||||
// Let's hope the bug isn't somewhere else..
|
||||
|
||||
bool islocalbroadcast=true;
|
||||
bool isloopback=true;
|
||||
|
||||
Bit8u * addrptr;
|
||||
|
||||
addrptr = (Bit8u *)&localIpxAddr.netnum;
|
||||
for(Bitu m=0;m<4;m++) {
|
||||
if(addrptr[m]!=outbuffer[m+0x6])isloopback=false;
|
||||
if(outbuffer[m+0x6]!=0xff) islocalbroadcast=false;
|
||||
}
|
||||
addrptr = (Bit8u *)&localIpxAddr.netnode;
|
||||
for(Bitu m=0;m<6;m++) {
|
||||
if(addrptr[m]!=outbuffer[m+0xa])isloopback=false;
|
||||
if(outbuffer[m+0xa]!=0xff) islocalbroadcast=false;
|
||||
}
|
||||
|
||||
if(!isloopback) {
|
||||
outPacket.channel = UDPChannel;
|
||||
outPacket.data = (Uint8 *)&outbuffer[0];
|
||||
outPacket.len = packetsize;
|
||||
outPacket.maxlen = packetsize;
|
||||
// Since we're using a channel, we won't send the IP address again
|
||||
result = SDLNet_UDP_Send(ipxClientSocket, UDPChannel, &outPacket);
|
||||
|
||||
if(result == 0) {
|
||||
LOG_MSG("IPX: Could not send packet: %s", SDLNet_GetError());
|
||||
sendecb->setCompletionFlag(COMP_HARDWAREERROR);
|
||||
sendecb->NotifyESR();
|
||||
DisconnectFromServer(true);
|
||||
return;
|
||||
} else {
|
||||
sendecb->setCompletionFlag(COMP_SUCCESS);
|
||||
#ifdef IPX_DEBUGMSG
|
||||
LOG_MSG("Packet sent: size: %d",packetsize);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if(isloopback||islocalbroadcast) {
|
||||
receivePacket(&outbuffer[0],packetsize);
|
||||
#ifdef IPX_DEBUGMSG
|
||||
LOG_MSG("Packet back: loopback:%d, broadcast:%d",isloopback,isbroadcast);
|
||||
#endif
|
||||
}
|
||||
sendecb->NotifyESR();
|
||||
}
|
||||
|
||||
static bool pingCheck(IPXHeader * outHeader) {
|
||||
char buffer[1024];
|
||||
Bits result;
|
||||
UDPpacket regPacket;
|
||||
|
||||
IPXHeader *regHeader;
|
||||
regPacket.data = (Uint8 *)buffer;
|
||||
regPacket.maxlen = sizeof(buffer);
|
||||
|
@ -766,8 +692,6 @@ static bool pingCheck(IPXHeader * outHeader) {
|
|||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool ConnectToServer(char *strAddr) {
|
||||
|
@ -776,7 +700,12 @@ bool ConnectToServer(char *strAddr) {
|
|||
IPXHeader regHeader;
|
||||
|
||||
if(!SDLNet_ResolveHost(&ipxServConnIp, strAddr, (Bit16u)tcpPort)) {
|
||||
|
||||
// Generate the MAC address. This is made by zeroing out the first two
|
||||
// octets and then using the actual IP address for the last 4 octets.
|
||||
// This idea is from the IPX over IP implementation as specified in RFC 1234:
|
||||
// http://www.faqs.org/rfcs/rfc1234.html
|
||||
|
||||
|
||||
// Select an anonymous UDP port
|
||||
ipxClientSocket = SDLNet_UDP_Open(0);
|
||||
if(ipxClientSocket) {
|
||||
|
@ -848,45 +777,21 @@ bool ConnectToServer(char *strAddr) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void DisconnectFromServer(void) {
|
||||
void IPX_NetworkInit() {
|
||||
|
||||
if(incomingPacket.connected) {
|
||||
incomingPacket.connected = false;
|
||||
TIMER_DelTickHandler(&IPX_ClientLoop);
|
||||
SDLNet_UDP_Close(ipxClientSocket);
|
||||
}
|
||||
}
|
||||
|
||||
bool IPX_NetworkInit() {
|
||||
|
||||
localIpxAddr.netnum[0] = 0x0; localIpxAddr.netnum[1] = 0x0; localIpxAddr.netnum[2] = 0x0; localIpxAddr.netnum[3] = 0x1;
|
||||
|
||||
/*
|
||||
if(SDLNet_ResolveHost(&ipxClientIp, localhostname, tcpPort)) {
|
||||
LOG_MSG("IPX: Unable to resolve localname: \"%s\". IPX disabled.", localhostname);
|
||||
return false;
|
||||
} else {
|
||||
LOG_MSG("IPX: Using localname: %s IP is: %d.%d.%d.%d", localhostname, CONVIP(ipxClientIp.host));
|
||||
}
|
||||
*/
|
||||
|
||||
// Generate the MAC address. This is made by zeroing out the first two octets and then using the actual IP address for
|
||||
// the last 4 octets. This idea is from the IPX over IP implementation as specified in RFC 1234:
|
||||
// http://www.faqs.org/rfcs/rfc1234.html
|
||||
localIpxAddr.netnum[0] = 0x0;
|
||||
localIpxAddr.netnum[1] = 0x0;
|
||||
localIpxAddr.netnum[2] = 0x0;
|
||||
localIpxAddr.netnum[3] = 0x1;
|
||||
localIpxAddr.netnode[0] = 0x00;
|
||||
localIpxAddr.netnode[1] = 0x00;
|
||||
//localIpxAddr.netnode[5] = (ipxClientIp.host >> 24) & 0xff;
|
||||
//localIpxAddr.netnode[4] = (ipxClientIp.host >> 16) & 0xff;
|
||||
//localIpxAddr.netnode[3] = (ipxClientIp.host >> 8) & 0xff;
|
||||
//localIpxAddr.netnode[2] = (ipxClientIp.host & 0xff);
|
||||
//To be filled in on response from server
|
||||
localIpxAddr.netnode[2] = 0x00;
|
||||
localIpxAddr.netnode[3] = 0x00;
|
||||
localIpxAddr.netnode[4] = 0x00;
|
||||
localIpxAddr.netnode[5] = 0x00;
|
||||
|
||||
socketCount = 0;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
class IPXNET : public Program {
|
||||
|
@ -1003,7 +908,7 @@ public:
|
|||
WriteOut("IPX Tunneling Server not running in this DosBox session.\n");
|
||||
} else {
|
||||
isIpxServer = false;
|
||||
DisconnectFromServer();
|
||||
DisconnectFromServer(false);
|
||||
IPX_StopServer();
|
||||
WriteOut("IPX Tunneling Server stopped.");
|
||||
// Don't know how to stop the timer just yet.
|
||||
|
@ -1044,7 +949,7 @@ public:
|
|||
// TODO: Send a packet to the server notifying of disconnect
|
||||
|
||||
WriteOut("IPX Tunneling Client disconnected from server.\n");
|
||||
DisconnectFromServer();
|
||||
DisconnectFromServer(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1093,19 +998,6 @@ public:
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
WriteOut("IPX Status\n\n");
|
||||
if(!incomingPacket.connected) {
|
||||
WriteOut("IPX tunneling client not presently connected");
|
||||
return;
|
||||
}
|
||||
if(isIpxServer) {
|
||||
WriteOut("This DosBox session is an IPX tunneling server running on port %d", tcpPort);
|
||||
} else {
|
||||
WriteOut("This DosBox session is an IPX tunneling client connected to: %s",SDLNet_ResolveIP(&ipxServConnIp));
|
||||
}
|
||||
*/
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1126,17 +1018,12 @@ Bitu IPX_ESRHandler1(void) {
|
|||
SegSet16(es, RealSeg(ESRList->ECBAddr));
|
||||
reg_si = RealOff(ESRList->ECBAddr);
|
||||
reg_al = 0xff;
|
||||
|
||||
CALLBACK_RunRealFar(RealSeg(ESRList->getESRAddr()), RealOff(ESRList->getESRAddr()));
|
||||
|
||||
delete ESRList;
|
||||
} // while
|
||||
|
||||
// PIC_DeActivateIRQ(11);
|
||||
IO_WriteB(0xa0,0x63); //EOI11
|
||||
IO_WriteB(0x20,0x62); //EOI2
|
||||
// IO_WriteB(0xa0,0x20); //EOI
|
||||
//IO_WriteB(0x20,0x20); //EOI
|
||||
|
||||
#ifdef IPX_DEBUGMSG
|
||||
LOG_MSG("ESR loop done.");
|
||||
|
@ -1192,14 +1079,12 @@ public:
|
|||
LOG_MSG("ESR callback address: %x, HandlerID %d", phyDospage,call_ipxesr1);
|
||||
#endif
|
||||
//save registers
|
||||
phys_writeb(phyDospage+0,(Bit8u)0xFA); // CLI
|
||||
phys_writeb(phyDospage+1,(Bit8u)0x60); // PUSHA
|
||||
phys_writeb(phyDospage+2,(Bit8u)0x1E); // PUSH DS
|
||||
phys_writeb(phyDospage+3,(Bit8u)0x06); // PUSH ES
|
||||
phys_writeb(phyDospage+4,(Bit8u)0x0F); // PUSH..
|
||||
phys_writeb(phyDospage+5,(Bit8u)0xA0); // FS
|
||||
phys_writeb(phyDospage+6,(Bit8u)0x0F); // PUSH..
|
||||
phys_writeb(phyDospage+7,(Bit8u)0xA8); // GS
|
||||
phys_writeb(phyDospage+0,(Bit8u)0xFA); // CLI
|
||||
phys_writeb(phyDospage+1,(Bit8u)0x60); // PUSHA
|
||||
phys_writeb(phyDospage+2,(Bit8u)0x1E); // PUSH DS
|
||||
phys_writeb(phyDospage+3,(Bit8u)0x06); // PUSH ES
|
||||
phys_writew(phyDospage+4,(Bit16u)0xA00F); // PUSH FS
|
||||
phys_writew(phyDospage+6,(Bit16u)0xA80F); // PUSH GS
|
||||
|
||||
// callback
|
||||
phys_writeb(phyDospage+8,(Bit8u)0xFE); // GRP 4
|
||||
|
@ -1207,14 +1092,12 @@ public:
|
|||
phys_writew(phyDospage+10,call_ipxesr1); // Callback identifier
|
||||
|
||||
// register recreation
|
||||
phys_writeb(phyDospage+12,(Bit8u)0x0F);// POP..
|
||||
phys_writeb(phyDospage+13,(Bit8u)0xA9); // GS
|
||||
phys_writeb(phyDospage+14,(Bit8u)0x0F);// POP..
|
||||
phys_writeb(phyDospage+15,(Bit8u)0xA1); // FS
|
||||
phys_writeb(phyDospage+16,(Bit8u)0x07); // POP ES
|
||||
phys_writeb(phyDospage+17,(Bit8u)0x1F); // POP DS
|
||||
phys_writeb(phyDospage+18,(Bit8u)0x61); //POPA
|
||||
phys_writeb(phyDospage+19,(Bit8u)0xCF); //IRET: restores flags, CS, IP
|
||||
phys_writew(phyDospage+12,(Bit16u)0xA90F); // POP GS
|
||||
phys_writew(phyDospage+14,(Bit16u)0xA10F); // POP FS
|
||||
phys_writeb(phyDospage+16,(Bit8u)0x07); // POP ES
|
||||
phys_writeb(phyDospage+17,(Bit8u)0x1F); // POP DS
|
||||
phys_writeb(phyDospage+18,(Bit8u)0x61); // POPA
|
||||
phys_writeb(phyDospage+19,(Bit8u)0xCF); // IRET: restores flags, CS, IP
|
||||
|
||||
// IPX version 2.12
|
||||
//phys_writeb(phyDospage+27,(Bit8u)0x2);
|
||||
|
@ -1224,10 +1107,8 @@ public:
|
|||
RealPt ESRRoutineBase = RealMake(dospage, 0);
|
||||
|
||||
// Interrupt enabling
|
||||
RealSetVec(0x73,ESRRoutineBase,old_73_vector); // IRQ11
|
||||
Bit8u irqmask=IO_ReadB(0xa1);
|
||||
irqmask &= ~8; // enable IRQ11
|
||||
IO_WriteB(0xa1,irqmask);
|
||||
RealSetVec(0x73,ESRRoutineBase,old_73_vector); // IRQ11
|
||||
IO_WriteB(0xa1,IO_ReadB(0xa1)&(~8)); // enable IRQ11
|
||||
|
||||
PROGRAMS_MakeFile("IPXNET.COM",IPXNET_ProgramStart);
|
||||
}
|
||||
|
@ -1238,16 +1119,13 @@ public:
|
|||
|
||||
if(isIpxServer) {
|
||||
isIpxServer = false;
|
||||
DisconnectFromServer();
|
||||
IPX_StopServer();
|
||||
}
|
||||
disconnectServer(false);
|
||||
DisconnectFromServer(false);
|
||||
|
||||
DOS_DelMultiplexHandler(IPX_Multiplex);
|
||||
RealSetVec(0x73,old_73_vector);
|
||||
Bit8u irqmask=IO_ReadB(0xa1);
|
||||
irqmask |= 8; // disable IRQ11
|
||||
IO_WriteB(0xa1,irqmask);
|
||||
IO_WriteB(0xa1,IO_ReadB(0xa1)|8); // disable IRQ11
|
||||
|
||||
PhysPt phyDospage = PhysMake(dospage,0);
|
||||
for(Bitu i = 0;i < 32;i++)
|
||||
|
|
Loading…
Add table
Reference in a new issue