home *** CD-ROM | disk | FTP | other *** search
/ WADS of WADS / WadsOfWads.1994.zip / MULTI / IPXSRC / IPXNET.C < prev    next >
C/C++ Source or Header  |  1994-02-13  |  6KB  |  328 lines

  1. // ipxnet.c
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <dos.h>
  6. #include <string.h>
  7. #include <process.h>
  8. #include <values.h>
  9.  
  10. #include "ipxnet.h"
  11.  
  12. /*
  13. =============================================================================
  14.  
  15.                         IPX PACKET DRIVER
  16.  
  17. =============================================================================
  18. */
  19.  
  20.  
  21. packet_t        packets[NUMPACKETS];
  22.  
  23. nodeadr_t         nodeadr[MAXNETNODES+1];    // first is local, last is broadcast
  24.  
  25. nodeadr_t        remoteadr;            // set by each GetPacket
  26.  
  27. localadr_t        localadr;            // set at startup
  28.  
  29. int     socketid = 0x869c;        // 0x869c is the official DOOM socket
  30.  
  31. union   REGS    regs;           // scratch for int86 calls
  32. struct  SREGS   sregs;
  33.  
  34. unsigned short    enteripx[2];
  35.  
  36. long               localtime;        // for time stamp in packets
  37. long            remotetime;
  38.  
  39. //===========================================================================
  40.  
  41. char *hex = "0123456789abcdef";
  42.  
  43. void PrintAddress (nodeadr_t *adr, char *str)
  44. {
  45.     int    i;
  46.  
  47.     for (i=0 ; i<6 ; i++)
  48.     {
  49.         *str++ = hex[adr->node[i]>>4];
  50.         *str++ = hex[adr->node[i]&15];
  51.     }
  52.     *str = 0;
  53. }
  54.  
  55.  
  56.  
  57.  
  58. int OpenSocket(short socketNumber)
  59. {
  60.     regs.x.bx = 0;
  61.     regs.h.al = 0;                  // longevity
  62.     regs.x.dx = socketNumber;
  63.     int86(0x7A,®s,®s);
  64.     if (regs.h.al)
  65.         Error ("OpenSocket: 0x%x",regs.h.al);
  66.     return regs.x.dx;
  67. }
  68.  
  69.  
  70. void CloseSocket(short socketNumber)
  71. {
  72.     regs.x.bx = 1;
  73.     regs.x.dx = socketNumber;
  74.     int86(0x7A,®s,®s);
  75. }
  76.  
  77. void ListenForPacket(ECB *ecb)
  78. {
  79.     regs.x.si = FP_OFF(ecb);
  80.     sregs.es = FP_SEG(ecb);
  81.     regs.x.bx = 4;
  82.  
  83.     int86x (0x7a,®s,®s,&sregs);
  84.     if (regs.h.al)
  85.         Error ("ListenForPacket: 0x%x",regs.h.al);
  86. }
  87.  
  88.  
  89. void GetLocalAddress (void)
  90. {
  91.     regs.x.si = FP_OFF(&localadr);
  92.     sregs.es = FP_SEG(&localadr);
  93.     regs.x.bx = 9;
  94.  
  95.     int86x (0x7a,®s,®s,&sregs);
  96.     if (regs.h.al)
  97.         Error ("Get inet addr: 0x%x",regs.h.al);
  98. }
  99.  
  100.  
  101.  
  102. /*
  103. ====================
  104. =
  105. = InitNetwork
  106. =
  107. ====================
  108. */
  109.  
  110. void InitNetwork (void)
  111. {
  112.     int     i,j;
  113.  
  114. //
  115. // get IPX function address
  116. //
  117.     regs.x.ax = 0x7a00;
  118.     int86x (0x2f,®s,®s,&sregs);
  119.     if ( regs.h.al != 0xff)
  120.         Error ("IPX not detected\n");
  121.  
  122.     enteripx[0] = regs.x.di;
  123.     enteripx[1] = sregs.es;
  124.  
  125.  
  126. //
  127. // allocate a socket for sending and receiving
  128. //
  129.     i = CheckParm ("-port");
  130.     if (i>0 && i<_argc-1)
  131.     {
  132.         socketid = atoi (_argv[i+1]);
  133.         printf ("Using alternate port %i for network\n",socketid);
  134.     }
  135.     socketid = OpenSocket ( (socketid>>8) + ((socketid&255)<<8) );
  136.  
  137.     GetLocalAddress ();
  138.  
  139. //
  140. // set up several receiving ECBs
  141. //
  142.     memset (packets,0,NUMPACKETS*sizeof(packet_t));
  143.  
  144.     for (i=1 ; i<NUMPACKETS ; i++)
  145.     {
  146.         packets[i].ecb.InUseFlag = 0x1d;
  147.         packets[i].ecb.ECBSocket = socketid;
  148.         packets[i].ecb.FragmentCount = 1;
  149.         packets[i].ecb.fAddress[0] = FP_OFF(&packets[i].ipx);
  150.         packets[i].ecb.fAddress[1] = FP_SEG(&packets[i].ipx);
  151.         packets[i].ecb.fSize = sizeof(packet_t)-sizeof(ECB);
  152.  
  153.         ListenForPacket (&packets[i].ecb);
  154.     }
  155.  
  156. //
  157. // set up a sending ECB
  158. //
  159.     memset (&packets[0],0,sizeof(packets[0]));
  160.  
  161.     packets[0].ecb.ECBSocket = socketid;
  162.     packets[0].ecb.FragmentCount = 1;
  163.     packets[0].ecb.fAddress[0] = FP_OFF(&packets[0].ipx);
  164.     packets[0].ecb.fAddress[1] = FP_SEG(&packets[0].ipx);
  165.     for (j=0 ; j<4 ; j++)
  166.         packets[0].ipx.dNetwork[j] = localadr.network[j];
  167.     packets[0].ipx.dSocket[0] = socketid&255;
  168.     packets[0].ipx.dSocket[1] = socketid>>8;
  169.  
  170. // known local node at 0
  171.     for (i=0 ; i<6 ; i++)
  172.         nodeadr[0].node[i] = localadr.node[i];
  173.  
  174. // broadcast node at MAXNETNODES
  175.     for (j=0 ; j<6 ; j++)
  176.         nodeadr[MAXNETNODES].node[j] = 0xff;
  177.  
  178. }
  179.  
  180.  
  181. /*
  182. ====================
  183. =
  184. = ShutdownNetwork
  185. =
  186. ====================
  187. */
  188.  
  189. void ShutdownNetwork (void)
  190. {
  191.     CloseSocket (socketid);
  192. }
  193.  
  194.  
  195. /*
  196. ==============
  197. =
  198. = SendPacket
  199. =
  200. = A destination of MAXNETNODES is a broadcast
  201. ==============
  202. */
  203.  
  204. void SendPacket (int destination)
  205. {
  206.     int             j;
  207.  
  208. // find a free packet buffer to use
  209.     while (packets[0].ecb.InUseFlag)
  210.     {
  211.     }
  212.  
  213. // set the time
  214.     packets[0].time = localtime;
  215.  
  216. // set the address
  217.     for (j=0 ; j<6 ; j++)
  218.         packets[0].ipx.dNode[j] = packets[0].ecb.ImmediateAddress[j] =
  219.         nodeadr[destination].node[j];
  220.  
  221. // set the length (ipx + time + datalength)
  222.     packets[0].ecb.fSize = sizeof(IPXPacket) + 4 + doomcom.datalength + 4;
  223.  
  224. // put the data into an ipx packet
  225.     memcpy (&packets[0].data, &doomcom.data, doomcom.datalength);
  226.  
  227. // send the packet
  228.     regs.x.si = FP_OFF(&packets[0]);
  229.     sregs.es = FP_SEG(&packets[0]);
  230.     regs.x.bx = 3;
  231.  
  232.     int86x (0x7a, ®s, ®s, &sregs);
  233.  
  234.     if (regs.h.al)
  235.         Error ("SendPacket: 0x%x",regs.h.al);
  236. }
  237.  
  238.  
  239. unsigned short ShortSwap (unsigned short i)
  240. {
  241.     return ((i&255)<<8) + ((i>>8)&255);
  242. }
  243.  
  244. /*
  245. ==============
  246. =
  247. = GetPacket
  248. =
  249. = Returns false if no packet is waiting
  250. =
  251. ==============
  252. */
  253.  
  254. int GetPacket (void)
  255. {
  256.     int             packetnum;
  257.     int             i, j;
  258.     long            besttic;
  259.     packet_t        *packet;
  260.  
  261. // if multiple packets are waiting, return them in order by time
  262.  
  263.     besttic = MAXLONG;
  264.     packetnum = -1;
  265.     doomcom.remotenode = -1;
  266.  
  267.     for ( i = 1 ; i < NUMPACKETS ; i++)
  268.     {
  269.         if (packets[i].ecb.InUseFlag)
  270.         {
  271.             continue;
  272.         }
  273.  
  274.         if (packets[i].time < besttic)
  275.         {
  276.             besttic = packets[i].time;
  277.             packetnum = i;
  278.         }
  279.     }
  280.  
  281.     if (besttic == MAXLONG)
  282.         return 0;                           // no packets
  283.  
  284.     packet = &packets[packetnum];
  285.  
  286.     if (besttic == -1 && localtime != -1)
  287.     {
  288.         ListenForPacket (&packet->ecb);
  289.         return 0;                            // setup broadcast from other game
  290.     }
  291.  
  292.     remotetime = besttic;
  293.  
  294. //
  295. // got a good packet
  296. //
  297.     if (packet->ecb.CompletionCode)
  298.         Error ("GetPacket: ecb.ComletionCode = 0x%x",packet->ecb.CompletionCode);
  299.  
  300. // set remoteadr to the sender of the packet
  301.     memcpy (&remoteadr, packet->ipx.sNode, sizeof(remoteadr));
  302.     for (i=0 ; i<doomcom.numnodes ; i++)
  303.         if (!memcmp(&remoteadr, &nodeadr[i], sizeof(remoteadr)))
  304.             break;
  305.     if (i < doomcom.numnodes)
  306.         doomcom.remotenode = i;
  307.     else
  308.     {
  309.         if (localtime != -1)
  310.         {    // this really shouldn't happen
  311.             ListenForPacket (&packet->ecb);
  312.             return 0;
  313.         }
  314.     }
  315.  
  316.  
  317. // copy out the data
  318.     doomcom.datalength = ShortSwap(packet->ipx.PacketLength) - 38;
  319.     memcpy (&doomcom.data, &packet->data, doomcom.datalength);
  320.  
  321. // repost the ECB
  322.     ListenForPacket (&packet->ecb);
  323.  
  324.     return 1;
  325. }
  326.  
  327.  
  328.