1 /* FCE Ultra - NES/Famicom Emulator
\r
3 * Copyright notice for this file:
\r
4 * Copyright (C) 2002 Ben Parnell
\r
6 * This program is free software; you can redistribute it and/or modify
\r
7 * it under the terms of the GNU General Public License as published by
\r
8 * the Free Software Foundation; either version 2 of the License, or
\r
9 * (at your option) any later version.
\r
11 * This program is distributed in the hope that it will be useful,
\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 * GNU General Public License for more details.
\r
16 * You should have received a copy of the GNU General Public License
\r
17 * along with this program; if not, write to the Free Software
\r
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
21 static char netplayhost[256]={0};
\r
22 static int netplayport=0xFCE;
\r
24 static int netplayon=0;
\r
25 static int netplaytype=0;
\r
27 static HWND hwndns=0;
\r
29 static SOCKET Socket=INVALID_SOCKET;
\r
30 static int wsainit=0;
\r
32 static volatile int abortnetplay=0;
\r
33 static volatile int concommand=0;
\r
35 static void WSE(char *ahh)
\r
38 sprintf(tmp,"Winsock: %s",ahh);
\r
39 FCEUD_PrintError(tmp);
\r
42 int SetBlockingSock(SOCKET Socko)
\r
46 if(ioctlsocket(Socko,FIONBIO,&t))
\r
48 WSE("Error setting socket to non-blocking mode!\n");
\r
54 BOOL CALLBACK BoogaDooga(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
58 if(WSAGETASYNCERROR(lParam))
\r
64 if(WSAGETSELECTEVENT(lParam)==FD_CONNECT)
\r
66 if(WSAGETSELECTERROR(lParam))
\r
73 if(!netplaytype) SetDlgItemText(hwndDlg,100,(LPTSTR)"Waiting for a connection...");
\r
74 else SetDlgItemText(hwndDlg,100,(LPTSTR)"Attempting to establish a connection...");
\r
77 case WM_QUIT: goto gornk;
\r
80 switch(wParam&0xFFFF)
\r
85 EndDialog(hwndDlg,0);
\r
93 static void CloseNSDialog(void)
\r
97 SendMessage(hwndns,WM_COMMAND,1,0);
\r
102 void CreateStatusDialog(void)
\r
104 hwndns=CreateDialog(fceu_hInstance,"NETSTAT",hAppWnd,BoogaDooga);
\r
107 void FCEUD_NetworkClose(void)
\r
110 if(Socket!=INVALID_SOCKET)
\r
112 closesocket(Socket);
\r
113 Socket=INVALID_SOCKET;
\r
120 /* Make sure blocking is returned to normal once network play is stopped. */
\r
124 int FCEUD_NetworkConnect(void)
\r
127 SOCKADDR_IN sockin; /* I want to play with fighting robots. */
\r
130 if(WSAStartup(MAKEWORD(1,1),&WSAData))
\r
132 FCEUD_PrintError("Error initializing Windows Sockets.");
\r
136 concommand=abortnetplay=0;
\r
138 if( (TSocket=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET)
\r
140 WSE("Error creating socket.");
\r
141 FCEUD_NetworkClose();
\r
145 memset(&sockin,0,sizeof(sockin));
\r
146 sockin.sin_family=AF_INET;
\r
147 sockin.sin_port=htons(netplayport);
\r
149 if(!netplaytype) /* Act as a server. */
\r
153 sockin.sin_addr.s_addr=INADDR_ANY;
\r
155 sockin_len=sizeof(sockin);
\r
157 if(bind(TSocket,(struct sockaddr *)&sockin,sizeof(sockin))==SOCKET_ERROR)
\r
159 WSE("Error binding to socket.");
\r
160 closesocket(TSocket);
\r
161 FCEUD_NetworkClose();
\r
165 if(listen(TSocket,1)==SOCKET_ERROR)
\r
167 WSE("Error listening on socket.");
\r
168 closesocket(TSocket);
\r
169 FCEUD_NetworkClose();
\r
173 CreateStatusDialog();
\r
174 if(!SetBlockingSock(TSocket))
\r
176 closesocket(TSocket);
\r
177 FCEUD_NetworkClose();
\r
181 while( (Socket=accept(TSocket,(struct sockaddr *) &sockin,(int *)&sockin_len)) ==
\r
184 if(abortnetplay || WSAGetLastError()!=WSAEWOULDBLOCK)
\r
187 WSE("Error accepting connection.");
\r
188 closesocket(TSocket);
\r
189 FCEUD_NetworkClose();
\r
196 if(!SetBlockingSock(Socket))
\r
198 FCEUD_NetworkClose();
\r
203 else /* We're a client... */
\r
205 char phostentb[MAXGETHOSTSTRUCT];
\r
206 unsigned long hadr;
\r
208 hadr=inet_addr(netplayhost);
\r
210 CreateStatusDialog();
\r
212 if(hadr!=INADDR_NONE)
\r
213 sockin.sin_addr.s_addr=hadr;
\r
216 if(!WSAAsyncGetHostByName(hwndns,WM_USER+1,(const char *)netplayhost,phostentb,MAXGETHOSTSTRUCT))
\r
219 WSE("Error getting host network information.");
\r
220 closesocket(TSocket);
\r
221 FCEUD_NetworkClose();
\r
224 while(concommand!=2)
\r
227 if(concommand==1 || abortnetplay)
\r
230 memcpy((char *)&sockin.sin_addr,((PHOSTENT)phostentb)->h_addr,((PHOSTENT)phostentb)->h_length);
\r
234 if(WSAAsyncSelect(TSocket,hwndns,WM_USER,FD_CONNECT|FD_CLOSE)==SOCKET_ERROR)
\r
237 WSE("Error setting event notification on socket.");
\r
238 closesocket(TSocket);
\r
239 FCEUD_NetworkClose();
\r
243 if(!SetBlockingSock(TSocket))
\r
245 closesocket(TSocket);
\r
246 FCEUD_NetworkClose();
\r
250 if(connect(TSocket,(PSOCKADDR)&sockin,sizeof(sockin))==SOCKET_ERROR)
\r
252 if(WSAGetLastError()!=WSAEWOULDBLOCK)
\r
255 WSE("Error connecting to remote host.");
\r
258 closesocket(TSocket);
\r
259 FCEUD_NetworkClose();
\r
263 while(concommand!=2)
\r
266 if(abortnetplay) goto cerra;
\r
267 if(concommand==1) goto cerrav;
\r
270 if(WSAAsyncSelect(TSocket,hAppWnd,WM_USER,0)==SOCKET_ERROR)
\r
280 int FCEUD_NetworkSendData(uint8 *data, uint32 len)
\r
284 while((erc=send(Socket,data,len,0)))
\r
286 if(erc!=SOCKET_ERROR)
\r
291 return(1); /* All data sent. */
\r
293 if(!BlockingCheck()) return(0);
\r
297 if(WSAGetLastError()==WSAEWOULDBLOCK)
\r
299 if(!BlockingCheck()) return(0);
\r
308 int FCEUD_NetworkRecvData(uint8 *data, uint32 len, int block)
\r
312 if(block) // TODO: Add code elsewhere to handle sound buffer underruns.
\r
314 while((erc=recv(Socket,data,len,0))!=len)
\r
318 if(WSAGetLastError()==WSAEWOULDBLOCK)
\r
320 if(!BlockingCheck()) return(0);
\r
328 if(recv(Socket,buf,24,MSG_PEEK)==SOCKET_ERROR)
\r
330 if(WSAGetLastError()==WSAEWOULDBLOCK)
\r
336 NoWaiting|=2; /* We're the client and we're lagging behind.
\r
337 disable blocking(particularly sound...) to *try*
\r
345 else /* We're the server. See if there's any new data
\r
346 from player 2. If not, then return(-1).
\r
349 erc=recv(Socket,data,len,0);
\r
352 if(erc==SOCKET_ERROR)
\r
354 if(WSAGetLastError()==WSAEWOULDBLOCK)
\r
356 return(0); // Some other(bad) error occurred.
\r
359 } // end else to if(block)
\r
362 BOOL CALLBACK NetConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
365 case WM_INITDIALOG:
\r
367 CheckDlgButton(hwndDlg,100,netplayon?BST_CHECKED:BST_UNCHECKED);
\r
368 CheckRadioButton(hwndDlg,101,102,101+netplaytype);
\r
369 SetDlgItemInt(hwndDlg,107,netplayport,0);
\r
372 SetDlgItemText(hwndDlg,104,netplayhost);
\r
375 case WM_QUIT: goto gornk;
\r
378 switch(wParam&0xFFFF)
\r
383 netplayport=GetDlgItemInt(hwndDlg,107,0,0);
\r
385 if(IsDlgButtonChecked(hwndDlg,100)==BST_CHECKED)
\r
390 if(IsDlgButtonChecked(hwndDlg,101)==BST_CHECKED)
\r
395 GetDlgItemText(hwndDlg,104,netplayhost,255);
\r
396 netplayhost[255]=0;
\r
398 EndDialog(hwndDlg,0);
\r
406 static void ConfigNetplay(void)
\r
408 DialogBox(fceu_hInstance,"NETPLAYCONFIG",hAppWnd,NetConCallB);
\r
411 FCEUI_SetNetworkPlay(netplaytype+1);
\r
413 FCEUI_SetNetworkPlay(0);
\r