apply patch from bluecow to fix hmiplay sync issues and lack of midi reset (d1x r1.5)
[btb/d2x.git] / arch / win32 / ipx_win.c
1 /* $Id: ipx_win.c,v 1.8 2003-11-26 12:26:25 btb Exp $ */
2
3 /*
4  *
5  * IPX driver using BSD style sockets
6  * Mostly taken from dosemu
7  *
8  */
9
10 #ifdef HAVE_CONFIG_H
11 #include <conf.h>
12 #endif
13
14 #include <string.h>
15 #include <stdlib.h>
16 #include <winsock.h>
17 #include <wsipx.h>
18 #include <errno.h>
19 #include <stdio.h>
20
21 #include "ipx_drv.h"
22
23 #ifdef __GNUC__
24 #define _do_mprintf(n, format, args...) printf(format, ## args)
25 #define mprintf(args) _do_mprintf args
26 #else
27 #define mprintf()
28 #endif
29
30 //#define n_printf(format, args...) mprintf((1, format, ## args))
31
32 static int ipx_win_GetMyAddress( void )
33 {
34 #if 0
35   int sock;
36   struct sockaddr_ipx ipxs;
37   struct sockaddr_ipx ipxs2;
38   int len;
39   int i;
40   
41 //  sock=socket(AF_IPX,SOCK_DGRAM,PF_IPX);
42   sock=socket(AF_IPX,SOCK_DGRAM,0);
43
44   if(sock==-1)
45   {
46     mprintf((1,"IPX: could not open socket in GetMyAddress\n"));
47     return(-1);
48   }
49
50   /* bind this socket to network 0 */  
51   ipxs.sa_family=AF_IPX;
52 #ifdef IPX_MANUAL_ADDRESS
53   memcpy(ipxs.sa_netnum, ipx_MyAddress, 4);
54 #else
55   memset(ipxs.sa_netnum, 0, 4);
56 #endif  
57   ipxs.sa_socket=0;
58   
59   if(bind(sock,(struct sockaddr *)&ipxs,sizeof(ipxs))==-1)
60   {
61     mprintf((1,"IPX: could bind to network 0 in GetMyAddress\n"));
62     closesocket( sock );
63     return(-1);
64   }
65   
66   len = sizeof(ipxs2);
67   if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) {
68     mprintf((1,"IPX: could not get socket name in GetMyAddress\n"));
69     closesocket( sock );
70     return(-1);
71   }
72
73   memcpy(ipx_MyAddress, ipxs2.sa_netnum, 4);
74   for (i = 0; i < 6; i++) {
75     ipx_MyAddress[4+i] = ipxs2.sa_nodenum[i];
76   }
77 /*  printf("My address is 0x%.4X:%.2X.%.2X.%.2X.%.2X.%.2X.%.2X\n", *((int *)ipxs2.sa_netnum), ipxs2.sa_nodenum[0],
78   ipxs2.sa_nodenum[1], ipxs2.sa_nodenum[2], ipxs2.sa_nodenum[3], ipxs2.sa_nodenum[4], ipxs2.sa_nodenum[5]);*/
79
80     closesocket( sock );
81
82 #endif
83   return(0);
84 }
85
86 static int ipx_win_OpenSocket(ipx_socket_t *sk, int port)
87 {
88   int sock;                     /* sock here means Linux socket handle */
89   int opt;
90   struct sockaddr_ipx ipxs;
91   int len;
92   struct sockaddr_ipx ipxs2;
93
94   /* DANG_FIXTHIS - kludge to support broken linux IPX stack */
95   /* need to convert dynamic socket open into a real socket number */
96 /*  if (port == 0) {
97     mprintf((1,"IPX: using socket %x\n", nextDynamicSocket));
98     port = nextDynamicSocket++;
99   }
100 */
101   /* do a socket call, then bind to this port */
102 //  sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
103 //  sock = socket(AF_IPX, SOCK_DGRAM, 0);
104   sock = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX);//why NSPROTO_IPX?  I looked in the quake source and thats what they used. :) -MPM  (on w2k 0 and PF_IPX don't work)
105   if (sock == -1) {
106     mprintf((1,"IPX: could not open IPX socket.\n"));
107     return -1;
108   }
109
110
111   opt = 1;
112   /* Permit broadcast output */
113   if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
114                  (const char *)&opt, sizeof(opt)) == -1) {
115     mprintf((1,"IPX: could not set socket option for broadcast.\n"));
116     return -1;
117   }
118   ipxs.sa_family = AF_IPX;
119   memcpy(ipxs.sa_netnum, ipx_MyAddress, 4);
120 //  *((unsigned int *)&ipxs.sa_netnum[0]) = *((unsigned int *)&ipx_MyAddress[0]);
121 /*  ipxs.sa_netnum = htonl(MyNetwork); */
122   memset(ipxs.sa_nodenum, 0, 6);
123 //  bzero(ipxs.sa_nodenum, 6);  /* Please fill in my node name */
124   ipxs.sa_socket = htons((short)port);
125
126   /* now bind to this port */
127   if (bind(sock, (struct sockaddr *) &ipxs, sizeof(ipxs)) == -1) {
128     mprintf((1,"IPX: could not bind socket to address\n"));
129     closesocket( sock );
130     return -1;
131   }
132   
133 //  if( port==0 ) {
134 //    len = sizeof(ipxs2);
135 //    if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) {
136 //       //n_printf("IPX: could not get socket name in IPXOpenSocket\n");
137 //     closesocket( sock );
138 //      return -1;
139 //    } else {
140 //      port = htons(ipxs2.sa_socket);
141 //      //n_printf("IPX: opened dynamic socket %04x\n", port);
142 //    }
143   len = sizeof(ipxs2);
144   if (getsockname(sock,(struct sockaddr *)&ipxs2,&len) < 0) {
145     mprintf((1,"IPX: could not get socket name in IPXOpenSocket\n"));
146     closesocket( sock );
147     return -1;
148   } 
149   if (port == 0) {
150     port = htons(ipxs2.sa_socket);
151     mprintf((1,"IPX: opened dynamic socket %04x\n", port));
152   }
153
154   memcpy(ipx_MyAddress, ipxs2.sa_netnum, 4);
155   memcpy(ipx_MyAddress + 4, ipxs2.sa_nodenum, 6);
156
157   sk->fd = sock;
158   sk->socket = port;
159   return 0;
160 }
161
162 static void ipx_win_CloseSocket(ipx_socket_t *mysock) {
163   /* now close the file descriptor for the socket, and free it */
164   mprintf((1,"IPX: closing file descriptor on socket %x\n", mysock->socket));
165   closesocket(mysock->fd);
166 }
167
168 static int ipx_win_SendPacket(ipx_socket_t *mysock, IPXPacket_t *IPXHeader,
169  u_char *data, int dataLen) {
170   struct sockaddr_ipx ipxs;
171  
172   ipxs.sa_family = AF_IPX;
173   /* get destination address from IPX packet header */
174   memcpy(&ipxs.sa_netnum, IPXHeader->Destination.Network, 4);
175   /* if destination address is 0, then send to my net */
176   if ((*(unsigned int *)&ipxs.sa_netnum) == 0) {
177     (*(unsigned int *)&ipxs.sa_netnum)= *((unsigned int *)&ipx_MyAddress[0]);
178 /*  ipxs.sa_netnum = htonl(MyNetwork); */
179   }
180   memcpy(&ipxs.sa_nodenum, IPXHeader->Destination.Node, 6);
181   memcpy(&ipxs.sa_socket, IPXHeader->Destination.Socket, 2);
182 //  ipxs.sa_type = IPXHeader->PacketType;
183   /*    ipxs.sipx_port=htons(0x452); */
184   return sendto(mysock->fd, data, dataLen, 0,
185              (struct sockaddr *) &ipxs, sizeof(ipxs));
186 }
187
188 static int ipx_win_ReceivePacket(ipx_socket_t *s, char *buffer, int bufsize, 
189  struct ipx_recv_data *rd) {
190         int sz, size;
191         struct sockaddr_ipx ipxs;
192  
193         sz = sizeof(ipxs);
194         if ((size = recvfrom(s->fd, buffer, bufsize, 0,
195              (struct sockaddr *) &ipxs, &sz)) <= 0)
196              return size;
197         memcpy(rd->src_network, ipxs.sa_netnum, 4);
198         memcpy(rd->src_node, ipxs.sa_nodenum, 6);
199         rd->src_socket = ipxs.sa_socket;
200         rd->dst_socket = s->socket;
201 //      rd->pkt_type = ipxs.sipx_type;
202   
203         return size;
204 }
205
206 struct ipx_driver ipx_win = {
207         ipx_win_GetMyAddress,
208         ipx_win_OpenSocket,
209         ipx_win_CloseSocket,
210         ipx_win_SendPacket,
211         ipx_win_ReceivePacket,
212         ipx_general_PacketReady,
213         NULL,   // InitNetgameAuxData
214         NULL,   // HandleNetgameAuxData
215         NULL,   // HandleLeaveGame
216         NULL    // SendGamePack
217 };