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"
195 void S9xNPClientLoop (void *);
196 bool8 S9xNPLoadROM (uint32 len);
197 bool8 S9xNPLoadROMDialog (const char *);
198 bool8 S9xNPGetROMImage (uint32 len);
199 void S9xNPGetSRAMData (uint32 len);
200 void S9xNPGetFreezeFile (uint32 len);
202 unsigned long START = 0;
204 bool8 S9xNPConnectToServer (const char *hostname, int port,
205 const char *rom_name)
207 if (!S9xNPInitialise ())
212 NetPlay.MySequenceNum = 0;
213 NetPlay.ServerSequenceNum = 0;
214 NetPlay.Connected = FALSE;
215 NetPlay.Abort = FALSE;
217 NetPlay.Paused = FALSE;
218 NetPlay.PercentageComplete = 0;
220 if (NetPlay.ServerHostName)
221 free ((char *) NetPlay.ServerHostName);
222 NetPlay.ServerHostName = strdup (hostname);
224 free ((char *) NetPlay.ROMName);
225 NetPlay.ROMName = strdup (rom_name);
227 NetPlay.PendingWait4Sync = FALSE;
230 if (GUI.ClientSemaphore == NULL)
231 GUI.ClientSemaphore = CreateSemaphore (NULL, 0, NP_JOYPAD_HIST_SIZE, NULL);
233 if (NetPlay.ReplyEvent == NULL)
234 NetPlay.ReplyEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
236 _beginthread (S9xNPClientLoop, 0, NULL);
242 bool8 S9xNPConnect ()
244 struct sockaddr_in address;
245 struct hostent *hostinfo;
248 address.sin_family = AF_INET;
249 address.sin_port = htons (NetPlay.Port);
251 printf ("CLIENT: Looking up server's hostname (%s) @%ld\n", NetPlay.ServerHostName, S9xGetMilliTime () - START);
253 S9xNPSetAction ("Looking up server's hostname...");
254 if ((int) (addr = inet_addr (NetPlay.ServerHostName)) == -1)
256 if ((hostinfo = gethostbyname (NetPlay.ServerHostName)))
258 memcpy ((char *)&address.sin_addr, hostinfo->h_addr,
264 Unable to look up server's IP address from hostname.\n\n\
265 Unknown hostname or may be your nameserver isn't set\n\
272 memcpy ((char *)&address.sin_addr, &addr, sizeof (addr));
276 printf ("CLIENT: Creating socket @%ld\n", S9xGetMilliTime () - START);
278 S9xNPSetAction ("Creating network socket...");
279 if ((NetPlay.Socket = socket (AF_INET, SOCK_STREAM, 0)) < 0)
281 S9xNPSetError ("Creating network socket failed.");
286 printf ("CLIENT: Trying to connect to server @%ld...\n", S9xGetMilliTime () - START);
288 S9xNPSetAction ("Trying to connect to Snes9X server...");
290 if (connect (NetPlay.Socket, (struct sockaddr *) &address, sizeof (address)) < 0)
294 if (WSAGetLastError () == WSAECONNREFUSED)
296 if (errno == ECONNREFUSED)
300 Connection to remote server socket refused:\n\n\
301 Is there actually a Snes9X NetPlay server running\n\
302 on the remote machine on this port?");
306 sprintf (buf, "Connection to server failed with error number %d",
317 NetPlay.Connected = TRUE;
320 printf ("CLIENT: Sending 'HELLO' message @%ld...\n", S9xGetMilliTime () - START);
322 S9xNPSetAction ("Sending 'HELLO' message...");
323 /* Send the server a HELLO packet*/
324 int len = 7 + 4 + strlen (NetPlay.ROMName) + 1;
325 uint8 *tmp = new uint8 [len];
328 *ptr++ = NP_CLNT_MAGIC;
329 *ptr++ = NetPlay.MySequenceNum++;
330 *ptr++ = NP_CLNT_HELLO;
331 WRITE_LONG (ptr, len);
334 uint32 ft = Settings.FrameTime * 1000;
336 WRITE_LONG (ptr, ft);
338 WRITE_LONG (ptr, Settings.FrameTime);
341 strcpy ((char *) ptr, NetPlay.ROMName);
343 if (!S9xNPSendData (NetPlay.Socket, tmp, len))
345 S9xNPSetError ("Sending 'HELLO' message failed.");
353 printf ("CLIENT: Waiting for 'WELCOME' reply from server @%ld...\n", S9xGetMilliTime () - START);
355 S9xNPSetAction ("Waiting for 'HELLO' reply from server...");
359 if (!S9xNPGetData (NetPlay.Socket, header, 7) ||
360 header [0] != NP_SERV_MAGIC || header [1] != 0 ||
361 (header [2] & 0x1f) != NP_SERV_HELLO)
363 S9xNPSetError ("Error in 'HELLO' reply packet received from server.");
368 printf ("CLIENT: Got 'WELCOME' reply @%ld\n", S9xGetMilliTime () - START);
370 len = READ_LONG (&header [3]);
373 S9xNPSetError ("Error in 'HELLO' reply packet received from server.");
377 uint8 *data = new uint8 [len];
378 if (!S9xNPGetData (NetPlay.Socket, data, len - 7))
380 S9xNPSetError ("Error in 'HELLO' reply packet received from server.");
386 if (data [0] != NP_VERSION)
389 The Snes9X NetPlay server implements a different\n\
390 version of the protocol. Disconnecting.");
396 NetPlay.FrameCount = READ_LONG (&data [2]);
398 if (!(header [2] & 0x80) &&
399 strcmp ((char *) data + 4 + 2, NetPlay.ROMName) != 0)
401 if (!S9xNPLoadROMDialog ((char *) data + 4 + 2))
408 NetPlay.Player = data [1];
411 NetPlay.PendingWait4Sync = TRUE;
412 Settings.NetPlay = TRUE;
413 S9xNPResetJoypadReadPos ();
414 NetPlay.ServerSequenceNum = 1;
417 printf ("CLIENT: Sending 'READY' to server @%ld...\n", S9xGetMilliTime () - START);
419 S9xNPSetAction ("Sending 'READY' to the server...");
421 return (S9xNPSendReady ((header [2] & 0x80) ?
422 NP_CLNT_WAITING_FOR_ROM_IMAGE :
426 bool8 S9xNPSendReady (uint8 op)
430 *ptr++ = NP_CLNT_MAGIC;
431 *ptr++ = NetPlay.MySequenceNum++;
436 if (!S9xNPSendData (NetPlay.Socket, ready, 7))
439 S9xNPSetError ("Sending 'READY' message failed.");
446 bool8 S9xNPSendPause (bool8 paused)
449 printf ("CLIENT: Pause - %s @%ld\n", paused ? "YES" : "NO", S9xGetMilliTime () - START);
453 *ptr++ = NP_CLNT_MAGIC;
454 *ptr++ = NetPlay.MySequenceNum++;
455 *ptr++ = NP_CLNT_PAUSE | (paused ? 0x80 : 0);
459 if (!S9xNPSendData (NetPlay.Socket, pause, 7))
461 S9xNPSetError ("Sending 'PAUSE' message failed.");
470 void S9xNPClientLoop (void *)
472 NetPlay.Waiting4EmulationThread = FALSE;
476 S9xClearPause (PAUSE_NETPLAY_CONNECT);
477 while (NetPlay.Connected)
479 if (S9xNPWaitForHeartBeat ())
482 if (!ReleaseSemaphore (GUI.ClientSemaphore, 1, &prev))
485 printf ("CLIENT: ReleaseSemaphore failed - already hit max count (%d) %ld\n", NP_JOYPAD_HIST_SIZE, S9xGetMilliTime () - START);
487 S9xNPSetWarning ("NetPlay: Client may be out of sync with server.");
491 if (!NetPlay.Waiting4EmulationThread &&
492 prev == (int) NetPlay.MaxBehindFrameCount)
494 NetPlay.Waiting4EmulationThread = TRUE;
495 S9xNPSendPause (TRUE);
505 S9xClearPause (PAUSE_NETPLAY_CONNECT);
508 printf ("CLIENT: Client thread exiting @%ld\n", S9xGetMilliTime () - START);
513 bool8 S9xNPWaitForHeartBeat ()
515 uint8 header [3 + 4 + 4 * 5];
517 while (S9xNPGetData (NetPlay.Socket, header, 3 + 4))
519 if (header [0] != NP_SERV_MAGIC)
521 S9xNPSetError ("Bad magic value from server while waiting for heart-beat message\n");
525 if (header [1] != NetPlay.ServerSequenceNum)
528 sprintf (buf, "Unexpected message sequence number from server, expected %d, got %d\n", NetPlay.ServerSequenceNum, header [1]);
529 S9xNPSetWarning (buf);
530 NetPlay.ServerSequenceNum = header [1] + 1;
533 NetPlay.ServerSequenceNum++;
535 if ((header [2] & 0x1f) == NP_SERV_JOYPAD)
537 // Top 2 bits + 1 of opcode is joypad data count.
538 int num = (header [2] >> 6) + 1;
542 if (!S9xNPGetData (NetPlay.Socket, header + 3 + 4, num * 4))
544 S9xNPSetError ("Error while receiving 'JOYPAD' message.");
549 NetPlay.Frame [NetPlay.JoypadWriteInd] = READ_LONG (&header [3]);
551 for (int i = 0; i < num; i++)
553 NetPlay.Joypads [NetPlay.JoypadWriteInd][i] =
554 READ_LONG (&header [3 + 4 + i * sizeof (uint32)]);
556 NetPlay.Paused = (header [2] & 0x20) != 0;
558 NetPlay.JoypadWriteInd = (NetPlay.JoypadWriteInd + 1) % NP_JOYPAD_HIST_SIZE;
560 if (NetPlay.JoypadWriteInd != (NetPlay.JoypadReadInd + 1) % NP_JOYPAD_HIST_SIZE)
562 //printf ("(%d)", (NetPlay.JoypadWriteInd - NetPlay.JoypadReadInd) % NP_JOYPAD_HIST_SIZE); fflush (stdout);
564 //printf ("CLIENT: HB: @%d\n", S9xGetMilliTime () - START);
569 uint32 len = READ_LONG (&header [3]);
570 switch (header [2] & 0x1f)
574 printf ("CLIENT: RESET received @%ld\n", S9xGetMilliTime () - START);
576 S9xNPDiscardHeartbeats ();
578 NetPlay.FrameCount = READ_LONG (&header [3]);
579 S9xNPResetJoypadReadPos ();
583 NetPlay.Paused = (header [2] & 0x20) != 0;
585 case NP_SERV_LOAD_ROM:
587 printf ("CLIENT: LOAD_ROM received @%ld\n", S9xGetMilliTime () - START);
589 S9xNPDiscardHeartbeats ();
590 if (S9xNPLoadROM (len - 7))
591 S9xNPSendReady (NP_CLNT_LOADED_ROM);
593 case NP_SERV_ROM_IMAGE:
595 printf ("CLIENT: ROM_IMAGE received @%ld\n", S9xGetMilliTime () - START);
597 S9xNPDiscardHeartbeats ();
598 if (S9xNPGetROMImage (len - 7))
599 S9xNPSendReady (NP_CLNT_RECEIVED_ROM_IMAGE);
601 case NP_SERV_SRAM_DATA:
603 printf ("CLIENT: SRAM_DATA received @%ld\n", S9xGetMilliTime () - START);
605 S9xNPDiscardHeartbeats ();
606 S9xNPGetSRAMData (len - 7);
608 case NP_SERV_FREEZE_FILE:
610 printf ("CLIENT: FREEZE_FILE received @%ld\n", S9xGetMilliTime () - START);
612 S9xNPDiscardHeartbeats ();
613 S9xNPGetFreezeFile (len - 7);
614 S9xNPResetJoypadReadPos ();
619 printf ("CLIENT: UNKNOWN received @%ld\n", S9xGetMilliTime () - START);
631 bool8 S9xNPLoadROMDialog (const char *rom_name)
633 NetPlay.Answer = FALSE;
636 ResetEvent (NetPlay.ReplyEvent);
639 printf ("CLIENT: Asking GUI thread to open ROM load dialog...\n");
642 PostMessage (GUI.hWnd, WM_USER + 3, (uint32) rom_name, (uint32) rom_name);
645 printf ("CLIENT: Waiting for reply from GUI thread...\n");
648 WaitForSingleObject (NetPlay.ReplyEvent, INFINITE);
651 printf ("CLIENT: Got reply from GUI thread (%d)\n", NetPlay.Answer);
655 return (NetPlay.Answer);
658 bool8 S9xNPLoadROM (uint32 len)
660 uint8 *data = new uint8 [len];
662 S9xNPSetAction ("Receiving ROM name...");
663 if (!S9xNPGetData (NetPlay.Socket, data, len))
665 S9xNPSetError ("Error while receiving ROM name.");
671 S9xNPSetAction ("Opening LoadROM dialog...");
672 if (!S9xNPLoadROMDialog ((char *) data))
674 S9xNPSetError ("Disconnected from NetPlay server because you are playing a different game!");
683 bool8 S9xNPGetROMImage (uint32 len)
687 S9xNPSetAction ("Receiving ROM information...");
688 if (!S9xNPGetData (NetPlay.Socket, rom_info, 5))
690 S9xNPSetError ("Error while receiving ROM information.");
694 uint32 CalculatedSize = READ_LONG (&rom_info [1]);
696 printf ("CLIENT: Hi-ROM: %s, Size: %04x\n", rom_info [0] ? "Y" : "N", CalculatedSize);
698 if (CalculatedSize + 5 >= len ||
699 CalculatedSize >= CMemory::MAX_ROM_SIZE)
701 S9xNPSetError ("Size error in ROM image data received from server.");
706 Memory.HiROM = rom_info [0];
707 Memory.LoROM = !Memory.HiROM;
708 Memory.HeaderCount = 0;
709 Memory.CalculatedSize = CalculatedSize;
713 printf ("CLIENT: Receiving ROM image @%ld...\n", S9xGetMilliTime () - START);
715 S9xNPSetAction ("Receiving ROM image...");
716 if (!S9xNPGetData (NetPlay.Socket, Memory.ROM, Memory.CalculatedSize))
718 S9xNPSetError ("Error while receiving ROM image from server.");
719 Settings.StopEmulation = TRUE;
724 printf ("CLIENT: Receiving ROM filename @%ld...\n", S9xGetMilliTime () - START);
726 S9xNPSetAction ("Receiving ROM filename...");
727 uint32 filename_len = len - Memory.CalculatedSize - 5;
728 if (filename_len > _MAX_PATH ||
729 !S9xNPGetData (NetPlay.Socket, (uint8 *) Memory.ROMFilename, filename_len))
731 S9xNPSetError ("Error while receiving ROM filename from server.");
733 Settings.StopEmulation = TRUE;
736 Memory.InitROM (FALSE);
738 S9xNPResetJoypadReadPos ();
739 Settings.StopEmulation = FALSE;
742 PostMessage (GUI.hWnd, WM_NULL, 0, 0);
748 void S9xNPGetSRAMData (uint32 len)
752 S9xNPSetError ("Length error in S-RAM data received from server.");
756 S9xNPSetAction ("Receiving S-RAM data...");
757 if (len > 0 && !S9xNPGetData (NetPlay.Socket, ::SRAM, len))
759 S9xNPSetError ("Error while receiving S-RAM data from server.");
764 void S9xNPGetFreezeFile (uint32 len)
766 uint8 frame_count [4];
769 printf ("CLIENT: Receiving freeze file information @%ld...\n", S9xGetMilliTime () - START);
771 S9xNPSetAction ("Receiving freeze file information...");
772 if (!S9xNPGetData (NetPlay.Socket, frame_count, 4))
774 S9xNPSetError ("Error while receiving freeze file information from server.");
778 NetPlay.FrameCount = READ_LONG (frame_count);
781 printf ("CLIENT: Receiving freeze file @%ld...\n", S9xGetMilliTime () - START);
783 S9xNPSetAction ("Receiving freeze file...");
784 uint8 *data = new uint8 [len];
785 if (!S9xNPGetData (NetPlay.Socket, data, len - 4))
787 S9xNPSetError ("Error while receiving freeze file from server.");
793 //FIXME: Setting umask here wouldn't hurt.
797 char fname[] = "/tmp/snes9x_fztmpXXXXXX";
798 if ((fd = mkstemp(fname)) < 0)
800 if ((file = fdopen (fd, "wb")))
802 char fname [L_tmpnam];
805 if ((file = fopen (fname, "wb")))
808 if (fwrite (data, 1, len, file) == len)
811 if (!S9xUnfreezeGame (fname))
812 S9xNPSetError ("Unable to load freeze file just received.");
814 S9xNPSetError ("Failed to write to temporary freeze file.");
818 S9xNPSetError ("Failed to create temporary freeze file.");
821 S9xNPSetError ("Unable to get name for temporary freeze file.");
825 uint32 S9xNPGetJoypad (int which1)
827 if (Settings.NetPlay && which1 < 5)
828 return (NetPlay.Joypads [NetPlay.JoypadReadInd][which1]);
833 void S9xNPStepJoypadHistory ()
835 if ((NetPlay.JoypadReadInd + 1) % NP_JOYPAD_HIST_SIZE != NetPlay.JoypadWriteInd)
837 NetPlay.JoypadReadInd = (NetPlay.JoypadReadInd + 1) % NP_JOYPAD_HIST_SIZE;
838 if (NetPlay.FrameCount != NetPlay.Frame [NetPlay.JoypadReadInd])
840 S9xNPSetWarning ("This Snes9X session may be out of sync with the server.");
842 printf ("*** CLIENT: client out of sync with server (%d, %d) @%ld\n", NetPlay.FrameCount, NetPlay.Frame [NetPlay.JoypadReadInd], S9xGetMilliTime () - START);
849 printf ("*** CLIENT: S9xNPStepJoypadHistory NOT OK@%ld\n", S9xGetMilliTime () - START);
855 void S9xNPResetJoypadReadPos ()
858 printf ("CLIENT: ResetJoyReadPos @%ld\n", S9xGetMilliTime () - START); fflush (stdout);
860 NetPlay.JoypadWriteInd = 0;
861 NetPlay.JoypadReadInd = NP_JOYPAD_HIST_SIZE - 1;
862 for (int h = 0; h < NP_JOYPAD_HIST_SIZE; h++)
863 memset ((void *) &NetPlay.Joypads [h], 0, sizeof (NetPlay.Joypads [0]));
866 bool8 S9xNPSendJoypadUpdate (uint32 joypad)
871 *ptr++ = NP_CLNT_MAGIC;
872 *ptr++ = NetPlay.MySequenceNum++;
873 *ptr++ = NP_CLNT_JOYPAD;
875 joypad |= 0x80000000;
877 WRITE_LONG (ptr, joypad);
878 if (!S9xNPSendData (NetPlay.Socket, data, 7))
880 S9xNPSetError ("Error while sending joypad data server.");
887 void S9xNPDisconnect ()
889 close (NetPlay.Socket);
891 NetPlay.Connected = FALSE;
892 Settings.NetPlay = FALSE;
895 bool8 S9xNPSendData (int socket, const uint8 *data, int length)
898 const uint8 *ptr = data;
900 NetPlay.PercentageComplete = 0;
909 // Write the data in small chunks, allowing this thread to spot an
910 // abort request from another thread.
914 int sent = write (socket, (char *) ptr, num_bytes);
922 || errno == EWOULDBLOCK
927 printf ("CLIENT: EINTR, EAGAIN or EWOULDBLOCK while sending data @%ld\n", S9xGetMilliTime () - START);
939 NetPlay.PercentageComplete = (uint8) (((length - len) * 100) / length);
945 bool8 S9xNPGetData (int socket, uint8 *data, int length)
949 int chunk = length / 50;
954 NetPlay.PercentageComplete = 0;
962 // Read the data in small chunks, allowing this thread to spot an
963 // abort request from another thread.
964 if (num_bytes > chunk)
967 int got = read (socket, (char *) ptr, num_bytes);
975 || errno == EWOULDBLOCK
977 #ifdef WSAEWOULDBLOCK
978 || errno == WSAEWOULDBLOCK
983 printf ("CLIENT: EINTR, EAGAIN or EWOULDBLOCK while receiving data @%ld\n", S9xGetMilliTime () - START);
988 if (errno != WSAEMSGSIZE)
994 printf ("CLIENT: WSAEMSGSIZE, actual bytes %d while receiving data @%ld\n", got, S9xGetMilliTime () - START);
1008 if (!Settings.NetPlayServer && length > 1024)
1010 NetPlay.PercentageComplete = (uint8) (((length - len) * 100) / length);
1012 PostMessage (GUI.hWnd, WM_USER, NetPlay.PercentageComplete,
1013 NetPlay.PercentageComplete);
1023 bool8 S9xNPInitialise ()
1026 static bool8 initialised = FALSE;
1034 START = S9xGetMilliTime ();
1036 printf ("CLIENT/SERVER: Initialising WinSock @%ld\n", S9xGetMilliTime () - START);
1038 S9xNPSetAction ("Initialising Windows sockets interface...");
1039 if (WSAStartup (MAKEWORD (1, 0), &data) != 0)
1041 S9xNPSetError ("Call to init Windows sockets failed. Do you have WinSock2 installed?");
1049 void S9xNPDiscardHeartbeats ()
1051 // Discard any pending heartbeats and wait for any frame that is currently
1052 // being emulated to complete.
1054 printf ("CLIENT: DiscardHeartbeats @%ld, finished @", S9xGetMilliTime () - START);
1059 while (WaitForSingleObject (GUI.ClientSemaphore, 200) == WAIT_OBJECT_0)
1064 printf ("%ld\n", S9xGetMilliTime () - START);
1066 NetPlay.Waiting4EmulationThread = FALSE;
1069 void S9xNPSetAction (const char *action, bool8 force)
1071 if (force || !Settings.NetPlayServer)
1073 strncpy (NetPlay.ActionMsg, action, NP_MAX_ACTION_LEN - 1);
1074 NetPlay.ActionMsg [NP_MAX_ACTION_LEN - 1] = 0;
1076 PostMessage (GUI.hWnd, WM_USER, 0, 0);
1082 void S9xNPSetError (const char *error)
1084 strncpy (NetPlay.ErrorMsg, error, NP_MAX_ACTION_LEN - 1);
1085 NetPlay.ErrorMsg [NP_MAX_ACTION_LEN - 1] = 0;
1087 PostMessage (GUI.hWnd, WM_USER + 1, 0, 0);
1092 void S9xNPSetWarning (const char *warning)
1094 strncpy (NetPlay.WarningMsg, warning, NP_MAX_ACTION_LEN - 1);
1095 NetPlay.WarningMsg [NP_MAX_ACTION_LEN - 1] = 0;
1097 PostMessage (GUI.hWnd, WM_USER + 2, 0, 0);