+++ /dev/null
-/* FCE Ultra - NES/Famicom Emulator\r
- *\r
- * Copyright notice for this file:\r
- * Copyright (C) 2002 Ben Parnell\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
- */\r
-\r
-static char netplayhost[256]={0};\r
-static int netplayport=0xFCE;\r
-\r
-static int netplayon=0;\r
-static int netplaytype=0;\r
-\r
-static HWND hwndns=0;\r
-\r
-static SOCKET Socket=INVALID_SOCKET;\r
-static int wsainit=0;\r
-\r
-static volatile int abortnetplay=0;\r
-static volatile int concommand=0;\r
-\r
-static void WSE(char *ahh)\r
-{\r
- char tmp[256];\r
- sprintf(tmp,"Winsock: %s",ahh);\r
- FCEUD_PrintError(tmp);\r
-}\r
-\r
-int SetBlockingSock(SOCKET Socko)\r
-{\r
- unsigned long t;\r
- t=1;\r
- if(ioctlsocket(Socko,FIONBIO,&t))\r
- {\r
- WSE("Error setting socket to non-blocking mode!\n");\r
- return 0;\r
- }\r
- return 1;\r
-}\r
-\r
-BOOL CALLBACK BoogaDooga(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)\r
-{\r
- switch(uMsg) {\r
- case WM_USER+1:\r
- if(WSAGETASYNCERROR(lParam))\r
- concommand=1;\r
- else\r
- concommand=2;\r
- break;\r
- case WM_USER:\r
- if(WSAGETSELECTEVENT(lParam)==FD_CONNECT)\r
- {\r
- if(WSAGETSELECTERROR(lParam))\r
- concommand=1;\r
- else\r
- concommand=2;\r
- } \r
- break;\r
- case WM_INITDIALOG:\r
- if(!netplaytype) SetDlgItemText(hwndDlg,100,(LPTSTR)"Waiting for a connection...");\r
- else SetDlgItemText(hwndDlg,100,(LPTSTR)"Attempting to establish a connection..."); \r
- break;\r
- case WM_CLOSE:\r
- case WM_QUIT: goto gornk;\r
- case WM_COMMAND:\r
- if(!(wParam>>16))\r
- switch(wParam&0xFFFF)\r
- {\r
- case 1:\r
- gornk:\r
- abortnetplay=1;\r
- EndDialog(hwndDlg,0);\r
- break;\r
- }\r
- }\r
- return 0;\r
-\r
-}\r
-\r
-static void CloseNSDialog(void)\r
-{\r
- if(hwndns)\r
- {\r
- SendMessage(hwndns,WM_COMMAND,1,0);\r
- hwndns=0;\r
- }\r
-}\r
-\r
-void CreateStatusDialog(void)\r
-{\r
- hwndns=CreateDialog(fceu_hInstance,"NETSTAT",hAppWnd,BoogaDooga);\r
-}\r
-\r
-void FCEUD_NetworkClose(void)\r
-{\r
- CloseNSDialog();\r
- if(Socket!=INVALID_SOCKET)\r
- {\r
- closesocket(Socket);\r
- Socket=INVALID_SOCKET;\r
- }\r
- if(wsainit)\r
- {\r
- WSACleanup();\r
- wsainit=0;\r
- }\r
- /* Make sure blocking is returned to normal once network play is stopped. */\r
- NoWaiting&=~2;\r
-}\r
-\r
-int FCEUD_NetworkConnect(void)\r
-{\r
- WSADATA WSAData;\r
- SOCKADDR_IN sockin; /* I want to play with fighting robots. */\r
- SOCKET TSocket;\r
-\r
- if(WSAStartup(MAKEWORD(1,1),&WSAData))\r
- {\r
- FCEUD_PrintError("Error initializing Windows Sockets.");\r
- return(0);\r
- }\r
- wsainit=1;\r
- concommand=abortnetplay=0;\r
-\r
- if( (TSocket=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET)\r
- {\r
- WSE("Error creating socket.");\r
- FCEUD_NetworkClose();\r
- return(0);\r
- }\r
-\r
- memset(&sockin,0,sizeof(sockin));\r
- sockin.sin_family=AF_INET;\r
- sockin.sin_port=htons(netplayport);\r
-\r
- if(!netplaytype) /* Act as a server. */\r
- {\r
-\r
- int sockin_len;\r
- sockin.sin_addr.s_addr=INADDR_ANY;\r
-\r
- sockin_len=sizeof(sockin);\r
-\r
- if(bind(TSocket,(struct sockaddr *)&sockin,sizeof(sockin))==SOCKET_ERROR)\r
- {\r
- WSE("Error binding to socket.");\r
- closesocket(TSocket);\r
- FCEUD_NetworkClose();\r
- return(0);\r
- }\r
-\r
- if(listen(TSocket,1)==SOCKET_ERROR)\r
- {\r
- WSE("Error listening on socket.");\r
- closesocket(TSocket);\r
- FCEUD_NetworkClose();\r
- return(0);\r
- }\r
-\r
- CreateStatusDialog();\r
- if(!SetBlockingSock(TSocket))\r
- {\r
- closesocket(TSocket);\r
- FCEUD_NetworkClose();\r
- return(0);\r
- }\r
-\r
- while( (Socket=accept(TSocket,(struct sockaddr *) &sockin,(int *)&sockin_len)) ==\r
- INVALID_SOCKET)\r
- {\r
- if(abortnetplay || WSAGetLastError()!=WSAEWOULDBLOCK)\r
- {\r
- if(!abortnetplay)\r
- WSE("Error accepting connection.");\r
- closesocket(TSocket);\r
- FCEUD_NetworkClose();\r
- return(0);\r
- }\r
- else\r
- BlockingCheck();\r
- }\r
-\r
- if(!SetBlockingSock(Socket))\r
- {\r
- FCEUD_NetworkClose();\r
- return(0);\r
- }\r
-\r
- } \r
- else /* We're a client... */\r
- {\r
- char phostentb[MAXGETHOSTSTRUCT];\r
- unsigned long hadr;\r
-\r
- hadr=inet_addr(netplayhost);\r
-\r
- CreateStatusDialog();\r
-\r
- if(hadr!=INADDR_NONE)\r
- sockin.sin_addr.s_addr=hadr;\r
- else\r
- {\r
- if(!WSAAsyncGetHostByName(hwndns,WM_USER+1,(const char *)netplayhost,phostentb,MAXGETHOSTSTRUCT))\r
- {\r
- ghosterr:\r
- WSE("Error getting host network information.");\r
- closesocket(TSocket);\r
- FCEUD_NetworkClose();\r
- return(0);\r
- }\r
- while(concommand!=2)\r
- {\r
- BlockingCheck();\r
- if(concommand==1 || abortnetplay)\r
- goto ghosterr;\r
- }\r
- memcpy((char *)&sockin.sin_addr,((PHOSTENT)phostentb)->h_addr,((PHOSTENT)phostentb)->h_length);\r
- }\r
- concommand=0;\r
-\r
- if(WSAAsyncSelect(TSocket,hwndns,WM_USER,FD_CONNECT|FD_CLOSE)==SOCKET_ERROR)\r
- {\r
- eventnoterr:\r
- WSE("Error setting event notification on socket.");\r
- closesocket(TSocket);\r
- FCEUD_NetworkClose();\r
- return(0);\r
- }\r
-\r
- if(!SetBlockingSock(TSocket))\r
- {\r
- closesocket(TSocket);\r
- FCEUD_NetworkClose();\r
- return(0);\r
- }\r
-\r
- if(connect(TSocket,(PSOCKADDR)&sockin,sizeof(sockin))==SOCKET_ERROR)\r
- {\r
- if(WSAGetLastError()!=WSAEWOULDBLOCK)\r
- {\r
- cerrav:\r
- WSE("Error connecting to remote host.");\r
-\r
- cerra:\r
- closesocket(TSocket);\r
- FCEUD_NetworkClose();\r
- return(0);\r
- }\r
-\r
- while(concommand!=2)\r
- {\r
- BlockingCheck(); \r
- if(abortnetplay) goto cerra;\r
- if(concommand==1) goto cerrav;\r
- }\r
- }\r
- if(WSAAsyncSelect(TSocket,hAppWnd,WM_USER,0)==SOCKET_ERROR)\r
- goto eventnoterr;\r
- Socket=TSocket;\r
-\r
- }\r
- CloseNSDialog();\r
- return(1);\r
-}\r
-\r
-\r
-int FCEUD_NetworkSendData(uint8 *data, uint32 len)\r
-{\r
- int erc;\r
-\r
- while((erc=send(Socket,data,len,0)))\r
- {\r
- if(erc!=SOCKET_ERROR)\r
- {\r
- len-=erc;\r
- data+=erc;\r
- if(!len)\r
- return(1); /* All data sent. */\r
-\r
- if(!BlockingCheck()) return(0);\r
- }\r
- else\r
- {\r
- if(WSAGetLastError()==WSAEWOULDBLOCK)\r
- {\r
- if(!BlockingCheck()) return(0);\r
- continue;\r
- }\r
- return(0);\r
- }\r
- }\r
- return(0);\r
-}\r
-\r
-int FCEUD_NetworkRecvData(uint8 *data, uint32 len, int block)\r
-{\r
- int erc;\r
-\r
- if(block) // TODO: Add code elsewhere to handle sound buffer underruns.\r
- {\r
- while((erc=recv(Socket,data,len,0))!=len)\r
- { \r
- if(!erc)\r
- return(0);\r
- if(WSAGetLastError()==WSAEWOULDBLOCK)\r
- {\r
- if(!BlockingCheck()) return(0);\r
- continue;\r
- }\r
- return(0);\r
- }\r
-\r
- {\r
- char buf[24];\r
- if(recv(Socket,buf,24,MSG_PEEK)==SOCKET_ERROR)\r
- {\r
- if(WSAGetLastError()==WSAEWOULDBLOCK)\r
- NoWaiting&=~2;\r
- else\r
- return(0);\r
- }\r
- else\r
- NoWaiting|=2; /* We're the client and we're lagging behind.\r
- disable blocking(particularly sound...) to *try*\r
- to catch up.\r
- */ \r
- }\r
-\r
- return 1;\r
- }\r
-\r
- else /* We're the server. See if there's any new data\r
- from player 2. If not, then return(-1).\r
- */\r
- {\r
- erc=recv(Socket,data,len,0);\r
- if(!erc)\r
- return(0);\r
- if(erc==SOCKET_ERROR)\r
- {\r
- if(WSAGetLastError()==WSAEWOULDBLOCK)\r
- return(-1);\r
- return(0); // Some other(bad) error occurred.\r
- }\r
- return(1);\r
- } // end else to if(block)\r
-}\r
-\r
-BOOL CALLBACK NetConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)\r
-{\r
- switch(uMsg) {\r
- case WM_INITDIALOG: \r
-\r
- CheckDlgButton(hwndDlg,100,netplayon?BST_CHECKED:BST_UNCHECKED);\r
- CheckRadioButton(hwndDlg,101,102,101+netplaytype);\r
- SetDlgItemInt(hwndDlg,107,netplayport,0);\r
-\r
- if(netplayhost[0])\r
- SetDlgItemText(hwndDlg,104,netplayhost);\r
- break;\r
- case WM_CLOSE:\r
- case WM_QUIT: goto gornk;\r
- case WM_COMMAND:\r
- if(!(wParam>>16))\r
- switch(wParam&0xFFFF)\r
- {\r
- case 1:\r
- gornk:\r
-\r
- netplayport=GetDlgItemInt(hwndDlg,107,0,0);\r
-\r
- if(IsDlgButtonChecked(hwndDlg,100)==BST_CHECKED)\r
- netplayon=1;\r
- else\r
- netplayon=0;\r
-\r
- if(IsDlgButtonChecked(hwndDlg,101)==BST_CHECKED)\r
- netplaytype=0;\r
- else\r
- netplaytype=1;\r
-\r
- GetDlgItemText(hwndDlg,104,netplayhost,255);\r
- netplayhost[255]=0;\r
-\r
- EndDialog(hwndDlg,0);\r
- break;\r
- }\r
- }\r
- return 0;\r
-}\r
-\r
-\r
-static void ConfigNetplay(void)\r
-{\r
- DialogBox(fceu_hInstance,"NETPLAYCONFIG",hAppWnd,NetConCallB);\r
-\r
- if(netplayon)\r
- FCEUI_SetNetworkPlay(netplaytype+1);\r
- else\r
- FCEUI_SetNetworkPlay(0);\r
-}\r
-\r