1 /**********************************************************************************
2 Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
4 (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and
5 Jerremy Koot (jkoot@snes9x.com)
7 (c) Copyright 2002 - 2004 Matthew Kendora
9 (c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org)
11 (c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/)
13 (c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net)
15 (c) Copyright 2002 - 2006 Brad Jorsch (anomie@users.sourceforge.net),
16 funkyass (funkyass@spam.shaw.ca),
17 Kris Bleakley (codeviolation@hotmail.com),
18 Nach (n-a-c-h@users.sourceforge.net), and
19 zones (kasumitokoduck@yahoo.com)
22 (c) Copyright 2005 - 2006 Dreamer Nom,
25 C4 x86 assembler and some C emulation code
26 (c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com),
28 zsKnight (zsknight@zsnes.com)
31 (c) Copyright 2003 - 2006 Brad Jorsch,
35 (c) Copyright 1998 - 2006 _Demo_,
36 Andreas Naive (andreasnaive@gmail.com)
38 Ivar (ivar@snes9x.com),
43 neviksti (neviksti@hotmail.com)
46 (c) Copyright 2003 John Weidman,
48 Lord Nightmare (lord_nightmare@users.sourceforge.net),
54 (c) Copyright 2003 - 2006 John Weidman,
60 (c) Copyright 2004 - 2006 Dreamer Nom,
67 (c) Copyright 2001 - 2004 zsKnight,
68 pagefault (pagefault@zsnes.com),
70 Ported from x86 assembler to C by sanmaiwashi
72 SPC7110 and RTC C++ emulator code
73 (c) Copyright 2002 Matthew Kendora with research by
79 (c) Copyright 2003 Brad Jorsch with research by
84 (c) Copyright 2001-2006 byuu,
87 ST010 C++ emulator code
88 (c) Copyright 2003 Feather,
93 Super FX x86 assembler emulator code
94 (c) Copyright 1998 - 2003 _Demo_,
98 Super FX C emulator code
99 (c) Copyright 1997 - 1999 Ivar,
103 Sound DSP emulator code is derived from SNEeSe and OpenSPC:
104 (c) Copyright 1998 - 2003 Brad Martin
105 (c) Copyright 1998 - 2006 Charles Bilyue'
107 SH assembler code partly based on x86 assembler code
108 (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
111 (c) Copyright 1999 - 2001 Derek Liauw Kie Fa
114 (c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com)
116 Specific ports contains the works of other authors. See headers in
119 Snes9x homepage: http://www.snes9x.com
121 Permission to use, copy, modify and/or distribute Snes9x in both binary
122 and source form, for non-commercial purposes, is hereby granted without
123 fee, providing that this license information and copyright notice appear
124 with all copies and any derived work.
126 This software is provided 'as-is', without any express or implied
127 warranty. In no event shall the authors be held liable for any damages
128 arising from the use of this software or it's derivatives.
130 Snes9x is freeware for PERSONAL USE only. Commercial users should
131 seek permission of the copyright holders first. Commercial use includes,
132 but is not limited to, charging money for Snes9x or software derived from
133 Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
134 using Snes9x as a promotion for your commercial product.
136 The copyright holders request that bug fixes and improvements to the code
137 should be forwarded to them so everyone can benefit from the modifications
140 Super NES and Super Nintendo Entertainment System are trademarks of
141 Nintendo Co., Limited and its subsidiary companies.
142 **********************************************************************************/
146 #ifdef NETPLAY_SUPPORT
152 #include <sys/types.h>
156 #include <sys/time.h>
157 #include <sys/types.h>
158 #include <sys/stat.h>
161 #if defined (__WIN32__)
165 #define ioctl ioctlsocket
166 #define close closesocket
167 #define read(a,b,c) recv(a, b, c, 0)
168 #define write(a,b,c) send(a, b, c, 0)
172 #include <sys/ioctl.h>
173 #include <sys/socket.h>
174 #include <sys/param.h>
175 #include <netinet/in.h>
176 #include <arpa/inet.h>
179 #include <sys/stropts.h>
186 #include <semaphore.h>
193 #include "snapshot.h"
196 void S9xNPClientLoop (void *);
197 bool8 S9xNPLoadROM (uint32 len);
198 bool8 S9xNPLoadROMDialog (const char *);
199 bool8 S9xNPGetROMImage (uint32 len);
200 void S9xNPGetSRAMData (uint32 len);
201 void S9xNPGetFreezeFile (uint32 len);
203 unsigned long START = 0;
205 bool8 S9xNPConnectToServer (const char *hostname, int port,
206 const char *rom_name)
208 if (!S9xNPInitialise ())
213 NetPlay.MySequenceNum = 0;
214 NetPlay.ServerSequenceNum = 0;
215 NetPlay.Connected = FALSE;
216 NetPlay.Abort = FALSE;
218 NetPlay.Paused = FALSE;
219 NetPlay.PercentageComplete = 0;
221 if (NetPlay.ServerHostName)
222 free ((char *) NetPlay.ServerHostName);
223 NetPlay.ServerHostName = strdup (hostname);
225 free ((char *) NetPlay.ROMName);
226 NetPlay.ROMName = strdup (rom_name);
228 NetPlay.PendingWait4Sync = FALSE;
231 if (GUI.ClientSemaphore == NULL)
232 GUI.ClientSemaphore = CreateSemaphore (NULL, 0, NP_JOYPAD_HIST_SIZE, NULL);
234 if (NetPlay.ReplyEvent == NULL)
235 NetPlay.ReplyEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
237 _beginthread (S9xNPClientLoop, 0, NULL);
243 bool8 S9xNPConnect ()
245 struct sockaddr_in address;
246 struct hostent *hostinfo;
249 address.sin_family = AF_INET;
250 address.sin_port = htons (NetPlay.Port);
252 printf ("CLIENT: Looking up server's hostname (%s) @%ld\n", NetPlay.ServerHostName, S9xGetMilliTime () - START);
254 S9xNPSetAction ("Looking up server's hostname...");
255 if ((int) (addr = inet_addr (NetPlay.ServerHostName)) == -1)
257 if ((hostinfo = gethostbyname (NetPlay.ServerHostName)))
259 memcpy ((char *)&address.sin_addr, hostinfo->h_addr,
265 Unable to look up server's IP address from hostname.\n\n\
266 Unknown hostname or may be your nameserver isn't set\n\
273 memcpy ((char *)&address.sin_addr, &addr, sizeof (addr));
277 printf ("CLIENT: Creating socket @%ld\n", S9xGetMilliTime () - START);
279 S9xNPSetAction ("Creating network socket...");
280 if ((NetPlay.Socket = socket (AF_INET, SOCK_STREAM, 0)) < 0)
282 S9xNPSetError ("Creating network socket failed.");
287 printf ("CLIENT: Trying to connect to server @%ld...\n", S9xGetMilliTime () - START);
289 S9xNPSetAction ("Trying to connect to Snes9X server...");
291 if (connect (NetPlay.Socket, (struct sockaddr *) &address, sizeof (address)) < 0)
295 if (WSAGetLastError () == WSAECONNREFUSED)
297 if (errno == ECONNREFUSED)
301 Connection to remote server socket refused:\n\n\
302 Is there actually a Snes9X NetPlay server running\n\
303 on the remote machine on this port?");
307 sprintf (buf, "Connection to server failed with error number %d",
318 NetPlay.Connected = TRUE;
321 printf ("CLIENT: Sending 'HELLO' message @%ld...\n", S9xGetMilliTime () - START);
323 S9xNPSetAction ("Sending 'HELLO' message...");
324 /* Send the server a HELLO packet*/
325 int len = 7 + 4 + strlen (NetPlay.ROMName) + 1;
326 uint8 *tmp = new uint8 [len];
329 *ptr++ = NP_CLNT_MAGIC;
330 *ptr++ = NetPlay.MySequenceNum++;
331 *ptr++ = NP_CLNT_HELLO;
332 WRITE_LONG (ptr, len);
335 uint32 ft = Settings.FrameTime * 1000;
337 WRITE_LONG (ptr, ft);
339 WRITE_LONG (ptr, Settings.FrameTime);
342 strcpy ((char *) ptr, NetPlay.ROMName);
344 if (!S9xNPSendData (NetPlay.Socket, tmp, len))
346 S9xNPSetError ("Sending 'HELLO' message failed.");
354 printf ("CLIENT: Waiting for 'WELCOME' reply from server @%ld...\n", S9xGetMilliTime () - START);
356 S9xNPSetAction ("Waiting for 'HELLO' reply from server...");
360 if (!S9xNPGetData (NetPlay.Socket, header, 7) ||
361 header [0] != NP_SERV_MAGIC || header [1] != 0 ||
362 (header [2] & 0x1f) != NP_SERV_HELLO)
364 S9xNPSetError ("Error in 'HELLO' reply packet received from server.");
369 printf ("CLIENT: Got 'WELCOME' reply @%ld\n", S9xGetMilliTime () - START);
371 len = READ_LONG (&header [3]);
374 S9xNPSetError ("Error in 'HELLO' reply packet received from server.");
378 uint8 *data = new uint8 [len];
379 if (!S9xNPGetData (NetPlay.Socket, data, len - 7))
381 S9xNPSetError ("Error in 'HELLO' reply packet received from server.");
387 if (data [0] != NP_VERSION)
390 The Snes9X NetPlay server implements a different\n\
391 version of the protocol. Disconnecting.");
397 NetPlay.FrameCount = READ_LONG (&data [2]);
399 if (!(header [2] & 0x80) &&
400 strcmp ((char *) data + 4 + 2, NetPlay.ROMName) != 0)
402 if (!S9xNPLoadROMDialog ((char *) data + 4 + 2))
409 NetPlay.Player = data [1];
412 NetPlay.PendingWait4Sync = TRUE;
413 Settings.NetPlay = TRUE;
414 S9xNPResetJoypadReadPos ();
415 NetPlay.ServerSequenceNum = 1;
418 printf ("CLIENT: Sending 'READY' to server @%ld...\n", S9xGetMilliTime () - START);
420 S9xNPSetAction ("Sending 'READY' to the server...");
422 return (S9xNPSendReady ((header [2] & 0x80) ?
423 NP_CLNT_WAITING_FOR_ROM_IMAGE :
427 bool8 S9xNPSendReady (uint8 op)
431 *ptr++ = NP_CLNT_MAGIC;
432 *ptr++ = NetPlay.MySequenceNum++;
437 if (!S9xNPSendData (NetPlay.Socket, ready, 7))
440 S9xNPSetError ("Sending 'READY' message failed.");
447 bool8 S9xNPSendPause (bool8 paused)
450 printf ("CLIENT: Pause - %s @%ld\n", paused ? "YES" : "NO", S9xGetMilliTime () - START);
454 *ptr++ = NP_CLNT_MAGIC;
455 *ptr++ = NetPlay.MySequenceNum++;
456 *ptr++ = NP_CLNT_PAUSE | (paused ? 0x80 : 0);
460 if (!S9xNPSendData (NetPlay.Socket, pause, 7))
462 S9xNPSetError ("Sending 'PAUSE' message failed.");
471 void S9xNPClientLoop (void *)
473 NetPlay.Waiting4EmulationThread = FALSE;
477 S9xClearPause (PAUSE_NETPLAY_CONNECT);
478 while (NetPlay.Connected)
480 if (S9xNPWaitForHeartBeat ())
483 if (!ReleaseSemaphore (GUI.ClientSemaphore, 1, &prev))
486 printf ("CLIENT: ReleaseSemaphore failed - already hit max count (%d) %ld\n", NP_JOYPAD_HIST_SIZE, S9xGetMilliTime () - START);
488 S9xNPSetWarning ("NetPlay: Client may be out of sync with server.");
492 if (!NetPlay.Waiting4EmulationThread &&
493 prev == (int) NetPlay.MaxBehindFrameCount)
495 NetPlay.Waiting4EmulationThread = TRUE;
496 S9xNPSendPause (TRUE);
506 S9xClearPause (PAUSE_NETPLAY_CONNECT);
509 printf ("CLIENT: Client thread exiting @%ld\n", S9xGetMilliTime () - START);
514 bool8 S9xNPWaitForHeartBeat ()
516 uint8 header [3 + 4 + 4 * 5];
518 while (S9xNPGetData (NetPlay.Socket, header, 3 + 4))
520 if (header [0] != NP_SERV_MAGIC)
522 S9xNPSetError ("Bad magic value from server while waiting for heart-beat message\n");
526 if (header [1] != NetPlay.ServerSequenceNum)
529 sprintf (buf, "Unexpected message sequence number from server, expected %d, got %d\n", NetPlay.ServerSequenceNum, header [1]);
530 S9xNPSetWarning (buf);
531 NetPlay.ServerSequenceNum = header [1] + 1;
534 NetPlay.ServerSequenceNum++;
536 if ((header [2] & 0x1f) == NP_SERV_JOYPAD)
538 // Top 2 bits + 1 of opcode is joypad data count.
539 int num = (header [2] >> 6) + 1;
543 if (!S9xNPGetData (NetPlay.Socket, header + 3 + 4, num * 4))
545 S9xNPSetError ("Error while receiving 'JOYPAD' message.");
550 NetPlay.Frame [NetPlay.JoypadWriteInd] = READ_LONG (&header [3]);
552 for (int i = 0; i < num; i++)
554 NetPlay.Joypads [NetPlay.JoypadWriteInd][i] =
555 READ_LONG (&header [3 + 4 + i * sizeof (uint32)]);
557 NetPlay.Paused = (header [2] & 0x20) != 0;
559 NetPlay.JoypadWriteInd = (NetPlay.JoypadWriteInd + 1) % NP_JOYPAD_HIST_SIZE;
561 if (NetPlay.JoypadWriteInd != (NetPlay.JoypadReadInd + 1) % NP_JOYPAD_HIST_SIZE)
563 //printf ("(%d)", (NetPlay.JoypadWriteInd - NetPlay.JoypadReadInd) % NP_JOYPAD_HIST_SIZE); fflush (stdout);
565 //printf ("CLIENT: HB: @%d\n", S9xGetMilliTime () - START);
570 uint32 len = READ_LONG (&header [3]);
571 switch (header [2] & 0x1f)
575 printf ("CLIENT: RESET received @%ld\n", S9xGetMilliTime () - START);
577 S9xNPDiscardHeartbeats ();
579 NetPlay.FrameCount = READ_LONG (&header [3]);
580 S9xNPResetJoypadReadPos ();
584 NetPlay.Paused = (header [2] & 0x20) != 0;
586 case NP_SERV_LOAD_ROM:
588 printf ("CLIENT: LOAD_ROM received @%ld\n", S9xGetMilliTime () - START);
590 S9xNPDiscardHeartbeats ();
591 if (S9xNPLoadROM (len - 7))
592 S9xNPSendReady (NP_CLNT_LOADED_ROM);
594 case NP_SERV_ROM_IMAGE:
596 printf ("CLIENT: ROM_IMAGE received @%ld\n", S9xGetMilliTime () - START);
598 S9xNPDiscardHeartbeats ();
599 if (S9xNPGetROMImage (len - 7))
600 S9xNPSendReady (NP_CLNT_RECEIVED_ROM_IMAGE);
602 case NP_SERV_SRAM_DATA:
604 printf ("CLIENT: SRAM_DATA received @%ld\n", S9xGetMilliTime () - START);
606 S9xNPDiscardHeartbeats ();
607 S9xNPGetSRAMData (len - 7);
609 case NP_SERV_FREEZE_FILE:
611 printf ("CLIENT: FREEZE_FILE received @%ld\n", S9xGetMilliTime () - START);
613 S9xNPDiscardHeartbeats ();
614 S9xNPGetFreezeFile (len - 7);
615 S9xNPResetJoypadReadPos ();
620 printf ("CLIENT: UNKNOWN received @%ld\n", S9xGetMilliTime () - START);
632 bool8 S9xNPLoadROMDialog (const char *rom_name)
634 NetPlay.Answer = FALSE;
637 ResetEvent (NetPlay.ReplyEvent);
640 printf ("CLIENT: Asking GUI thread to open ROM load dialog...\n");
643 PostMessage (GUI.hWnd, WM_USER + 3, (uint32) rom_name, (uint32) rom_name);
646 printf ("CLIENT: Waiting for reply from GUI thread...\n");
649 WaitForSingleObject (NetPlay.ReplyEvent, INFINITE);
652 printf ("CLIENT: Got reply from GUI thread (%d)\n", NetPlay.Answer);
656 return (NetPlay.Answer);
659 bool8 S9xNPLoadROM (uint32 len)
661 uint8 *data = new uint8 [len];
663 S9xNPSetAction ("Receiving ROM name...");
664 if (!S9xNPGetData (NetPlay.Socket, data, len))
666 S9xNPSetError ("Error while receiving ROM name.");
672 S9xNPSetAction ("Opening LoadROM dialog...");
673 if (!S9xNPLoadROMDialog ((char *) data))
675 S9xNPSetError ("Disconnected from NetPlay server because you are playing a different game!");
684 bool8 S9xNPGetROMImage (uint32 len)
688 S9xNPSetAction ("Receiving ROM information...");
689 if (!S9xNPGetData (NetPlay.Socket, rom_info, 5))
691 S9xNPSetError ("Error while receiving ROM information.");
695 uint32 CalculatedSize = READ_LONG (&rom_info [1]);
697 printf ("CLIENT: Hi-ROM: %s, Size: %04x\n", rom_info [0] ? "Y" : "N", CalculatedSize);
699 if (CalculatedSize + 5 >= len ||
700 CalculatedSize >= CMemory::MAX_ROM_SIZE)
702 S9xNPSetError ("Size error in ROM image data received from server.");
707 Memory.HiROM = rom_info [0];
708 Memory.LoROM = !Memory.HiROM;
709 Memory.HeaderCount = 0;
710 Memory.CalculatedSize = CalculatedSize;
714 printf ("CLIENT: Receiving ROM image @%ld...\n", S9xGetMilliTime () - START);
716 S9xNPSetAction ("Receiving ROM image...");
717 if (!S9xNPGetData (NetPlay.Socket, Memory.ROM, Memory.CalculatedSize))
719 S9xNPSetError ("Error while receiving ROM image from server.");
720 Settings.StopEmulation = TRUE;
725 printf ("CLIENT: Receiving ROM filename @%ld...\n", S9xGetMilliTime () - START);
727 S9xNPSetAction ("Receiving ROM filename...");
728 uint32 filename_len = len - Memory.CalculatedSize - 5;
729 if (filename_len > _MAX_PATH ||
730 !S9xNPGetData (NetPlay.Socket, (uint8 *) Memory.ROMFilename, filename_len))
732 S9xNPSetError ("Error while receiving ROM filename from server.");
734 Settings.StopEmulation = TRUE;
737 Memory.InitROM (FALSE);
739 S9xNPResetJoypadReadPos ();
740 Settings.StopEmulation = FALSE;
743 PostMessage (GUI.hWnd, WM_NULL, 0, 0);
749 void S9xNPGetSRAMData (uint32 len)
753 S9xNPSetError ("Length error in S-RAM data received from server.");
757 S9xNPSetAction ("Receiving S-RAM data...");
758 if (len > 0 && !S9xNPGetData (NetPlay.Socket, ::SRAM, len))
760 S9xNPSetError ("Error while receiving S-RAM data from server.");
765 void S9xNPGetFreezeFile (uint32 len)
767 uint8 frame_count [4];
770 printf ("CLIENT: Receiving freeze file information @%ld...\n", S9xGetMilliTime () - START);
772 S9xNPSetAction ("Receiving freeze file information...");
773 if (!S9xNPGetData (NetPlay.Socket, frame_count, 4))
775 S9xNPSetError ("Error while receiving freeze file information from server.");
779 NetPlay.FrameCount = READ_LONG (frame_count);
782 printf ("CLIENT: Receiving freeze file @%ld...\n", S9xGetMilliTime () - START);
784 S9xNPSetAction ("Receiving freeze file...");
785 uint8 *data = new uint8 [len];
786 if (!S9xNPGetData (NetPlay.Socket, data, len - 4))
788 S9xNPSetError ("Error while receiving freeze file from server.");
794 //FIXME: Setting umask here wouldn't hurt.
798 char fname[] = "/tmp/snes9x_fztmpXXXXXX";
799 if ((fd = mkstemp(fname)) < 0)
801 if ((file = fdopen (fd, "wb")))
803 char fname [L_tmpnam];
806 if ((file = fopen (fname, "wb")))
809 if (fwrite (data, 1, len, file) == len)
812 if (!S9xUnfreezeGame (fname))
813 S9xNPSetError ("Unable to load freeze file just received.");
815 S9xNPSetError ("Failed to write to temporary freeze file.");
819 S9xNPSetError ("Failed to create temporary freeze file.");
822 S9xNPSetError ("Unable to get name for temporary freeze file.");
826 uint32 S9xNPGetJoypad (int which1)
828 if (Settings.NetPlay && which1 < 5)
829 return (NetPlay.Joypads [NetPlay.JoypadReadInd][which1]);
834 void S9xNPStepJoypadHistory ()
836 if ((NetPlay.JoypadReadInd + 1) % NP_JOYPAD_HIST_SIZE != NetPlay.JoypadWriteInd)
838 NetPlay.JoypadReadInd = (NetPlay.JoypadReadInd + 1) % NP_JOYPAD_HIST_SIZE;
839 if (NetPlay.FrameCount != NetPlay.Frame [NetPlay.JoypadReadInd])
841 S9xNPSetWarning ("This Snes9X session may be out of sync with the server.");
843 printf ("*** CLIENT: client out of sync with server (%d, %d) @%ld\n", NetPlay.FrameCount, NetPlay.Frame [NetPlay.JoypadReadInd], S9xGetMilliTime () - START);
850 printf ("*** CLIENT: S9xNPStepJoypadHistory NOT OK@%ld\n", S9xGetMilliTime () - START);
856 void S9xNPResetJoypadReadPos ()
859 printf ("CLIENT: ResetJoyReadPos @%ld\n", S9xGetMilliTime () - START); fflush (stdout);
861 NetPlay.JoypadWriteInd = 0;
862 NetPlay.JoypadReadInd = NP_JOYPAD_HIST_SIZE - 1;
863 for (int h = 0; h < NP_JOYPAD_HIST_SIZE; h++)
864 memset ((void *) &NetPlay.Joypads [h], 0, sizeof (NetPlay.Joypads [0]));
867 bool8 S9xNPSendJoypadUpdate (uint32 joypad)
872 *ptr++ = NP_CLNT_MAGIC;
873 *ptr++ = NetPlay.MySequenceNum++;
874 *ptr++ = NP_CLNT_JOYPAD;
876 joypad |= 0x80000000;
878 WRITE_LONG (ptr, joypad);
879 if (!S9xNPSendData (NetPlay.Socket, data, 7))
881 S9xNPSetError ("Error while sending joypad data server.");
888 void S9xNPDisconnect ()
890 close (NetPlay.Socket);
892 NetPlay.Connected = FALSE;
893 Settings.NetPlay = FALSE;
896 bool8 S9xNPSendData (int socket, const uint8 *data, int length)
899 const uint8 *ptr = data;
901 NetPlay.PercentageComplete = 0;
910 // Write the data in small chunks, allowing this thread to spot an
911 // abort request from another thread.
915 int sent = write (socket, (char *) ptr, num_bytes);
923 || errno == EWOULDBLOCK
928 printf ("CLIENT: EINTR, EAGAIN or EWOULDBLOCK while sending data @%ld\n", S9xGetMilliTime () - START);
940 NetPlay.PercentageComplete = (uint8) (((length - len) * 100) / length);
946 bool8 S9xNPGetData (int socket, uint8 *data, int length)
950 int chunk = length / 50;
955 NetPlay.PercentageComplete = 0;
963 // Read the data in small chunks, allowing this thread to spot an
964 // abort request from another thread.
965 if (num_bytes > chunk)
968 int got = read (socket, (char *) ptr, num_bytes);
976 || errno == EWOULDBLOCK
978 #ifdef WSAEWOULDBLOCK
979 || errno == WSAEWOULDBLOCK
984 printf ("CLIENT: EINTR, EAGAIN or EWOULDBLOCK while receiving data @%ld\n", S9xGetMilliTime () - START);
989 if (errno != WSAEMSGSIZE)
995 printf ("CLIENT: WSAEMSGSIZE, actual bytes %d while receiving data @%ld\n", got, S9xGetMilliTime () - START);
1009 if (!Settings.NetPlayServer && length > 1024)
1011 NetPlay.PercentageComplete = (uint8) (((length - len) * 100) / length);
1013 PostMessage (GUI.hWnd, WM_USER, NetPlay.PercentageComplete,
1014 NetPlay.PercentageComplete);
1024 bool8 S9xNPInitialise ()
1027 static bool8 initialised = FALSE;
1035 START = S9xGetMilliTime ();
1037 printf ("CLIENT/SERVER: Initialising WinSock @%ld\n", S9xGetMilliTime () - START);
1039 S9xNPSetAction ("Initialising Windows sockets interface...");
1040 if (WSAStartup (MAKEWORD (1, 0), &data) != 0)
1042 S9xNPSetError ("Call to init Windows sockets failed. Do you have WinSock2 installed?");
1050 void S9xNPDiscardHeartbeats ()
1052 // Discard any pending heartbeats and wait for any frame that is currently
1053 // being emulated to complete.
1055 printf ("CLIENT: DiscardHeartbeats @%ld, finished @", S9xGetMilliTime () - START);
1060 while (WaitForSingleObject (GUI.ClientSemaphore, 200) == WAIT_OBJECT_0)
1065 printf ("%ld\n", S9xGetMilliTime () - START);
1067 NetPlay.Waiting4EmulationThread = FALSE;
1070 void S9xNPSetAction (const char *action, bool8 force)
1072 if (force || !Settings.NetPlayServer)
1074 strncpy (NetPlay.ActionMsg, action, NP_MAX_ACTION_LEN - 1);
1075 NetPlay.ActionMsg [NP_MAX_ACTION_LEN - 1] = 0;
1077 PostMessage (GUI.hWnd, WM_USER, 0, 0);
1083 void S9xNPSetError (const char *error)
1085 strncpy (NetPlay.ErrorMsg, error, NP_MAX_ACTION_LEN - 1);
1086 NetPlay.ErrorMsg [NP_MAX_ACTION_LEN - 1] = 0;
1088 PostMessage (GUI.hWnd, WM_USER + 1, 0, 0);
1093 void S9xNPSetWarning (const char *warning)
1095 strncpy (NetPlay.WarningMsg, warning, NP_MAX_ACTION_LEN - 1);
1096 NetPlay.WarningMsg [NP_MAX_ACTION_LEN - 1] = 0;
1098 PostMessage (GUI.hWnd, WM_USER + 2, 0, 0);