/***************************************************************************/ /* */ /* */ /* IPX Network Communication Driver for Greed */ /* Copyright (C) 1995 by Channel 7 */ /* */ /* written by Robert Morgan */ /* */ /***************************************************************************/ #include #include #include #include "ipx.h" /**** CONSTANTS ****/ #define MAXLONG 0x7FFFFFFFL #define IPX_OPENSOCKET 0x0000 #define IPX_CLOSESOCKET 0x0001 #define IPX_SENDPACKET 0x0003 #define IPX_LISTEN 0x0004 #define IPX_GETLOCALADDR 0x0009 #define IPX_POLLDRIVER 0x000A #define IPX_LONGEVITY 0x0000 #define IPXINT Call_IPX() /**** VARIABLES ****/ packet_t packets[MAXPACKETS]; nodeadr_t nodeadr[MAXPLAYERS+1]; // first is local, last is broadcast nodeadr_t remoteadr; // set by each GetPacket localadr_t localadr; // set at startup int socketid=0x1234; // 0x1234 is the C7 socket int numpackets; // num of packets being used int IPXInstalled; long localt, remotet; // for time stamp in packets void far (*Call_IPX)(void); /**** FUNCTIONS ****/ unsigned short ShortSwap(unsigned short i) { return (i<<8) + ((i>>8)&255); } int IPX_OpenSocket(short socketNumber) { int socket; _BX=IPX_OPENSOCKET; _AL=IPX_LONGEVITY; _DX=socketNumber; IPXINT; socket=_DX; // _DX is lost after the next few lines, must store in variable if (_AL) { if (_AL==0xFF) printf("Socket 0x%X already open.\n",ShortSwap(socket)); else MS_Error("Error.. IPX_OpenSocket: 0x%X",_AL); } return socket; } void IPX_CloseSocket(short socketNumber) { _BX=IPX_CLOSESOCKET; _DX=socketNumber; IPXINT; } void IPX_ListenForPacket(ECB *ecb) { _SI=FP_OFF(ecb); _ES=FP_SEG(ecb); _BX=IPX_LISTEN; IPXINT; if (_AL) MS_Error("Error.. IPX_ListenForPacket: 0x%X",_AL); } void IPX_GetLocalAddress(void) { int i; _SI=FP_OFF(&localadr); _ES=FP_SEG(&localadr); _BX=IPX_GETLOCALADDR; IPXINT; printf("Local Address: 0x"); for(i=0;i<6;i++) printf("%X",localadr.node[i]&255); printf("\n"); } void IPX_InitNetwork(void) { int i, j; union REGS regs; struct SREGS sregs; // look for an IPX network printf("Detecting IPX: "); _AX=0x7a00; geninterrupt(0x2F); if (_AL!=0xFF) MS_Error("IPX not detected\n"); Call_IPX=MK_FP(_ES,_DI); IPXInstalled=1; printf("Found\n"); // allocate a socket for sending and receiving socketid=IPX_OpenSocket(ShortSwap(socketid)); IPX_GetLocalAddress(); // set up several receiving ECBs memset(packets,0,MAXPACKETS*sizeof(packet_t)); for (i=1;i>8; packets[0].ipx.PacketType=4; // packet exchange packet // known local node at 0 for (i=0;i<6;i++) nodeadr[0].node[i]=localadr.node[i]; // broadcast node at MAXPLAYERS for (j=0;j<6;j++) nodeadr[MAXPLAYERS].node[j]=0xff; } void IPX_ShutdownNetwork(void) { if (IPXInstalled) IPX_CloseSocket(socketid); } /* SendPacket A destination of MAXPLAYERS is a broadcast */ void IPX_SendPacket(int destination) { union REGS r; struct SREGS s; int j; while (packets[0].ecb.InUseFlag) { _BX=IPX_POLLDRIVER; IPXINT; } // set the time stamp packets[0].time=localt; // set the address for (j=0;j<6;j++) packets[0].ipx.dNode[j] = packets[0].ecb.ImmediateAddress[j] = nodeadr[destination].node[j]; // set the data length of the packet packets[0].ecb.fSize2=greedcom.datalength; // send the packet _SI=FP_OFF(&packets[0]); _ES=FP_SEG(&packets[0]); _BX=IPX_SENDPACKET; IPXINT; } /* GetPacket Returns false if no packet is waiting */ int IPX_GetPacket(void) { int i, packetnum, usage; long besttic; packet_t *packet; // if multiple packets are waiting, return them in order by time besttic=MAXLONG; greedcom.remotenode=-1; usage=0; for (i=1;igreedcom.maxusage) greedcom.maxusage=usage; // find max load packet=&packets[packetnum]; if (besttic==-1 && localt!=-1) { IPX_ListenForPacket(&packet->ecb); return 0; // setup broadcast from other game } remotet=besttic; // got a bad packet if (packet->ecb.CompletionCode) MS_Error("Error.. IPX_GetPacket: ecb.ComletionCode=0x%X",packet->ecb.CompletionCode); // set remoteadr to the sender of the packet memcpy(&remoteadr, packet->ipx.sNode,sizeof(remoteadr)); for (i=0;iecb); return 0; } // copy out the data greedcom.datalength=ShortSwap(packet->ipx.PacketLength) - 34; memcpy(&greedcom.data,&packet->data,greedcom.datalength); // repost the ECB IPX_ListenForPacket(&packet->ecb); return 1; }