diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | source/netplay.cpp | 1048 | ||||
-rw-r--r-- | source/server.cpp | 1303 |
3 files changed, 2 insertions, 2353 deletions
@@ -43,10 +43,10 @@ CPP_SOURCES = source/apu.cpp source/apudebug.cpp source/c4.cpp \ source/dma.cpp source/dsp1.cpp \
source/fxdbg.cpp source/fxemu.cpp source/fxinst.cpp \
source/gfx.cpp source/globals.cpp source/loadzip.cpp \
- source/memmap.cpp source/movie.cpp source/netplay.cpp \
+ source/memmap.cpp source/movie.cpp \
source/obc1.cpp source/ppu.cpp \
source/sa1.cpp source/sa1cpu.cpp source/screenshot.cpp \
- source/sdd1.cpp source/sdd1emu.cpp source/server.cpp \
+ source/sdd1.cpp source/sdd1emu.cpp \
source/seta010.cpp source/seta011.cpp source/seta018.cpp \
source/seta.cpp source/snaporig.cpp source/snapshot.cpp \
source/soundux.cpp \
diff --git a/source/netplay.cpp b/source/netplay.cpp deleted file mode 100644 index 753f088..0000000 --- a/source/netplay.cpp +++ /dev/null @@ -1,1048 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - Kris Bleakley - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, John Weidman, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - Specific ports contains the works of other authors. See headers in - individual files. - - Snes9x homepage: http://www.snes9x.com - - Permission to use, copy, modify and distribute Snes9x in both binary and - source form, for non-commercial purposes, is hereby granted without fee, - providing that this license information and copyright notice appear with - all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes - charging money for Snes9x or software derived from Snes9x. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. -*******************************************************************************/ - -#ifdef NETPLAY_SUPPORT - -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <memory.h> -#include <sys/types.h> - -#ifndef __WIN32__ -#include <unistd.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/stat.h> -#endif - -#if defined (__WIN32__) -#include <winsock.h> -#include <process.h> - -#define ioctl ioctlsocket -#define close closesocket -#define read(a,b,c) recv(a, b, c, 0) -#define write(a,b,c) send(a, b, c, 0) -#else - -#include <netdb.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <sys/param.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#ifdef __SVR4 -#include <sys/stropts.h> -#endif -#endif - -#ifdef USE_THREADS -#include <pthread.h> -#include <sched.h> -#include <semaphore.h> -#endif - -#include "snes9x.h" -#include "cpuexec.h" -#include "netplay.h" -#include "memmap.h" -#include "snapshot.h" -#include "display.h" - -void S9xNPClientLoop (void *); -bool8 S9xNPLoadROM (uint32 len); -bool8 S9xNPLoadROMDialog (const char *); -bool8 S9xNPGetROMImage (uint32 len); -void S9xNPGetSRAMData (uint32 len); -void S9xNPGetFreezeFile (uint32 len); - -unsigned long START = 0; - -bool8 S9xNPConnectToServer (const char *hostname, int port, - const char *rom_name) -{ - if (!S9xNPInitialise ()) - return (FALSE); - - S9xNPDisconnect (); - - NetPlay.MySequenceNum = 0; - NetPlay.ServerSequenceNum = 0; - NetPlay.Connected = FALSE; - NetPlay.Abort = FALSE; - NetPlay.Player = 0; - NetPlay.Paused = FALSE; - NetPlay.PercentageComplete = 0; - NetPlay.Socket = 0; - if (NetPlay.ServerHostName) - free ((char *) NetPlay.ServerHostName); - NetPlay.ServerHostName = strdup (hostname); - if (NetPlay.ROMName) - free ((char *) NetPlay.ROMName); - NetPlay.ROMName = strdup (rom_name); - NetPlay.Port = port; - NetPlay.PendingWait4Sync = FALSE; - -#ifdef __WIN32__ - if (GUI.ClientSemaphore == NULL) - GUI.ClientSemaphore = CreateSemaphore (NULL, 0, NP_JOYPAD_HIST_SIZE, NULL); - - if (NetPlay.ReplyEvent == NULL) - NetPlay.ReplyEvent = CreateEvent (NULL, FALSE, FALSE, NULL); - - _beginthread (S9xNPClientLoop, 0, NULL); -#endif - - return (TRUE); -} - -bool8 S9xNPConnect () -{ - struct sockaddr_in address; - struct hostent *hostinfo; - unsigned int addr; - - address.sin_family = AF_INET; - address.sin_port = htons (NetPlay.Port); -#ifdef NP_DEBUG - printf ("CLIENT: Looking up server's hostname (%s) @%ld\n", NetPlay.ServerHostName, S9xGetMilliTime () - START); -#endif - S9xNPSetAction ("Looking up server's hostname..."); - if ((int) (addr = inet_addr (NetPlay.ServerHostName)) == -1) - { - if ((hostinfo = gethostbyname (NetPlay.ServerHostName))) - { - memcpy ((char *)&address.sin_addr, hostinfo->h_addr, - hostinfo->h_length); - } - else - { - S9xNPSetError ("\ -Unable to look up server's IP address from hostname.\n\n\ -Unknown hostname or may be your nameserver isn't set\n\ -up correctly?"); - return (FALSE); - } - } - else - { - memcpy ((char *)&address.sin_addr, &addr, sizeof (addr)); - } - -#ifdef NP_DEBUG - printf ("CLIENT: Creating socket @%ld\n", S9xGetMilliTime () - START); -#endif - S9xNPSetAction ("Creating network socket..."); - if ((NetPlay.Socket = socket (AF_INET, SOCK_STREAM, 0)) < 0) - { - S9xNPSetError ("Creating network socket failed."); - return (FALSE); - } - -#ifdef NP_DEBUG - printf ("CLIENT: Trying to connect to server @%ld...\n", S9xGetMilliTime () - START); -#endif - S9xNPSetAction ("Trying to connect to Snes9X server..."); - - if (connect (NetPlay.Socket, (struct sockaddr *) &address, sizeof (address)) < 0) - { - char buf [100]; -#ifdef __WIN32__ - if (WSAGetLastError () == WSAECONNREFUSED) -#else - if (errno == ECONNREFUSED) -#endif - { - S9xNPSetError ("\ -Connection to remote server socket refused:\n\n\ -Is there actually a Snes9X NetPlay server running\n\ -on the remote machine on this port?"); - } - else - { - sprintf (buf, "Connection to server failed with error number %d", -#ifdef __WIN32__ - WSAGetLastError () -#else - errno -#endif - ); - S9xNPDisconnect (); - } - return (FALSE); - } - NetPlay.Connected = TRUE; - -#ifdef NP_DEBUG - printf ("CLIENT: Sending 'HELLO' message @%ld...\n", S9xGetMilliTime () - START); -#endif - S9xNPSetAction ("Sending 'HELLO' message..."); - /* Send the server a HELLO packet*/ - int len = 7 + 4 + strlen (NetPlay.ROMName) + 1; - uint8 *tmp = new uint8 [len]; - uint8 *ptr = tmp; - - *ptr++ = NP_CLNT_MAGIC; - *ptr++ = NetPlay.MySequenceNum++; - *ptr++ = NP_CLNT_HELLO; - WRITE_LONG (ptr, len); - ptr += 4; -#ifdef __WIN32__ - uint32 ft = Settings.FrameTime * 1000; - - WRITE_LONG (ptr, ft); -#else - WRITE_LONG (ptr, Settings.FrameTime); -#endif - ptr += 4; - strcpy ((char *) ptr, NetPlay.ROMName); - - if (!S9xNPSendData (NetPlay.Socket, tmp, len)) - { - S9xNPSetError ("Sending 'HELLO' message failed."); - S9xNPDisconnect (); - delete tmp; - return (FALSE); - } - delete tmp; - -#ifdef NP_DEBUG - printf ("CLIENT: Waiting for 'WELCOME' reply from server @%ld...\n", S9xGetMilliTime () - START); -#endif - S9xNPSetAction ("Waiting for 'HELLO' reply from server..."); - - uint8 header [7]; - - if (!S9xNPGetData (NetPlay.Socket, header, 7) || - header [0] != NP_SERV_MAGIC || header [1] != 0 || - (header [2] & 0x1f) != NP_SERV_HELLO) - { - S9xNPSetError ("Error in 'HELLO' reply packet received from server."); - S9xNPDisconnect (); - return (FALSE); - } -#ifdef NP_DEBUG - printf ("CLIENT: Got 'WELCOME' reply @%ld\n", S9xGetMilliTime () - START); -#endif - len = READ_LONG (&header [3]); - if (len > 256) - { - S9xNPSetError ("Error in 'HELLO' reply packet received from server."); - S9xNPDisconnect (); - return (FALSE); - } - uint8 *data = new uint8 [len]; - if (!S9xNPGetData (NetPlay.Socket, data, len - 7)) - { - S9xNPSetError ("Error in 'HELLO' reply packet received from server."); - delete data; - S9xNPDisconnect (); - return (FALSE); - } - - if (data [0] != NP_VERSION) - { - S9xNPSetError ("\ -The Snes9X NetPlay server implements a different\n\ -version of the protocol. Disconnecting."); - delete data; - S9xNPDisconnect (); - return (FALSE); - } - - NetPlay.FrameCount = READ_LONG (&data [2]); - - if (!(header [2] & 0x80) && - strcmp ((char *) data + 4 + 2, NetPlay.ROMName) != 0) - { - if (!S9xNPLoadROMDialog ((char *) data + 4 + 2)) - { - delete data; - S9xNPDisconnect (); - return (FALSE); - } - } - NetPlay.Player = data [1]; - delete data; - - NetPlay.PendingWait4Sync = TRUE; - Settings.NetPlay = TRUE; - S9xNPResetJoypadReadPos (); - NetPlay.ServerSequenceNum = 1; - -#ifdef NP_DEBUG - printf ("CLIENT: Sending 'READY' to server @%ld...\n", S9xGetMilliTime () - START); -#endif - S9xNPSetAction ("Sending 'READY' to the server..."); - - return (S9xNPSendReady ((header [2] & 0x80) ? - NP_CLNT_WAITING_FOR_ROM_IMAGE : - NP_CLNT_READY)); -} - -bool8 S9xNPSendReady (uint8 op) -{ - uint8 ready [7]; - uint8 *ptr = ready; - *ptr++ = NP_CLNT_MAGIC; - *ptr++ = NetPlay.MySequenceNum++; - *ptr++ = op; - WRITE_LONG (ptr, 7); - ptr += 4; - - if (!S9xNPSendData (NetPlay.Socket, ready, 7)) - { - S9xNPDisconnect (); - S9xNPSetError ("Sending 'READY' message failed."); - return (FALSE); - } - - return (TRUE); -} - -bool8 S9xNPSendPause (bool8 paused) -{ -#ifdef NP_DEBUG - printf ("CLIENT: Pause - %s @%ld\n", paused ? "YES" : "NO", S9xGetMilliTime () - START); -#endif - uint8 pause [7]; - uint8 *ptr = pause; - *ptr++ = NP_CLNT_MAGIC; - *ptr++ = NetPlay.MySequenceNum++; - *ptr++ = NP_CLNT_PAUSE | (paused ? 0x80 : 0); - WRITE_LONG (ptr, 7); - ptr += 4; - - if (!S9xNPSendData (NetPlay.Socket, pause, 7)) - { - S9xNPSetError ("Sending 'PAUSE' message failed."); - S9xNPDisconnect (); - return (FALSE); - } - - return (TRUE); -} - -#ifdef __WIN32__ -void S9xNPClientLoop (void *) -{ - NetPlay.Waiting4EmulationThread = FALSE; - - if (S9xNPConnect ()) - { - S9xClearPause (PAUSE_NETPLAY_CONNECT); - while (NetPlay.Connected) - { - if (S9xNPWaitForHeartBeat ()) - { - LONG prev; - if (!ReleaseSemaphore (GUI.ClientSemaphore, 1, &prev)) - { -#ifdef NP_DEBUG - printf ("CLIENT: ReleaseSemaphore failed - already hit max count (%d) %ld\n", NP_JOYPAD_HIST_SIZE, S9xGetMilliTime () - START); -#endif - S9xNPSetWarning ("NetPlay: Client may be out of sync with server."); - } - else - { - if (!NetPlay.Waiting4EmulationThread && - prev == (int) NetPlay.MaxBehindFrameCount) - { - NetPlay.Waiting4EmulationThread = TRUE; - S9xNPSendPause (TRUE); - } - } - } - else - S9xNPDisconnect (); - } - } - else - { - S9xClearPause (PAUSE_NETPLAY_CONNECT); - } -#ifdef NP_DEBUG - printf ("CLIENT: Client thread exiting @%ld\n", S9xGetMilliTime () - START); -#endif -} -#endif - -bool8 S9xNPWaitForHeartBeat () -{ - uint8 header [3 + 4 + 4 * 5]; - - while (S9xNPGetData (NetPlay.Socket, header, 3 + 4)) - { - if (header [0] != NP_SERV_MAGIC) - { - S9xNPSetError ("Bad magic value from server while waiting for heart-beat message\n"); - S9xNPDisconnect (); - return (FALSE); - } - if (header [1] != NetPlay.ServerSequenceNum) - { - char buf [200]; - sprintf (buf, "Unexpected message sequence number from server, expected %d, got %d\n", NetPlay.ServerSequenceNum, header [1]); - S9xNPSetWarning (buf); - NetPlay.ServerSequenceNum = header [1] + 1; - } - else - NetPlay.ServerSequenceNum++; - - if ((header [2] & 0x1f) == NP_SERV_JOYPAD) - { - // Top 2 bits + 1 of opcode is joypad data count. - int num = (header [2] >> 6) + 1; - - if (num) - { - if (!S9xNPGetData (NetPlay.Socket, header + 3 + 4, num * 4)) - { - S9xNPSetError ("Error while receiving 'JOYPAD' message."); - S9xNPDisconnect (); - return (FALSE); - } - } - NetPlay.Frame [NetPlay.JoypadWriteInd] = READ_LONG (&header [3]); - - for (int i = 0; i < num; i++) - { - NetPlay.Joypads [NetPlay.JoypadWriteInd][i] = - READ_LONG (&header [3 + 4 + i * sizeof (uint32)]); - } - NetPlay.Paused = (header [2] & 0x20) != 0; - - NetPlay.JoypadWriteInd = (NetPlay.JoypadWriteInd + 1) % NP_JOYPAD_HIST_SIZE; - - if (NetPlay.JoypadWriteInd != (NetPlay.JoypadReadInd + 1) % NP_JOYPAD_HIST_SIZE) - { - //printf ("(%d)", (NetPlay.JoypadWriteInd - NetPlay.JoypadReadInd) % NP_JOYPAD_HIST_SIZE); fflush (stdout); - } -//printf ("CLIENT: HB: @%d\n", S9xGetMilliTime () - START); - return (TRUE); - } - else - { - uint32 len = READ_LONG (&header [3]); - switch (header [2] & 0x1f) - { - case NP_SERV_RESET: -#ifdef NP_DEBUG - printf ("CLIENT: RESET received @%ld\n", S9xGetMilliTime () - START); -#endif - S9xNPDiscardHeartbeats (); - S9xReset (); - NetPlay.FrameCount = READ_LONG (&header [3]); - S9xNPResetJoypadReadPos (); - S9xNPSendReady (); - break; - case NP_SERV_PAUSE: - NetPlay.Paused = (header [2] & 0x20) != 0; - break; - case NP_SERV_LOAD_ROM: -#ifdef NP_DEBUG - printf ("CLIENT: LOAD_ROM received @%ld\n", S9xGetMilliTime () - START); -#endif - S9xNPDiscardHeartbeats (); - if (S9xNPLoadROM (len - 7)) - S9xNPSendReady (NP_CLNT_LOADED_ROM); - break; - case NP_SERV_ROM_IMAGE: -#ifdef NP_DEBUG - printf ("CLIENT: ROM_IMAGE received @%ld\n", S9xGetMilliTime () - START); -#endif - S9xNPDiscardHeartbeats (); - if (S9xNPGetROMImage (len - 7)) - S9xNPSendReady (NP_CLNT_RECEIVED_ROM_IMAGE); - break; - case NP_SERV_SRAM_DATA: -#ifdef NP_DEBUG - printf ("CLIENT: SRAM_DATA received @%ld\n", S9xGetMilliTime () - START); -#endif - S9xNPDiscardHeartbeats (); - S9xNPGetSRAMData (len - 7); - break; - case NP_SERV_FREEZE_FILE: -#ifdef NP_DEBUG - printf ("CLIENT: FREEZE_FILE received @%ld\n", S9xGetMilliTime () - START); -#endif - S9xNPDiscardHeartbeats (); - S9xNPGetFreezeFile (len - 7); - S9xNPResetJoypadReadPos (); - S9xNPSendReady (); - break; - default: -#ifdef NP_DEBUG - printf ("CLIENT: UNKNOWN received @%ld\n", S9xGetMilliTime () - START); -#endif - S9xNPDisconnect (); - return (FALSE); - } - } - } - - S9xNPDisconnect (); - return (FALSE); -} - -bool8 S9xNPLoadROMDialog (const char *rom_name) -{ - NetPlay.Answer = FALSE; - -#ifdef __WIN32__ - ResetEvent (NetPlay.ReplyEvent); - -#ifdef NP_DEBUG - printf ("CLIENT: Asking GUI thread to open ROM load dialog...\n"); -#endif - - PostMessage (GUI.hWnd, WM_USER + 3, (uint32) rom_name, (uint32) rom_name); - -#ifdef NP_DEBUG - printf ("CLIENT: Waiting for reply from GUI thread...\n"); -#endif - - WaitForSingleObject (NetPlay.ReplyEvent, INFINITE); - -#ifdef NP_DEBUG - printf ("CLIENT: Got reply from GUI thread (%d)\n", NetPlay.Answer); -#endif -#endif - - return (NetPlay.Answer); -} - -bool8 S9xNPLoadROM (uint32 len) -{ - uint8 *data = new uint8 [len]; - - S9xNPSetAction ("Receiving ROM name..."); - if (!S9xNPGetData (NetPlay.Socket, data, len)) - { - S9xNPSetError ("Error while receiving ROM name."); - delete data; - S9xNPDisconnect (); - return (FALSE); - } - - S9xNPSetAction ("Opening LoadROM dialog..."); - if (!S9xNPLoadROMDialog ((char *) data)) - { - S9xNPSetError ("Disconnected from NetPlay server because you are playing a different game!"); - delete data; - S9xNPDisconnect (); - return (FALSE); - } - delete data; - return (TRUE); -} - -bool8 S9xNPGetROMImage (uint32 len) -{ - uint8 rom_info [5]; - - S9xNPSetAction ("Receiving ROM information..."); - if (!S9xNPGetData (NetPlay.Socket, rom_info, 5)) - { - S9xNPSetError ("Error while receiving ROM information."); - S9xNPDisconnect (); - return (FALSE); - } - uint32 CalculatedSize = READ_LONG (&rom_info [1]); -#ifdef NP_DEBUG - printf ("CLIENT: Hi-ROM: %s, Size: %04x\n", rom_info [0] ? "Y" : "N", CalculatedSize); -#endif - if (CalculatedSize + 5 >= len || - CalculatedSize >= CMemory::MAX_ROM_SIZE) - { - S9xNPSetError ("Size error in ROM image data received from server."); - S9xNPDisconnect (); - return (FALSE); - } - - Memory.HiROM = rom_info [0]; - Memory.LoROM = !Memory.HiROM; - Memory.HeaderCount = 0; - Memory.CalculatedSize = CalculatedSize; - - // Load up ROM image -#ifdef NP_DEBUG - printf ("CLIENT: Receiving ROM image @%ld...\n", S9xGetMilliTime () - START); -#endif - S9xNPSetAction ("Receiving ROM image..."); - if (!S9xNPGetData (NetPlay.Socket, Memory.ROM, Memory.CalculatedSize)) - { - S9xNPSetError ("Error while receiving ROM image from server."); - Settings.StopEmulation = TRUE; - S9xNPDisconnect (); - return (FALSE); - } -#ifdef NP_DEBUG - printf ("CLIENT: Receiving ROM filename @%ld...\n", S9xGetMilliTime () - START); -#endif - S9xNPSetAction ("Receiving ROM filename..."); - uint32 filename_len = len - Memory.CalculatedSize - 5; - if (filename_len > _MAX_PATH || - !S9xNPGetData (NetPlay.Socket, (uint8 *) Memory.ROMFilename, filename_len)) - { - S9xNPSetError ("Error while receiving ROM filename from server."); - S9xNPDisconnect (); - Settings.StopEmulation = TRUE; - return (FALSE); - } - Memory.InitROM (FALSE); - S9xReset (); - S9xNPResetJoypadReadPos (); - Settings.StopEmulation = FALSE; - -#ifdef __WIN32__ - PostMessage (GUI.hWnd, WM_NULL, 0, 0); -#endif - - return (TRUE); -} - -void S9xNPGetSRAMData (uint32 len) -{ - if (len > 0x10000) - { - S9xNPSetError ("Length error in S-RAM data received from server."); - S9xNPDisconnect (); - return; - } - S9xNPSetAction ("Receiving S-RAM data..."); - if (len > 0 && !S9xNPGetData (NetPlay.Socket, ::SRAM, len)) - { - S9xNPSetError ("Error while receiving S-RAM data from server."); - S9xNPDisconnect (); - } -} - -void S9xNPGetFreezeFile (uint32 len) -{ - uint8 frame_count [4]; - -#ifdef NP_DEBUG - printf ("CLIENT: Receiving freeze file information @%ld...\n", S9xGetMilliTime () - START); -#endif - S9xNPSetAction ("Receiving freeze file information..."); - if (!S9xNPGetData (NetPlay.Socket, frame_count, 4)) - { - S9xNPSetError ("Error while receiving freeze file information from server."); - S9xNPDisconnect (); - return; - } - NetPlay.FrameCount = READ_LONG (frame_count); - -#ifdef NP_DEBUG - printf ("CLIENT: Receiving freeze file @%ld...\n", S9xGetMilliTime () - START); -#endif - S9xNPSetAction ("Receiving freeze file..."); - uint8 *data = new uint8 [len]; - if (!S9xNPGetData (NetPlay.Socket, data, len - 4)) - { - S9xNPSetError ("Error while receiving freeze file from server."); - S9xNPDisconnect (); - delete data; - return; - } - - //FIXME: Setting umask here wouldn't hurt. - FILE *file; -#ifdef HAVE_MKSTEMP - int fd; - char fname[] = "/tmp/snes9x_fztmpXXXXXX"; - if ((fd = mkstemp(fname)) < 0) - { - if ((file = fdopen (fd, "wb"))) -#else - char fname [L_tmpnam]; - if (tmpnam (fname)) - { - if ((file = fopen (fname, "wb"))) -#endif - { - if (fwrite (data, 1, len, file) == len) - { - fclose(file); - if (!S9xUnfreezeGame (fname)) - S9xNPSetError ("Unable to load freeze file just received."); - } else { - S9xNPSetError ("Failed to write to temporary freeze file."); - fclose (file); - } - } else - S9xNPSetError ("Failed to create temporary freeze file."); - remove (fname); - } else - S9xNPSetError ("Unable to get name for temporary freeze file."); - delete data; -} - -uint32 S9xNPGetJoypad (int which1) -{ - if (Settings.NetPlay && which1 < 5) - return (NetPlay.Joypads [NetPlay.JoypadReadInd][which1]); - - return (0); -} - -void S9xNPStepJoypadHistory () -{ - if ((NetPlay.JoypadReadInd + 1) % NP_JOYPAD_HIST_SIZE != NetPlay.JoypadWriteInd) - { - NetPlay.JoypadReadInd = (NetPlay.JoypadReadInd + 1) % NP_JOYPAD_HIST_SIZE; - if (NetPlay.FrameCount != NetPlay.Frame [NetPlay.JoypadReadInd]) - { - S9xNPSetWarning ("This Snes9X session may be out of sync with the server."); -#ifdef NP_DEBUG - printf ("*** CLIENT: client out of sync with server (%d, %d) @%ld\n", NetPlay.FrameCount, NetPlay.Frame [NetPlay.JoypadReadInd], S9xGetMilliTime () - START); -#endif - } - } - else - { -#ifdef NP_DEBUG - printf ("*** CLIENT: S9xNPStepJoypadHistory NOT OK@%ld\n", S9xGetMilliTime () - START); -#endif - } -} - - -void S9xNPResetJoypadReadPos () -{ -#ifdef NP_DEBUG - printf ("CLIENT: ResetJoyReadPos @%ld\n", S9xGetMilliTime () - START); fflush (stdout); -#endif - NetPlay.JoypadWriteInd = 0; - NetPlay.JoypadReadInd = NP_JOYPAD_HIST_SIZE - 1; - for (int h = 0; h < NP_JOYPAD_HIST_SIZE; h++) - memset ((void *) &NetPlay.Joypads [h], 0, sizeof (NetPlay.Joypads [0])); -} - -bool8 S9xNPSendJoypadUpdate (uint32 joypad) -{ - uint8 data [7]; - uint8 *ptr = data; - - *ptr++ = NP_CLNT_MAGIC; - *ptr++ = NetPlay.MySequenceNum++; - *ptr++ = NP_CLNT_JOYPAD; - - joypad |= 0x80000000; - - WRITE_LONG (ptr, joypad); - if (!S9xNPSendData (NetPlay.Socket, data, 7)) - { - S9xNPSetError ("Error while sending joypad data server."); - S9xNPDisconnect (); - return (FALSE); - } - return (TRUE); -} - -void S9xNPDisconnect () -{ - close (NetPlay.Socket); - NetPlay.Socket = -1; - NetPlay.Connected = FALSE; - Settings.NetPlay = FALSE; -} - -bool8 S9xNPSendData (int socket, const uint8 *data, int length) -{ - int len = length; - const uint8 *ptr = data; - - NetPlay.PercentageComplete = 0; - - do - { - if (NetPlay.Abort) - return (FALSE); - - int num_bytes = len; - - // Write the data in small chunks, allowing this thread to spot an - // abort request from another thread. - if (num_bytes > 512) - num_bytes = 512; - - int sent = write (socket, (char *) ptr, num_bytes); - if (sent < 0) - { - if (errno == EINTR -#ifdef EAGAIN - || errno == EAGAIN -#endif -#ifdef EWOULDBLOCK - || errno == EWOULDBLOCK -#endif - ) - { -#ifdef NP_DEBUG - printf ("CLIENT: EINTR, EAGAIN or EWOULDBLOCK while sending data @%ld\n", S9xGetMilliTime () - START); -#endif - continue; - } - return (FALSE); - } - else - if (sent == 0) - return (FALSE); - len -= sent; - ptr += sent; - - NetPlay.PercentageComplete = (uint8) (((length - len) * 100) / length); - } while (len > 0); - - return (TRUE); -} - -bool8 S9xNPGetData (int socket, uint8 *data, int length) -{ - int len = length; - uint8 *ptr = data; - int chunk = length / 50; - - if (chunk < 1024) - chunk = 1024; - - NetPlay.PercentageComplete = 0; - do - { - if (NetPlay.Abort) - return (FALSE); - - int num_bytes = len; - - // Read the data in small chunks, allowing this thread to spot an - // abort request from another thread. - if (num_bytes > chunk) - num_bytes = chunk; - - int got = read (socket, (char *) ptr, num_bytes); - if (got < 0) - { - if (errno == EINTR -#ifdef EAGAIN - || errno == EAGAIN -#endif -#ifdef EWOULDBLOCK - || errno == EWOULDBLOCK -#endif -#ifdef WSAEWOULDBLOCK - || errno == WSAEWOULDBLOCK -#endif - ) - { -#ifdef NP_DEBUG - printf ("CLIENT: EINTR, EAGAIN or EWOULDBLOCK while receiving data @%ld\n", S9xGetMilliTime () - START); -#endif - continue; - } -#ifdef WSAEMSGSIZE - if (errno != WSAEMSGSIZE) - return (FALSE); - else - { - got = num_bytes; -#ifdef NP_DEBUG - printf ("CLIENT: WSAEMSGSIZE, actual bytes %d while receiving data @%ld\n", got, S9xGetMilliTime () - START); -#endif - } -#else - return (FALSE); -#endif - } - else - if (got == 0) - return (FALSE); - - len -= got; - ptr += got; - - if (!Settings.NetPlayServer && length > 1024) - { - NetPlay.PercentageComplete = (uint8) (((length - len) * 100) / length); -#ifdef __WIN32__ - PostMessage (GUI.hWnd, WM_USER, NetPlay.PercentageComplete, - NetPlay.PercentageComplete); - Sleep (0); -#endif - } - - } while (len > 0); - - return (TRUE); -} - -bool8 S9xNPInitialise () -{ -#ifdef __WIN32__ - static bool8 initialised = FALSE; - - if (!initialised) - { - initialised = TRUE; - WSADATA data; - -#ifdef NP_DEBUG - START = S9xGetMilliTime (); - - printf ("CLIENT/SERVER: Initialising WinSock @%ld\n", S9xGetMilliTime () - START); -#endif - S9xNPSetAction ("Initialising Windows sockets interface..."); - if (WSAStartup (MAKEWORD (1, 0), &data) != 0) - { - S9xNPSetError ("Call to init Windows sockets failed. Do you have WinSock2 installed?"); - return (FALSE); - } - } -#endif - return (TRUE); -} - -void S9xNPDiscardHeartbeats () -{ - // Discard any pending heartbeats and wait for any frame that is currently - // being emulated to complete. -#ifdef NP_DEBUG - printf ("CLIENT: DiscardHeartbeats @%ld, finished @", S9xGetMilliTime () - START); - fflush (stdout); -#endif - -#ifdef __WIN32__ - while (WaitForSingleObject (GUI.ClientSemaphore, 200) == WAIT_OBJECT_0) - ; -#endif - -#ifdef NP_DEBUG - printf ("%ld\n", S9xGetMilliTime () - START); -#endif - NetPlay.Waiting4EmulationThread = FALSE; -} - -void S9xNPSetAction (const char *action, bool8 force) -{ - if (force || !Settings.NetPlayServer) - { - strncpy (NetPlay.ActionMsg, action, NP_MAX_ACTION_LEN - 1); - NetPlay.ActionMsg [NP_MAX_ACTION_LEN - 1] = 0; -#ifdef __WIN32__ - PostMessage (GUI.hWnd, WM_USER, 0, 0); - Sleep (0); -#endif - } -} - -void S9xNPSetError (const char *error) -{ - strncpy (NetPlay.ErrorMsg, error, NP_MAX_ACTION_LEN - 1); - NetPlay.ErrorMsg [NP_MAX_ACTION_LEN - 1] = 0; -#ifdef __WIN32 - PostMessage (GUI.hWnd, WM_USER + 1, 0, 0); - Sleep (0); -#endif -} - -void S9xNPSetWarning (const char *warning) -{ - strncpy (NetPlay.WarningMsg, warning, NP_MAX_ACTION_LEN - 1); - NetPlay.WarningMsg [NP_MAX_ACTION_LEN - 1] = 0; -#ifdef __WIN32__ - PostMessage (GUI.hWnd, WM_USER + 2, 0, 0); - Sleep (0); -#endif -} -#endif - - diff --git a/source/server.cpp b/source/server.cpp deleted file mode 100644 index 4eb384e..0000000 --- a/source/server.cpp +++ /dev/null @@ -1,1303 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - Kris Bleakley - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, John Weidman, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - Specific ports contains the works of other authors. See headers in - individual files. - - Snes9x homepage: http://www.snes9x.com - - Permission to use, copy, modify and distribute Snes9x in both binary and - source form, for non-commercial purposes, is hereby granted without fee, - providing that this license information and copyright notice appear with - all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes - charging money for Snes9x or software derived from Snes9x. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. -*******************************************************************************/ - -#ifdef NETPLAY_SUPPORT -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <memory.h> -#include <sys/types.h> -#ifdef HAVE_STRINGS_H -#include <strings.h> -#endif - -#ifndef __WIN32__ -#include <unistd.h> -#include <sys/time.h> -#endif - -#ifdef __WIN32__ - -#include <winsock.h> -#include <process.h> -#define ioctl ioctlsocket -#define close closesocket -#define read(a,b,c) recv(a, b, c, 0) -#define write(a,b,c) send(a, b, c, 0) -#define gettimeofday(a,b) S9xGetTimeOfDay (a) -#define exit(a) _endthread() -void S9xGetTimeOfDay (struct timeval *n); -#else - -#include <netdb.h> -#include <sys/socket.h> -#include <sys/param.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <signal.h> - -#ifdef __SVR4 -#include <sys/stropts.h> -#endif - -#endif // !__WIN32__ - -#include "snes9x.h" -#include "netplay.h" -#include "memmap.h" -#include "snapshot.h" - -#define NP_ONE_CLIENT 1 - -struct SNPServer NPServer; - -extern unsigned long START; - -void S9xNPSendToAllClients (uint8 *data, int len); -bool8 S9xNPLoadFreezeFile (const char *fname, uint8 *&data, uint32 &len); -void S9xNPSendFreezeFile (int c, uint8 *data, uint32 len); -void S9xNPNoClientReady (int start_index = NP_ONE_CLIENT); -void S9xNPRecomputePause (); -void S9xNPWaitForEmulationToComplete (); -void S9xNPSendROMImageToAllClients (); -bool8 S9xNPSendROMImageToClient (int client); -void S9xNPSendSRAMToClient (int c); -void S9xNPSendSRAMToAllClients (); -void S9xNPSyncClient (int); -void S9xNPSendROMLoadRequest (const char *filename); -void S9xNPSendFreezeFileToAllClients (const char *filename); -void S9xNPStopServer (); - -void S9xNPShutdownClient (int c, bool8 report_error = FALSE) -{ - if (NPServer.Clients [c].Connected) - { - NPServer.Clients [c].Connected = FALSE; - NPServer.Clients [c].SaidHello = FALSE; - - close (NPServer.Clients [c].Socket); -#ifdef NP_DEBUG - printf ("SERVER: Player %d disconnecting @%ld\n", c + 1, S9xGetMilliTime () - START); -#endif - if (report_error) - { - sprintf (NetPlay.ErrorMsg, - "Player %d on '%s' has disconnected.", c + 1, - NPServer.Clients [c].HostName); - S9xNPSetError (NetPlay.ErrorMsg); - } - - if (NPServer.Clients [c].HostName) - { - free ((char *) NPServer.Clients [c].HostName); - NPServer.Clients [c].HostName = NULL; - } - if (NPServer.Clients [c].ROMName) - { - free ((char *) NPServer.Clients [c].ROMName); - NPServer.Clients [c].ROMName = NULL; - } - if (NPServer.Clients [c].Who) - { - free ((char *) NPServer.Clients [c].Who); - NPServer.Clients [c].Who = NULL; - } - NPServer.Joypads [c] = 0; - NPServer.NumClients--; - S9xNPRecomputePause (); - } -} - -static bool8 S9xNPSGetData (int socket, uint8 *data, int length) -{ - int len = length; - uint8 *ptr = data; - - do - { - int num_bytes = len; - - // Read the data in small chunks, allowing this thread to spot an - // abort request from another thread. - if (num_bytes > 512) - num_bytes = 512; - - int got = read (socket, (char *) ptr, num_bytes); - if (got < 0) - { - if (errno == EINTR -#ifdef EAGAIN - || errno == EAGAIN -#endif -#ifdef EWOULDBLOCK - || errno == EWOULDBLOCK -#endif -#ifdef WSAEWOULDBLOCK - || errno == WSAEWOULDBLOCK -#endif - ) - continue; -#ifdef WSAEMSGSIZE - if (errno != WSAEMSGSIZE) - return (FALSE); - else - { - got = num_bytes; -#ifdef NP_DEBUG - printf ("SERVER: WSAEMSGSIZE, actual bytes %d while receiving data @%d\n", got, S9xGetMilliTime () - START); -#endif - } -#else - return (FALSE); -#endif - } - else - if (got == 0) - return (FALSE); - - len -= got; - ptr += got; - } while (len > 0); - - return (TRUE); -} - -static bool8 S9xNPSSendData (int fd, const uint8 *data, int length) -{ - int Percent = 0; - int len = length; - int chunk = length / 50; - - if (chunk < 1024) - chunk = 1024; - - do - { - int num_bytes = len; - - // Write the data in small chunks, allowing this thread to spot an - // abort request from another thread. - if (num_bytes > chunk) - num_bytes = chunk; - - int sent; - sent = write (fd, (char *) data, len); - - if (sent < 0) - { - if (errno == EINTR -#ifdef EAGAIN - || errno == EAGAIN -#endif -#ifdef EWOULDBLOCK - || errno == EWOULDBLOCK -#endif - ) - { -#ifdef NP_DEBUG - printf ("SERVER: EINTR, EAGAIN or EWOULDBLOCK while sending data @%ld\n", S9xGetMilliTime () - START); -#endif - continue; - } - return (FALSE); - } - else - if (sent == 0) - return (FALSE); - len -= sent; - data += sent; - if (length > 1024) - { - Percent = (uint8) (((length - len) * 100) / length); -#ifdef __WIN32__ - PostMessage (GUI.hWnd, WM_USER, Percent, Percent); - Sleep (0); -#endif - } - } while (len > 0); - - return (TRUE); -} - -void S9xNPSendHeartBeat () -{ - int len = 3; - uint8 data [3 + 4 * 5]; - uint8 *ptr = data; - int n; - - for (n = NP_MAX_CLIENTS - 1; n >= 0; n--) - { - if (NPServer.Clients [n].SaidHello) - break; - } - - if (n >= 0) - { - bool8 Paused = NPServer.Paused != 0; - - NPServer.FrameCount++; - *ptr++ = NP_SERV_MAGIC; - *ptr++ = 0; // Individual client sequence number will get placed here - *ptr++ = NP_SERV_JOYPAD | (n << 6) | ((Paused != 0) << 5); - - WRITE_LONG (ptr, NPServer.FrameCount); - len += 4; - ptr += 4; - - int i; - - for (i = 0; i <= n; i++) - { - WRITE_LONG (ptr, NPServer.Joypads [i]); - len += 4; - ptr += 4; - } - - S9xNPSendToAllClients (data, len); - } -} - -void S9xNPSendToAllClients (uint8 *data, int len) -{ - int i; - - for (i = 0; i < NP_MAX_CLIENTS; i++) - { - if (NPServer.Clients [i].SaidHello) - { - data [1] = NPServer.Clients [i].SendSequenceNum++; - if (!S9xNPSSendData (NPServer.Clients [i].Socket, data, len)) - S9xNPShutdownClient (i, TRUE); - } - } -} - -void S9xNPProcessClient (int c) -{ - uint8 header [7]; - uint8 *data; - uint32 len; - uint8 *ptr; - - if (!S9xNPSGetData (NPServer.Clients [c].Socket, header, 7)) - { - S9xNPSetWarning ("SERVER: Failed to get message header from client.\n"); - S9xNPShutdownClient (c, TRUE); - return; - } - if (header [0] != NP_CLNT_MAGIC) - { - S9xNPSetWarning ("SERVER: Bad header magic value received from client.\n"); - S9xNPShutdownClient (c, TRUE); - return; - } - - if (header [1] != NPServer.Clients [c].ReceiveSequenceNum) - { -#ifdef NP_DEBUG - printf ("SERVER: Messages lost from '%s', expected %d, got %d\n", - NPServer.Clients [c].HostName ? - NPServer.Clients [c].HostName : "Unknown", - NPServer.Clients [c].ReceiveSequenceNum, - header [1]); -#endif - sprintf (NetPlay.WarningMsg, - "SERVER: Messages lost from '%s', expected %d, got %d\n", - NPServer.Clients [c].HostName ? - NPServer.Clients [c].HostName : "Unknown", - NPServer.Clients [c].ReceiveSequenceNum, - header [1]); - NPServer.Clients [c].ReceiveSequenceNum = header [1] + 1; - S9xNPSetWarning (NetPlay.WarningMsg); - } - else - NPServer.Clients [c].ReceiveSequenceNum++; - - len = READ_LONG (&header [3]); - - switch (header [2] & 0x3f) - { - case NP_CLNT_HELLO: -#ifdef NP_DEBUG - printf ("SERVER: Got HELLO from client @%ld\n", S9xGetMilliTime () - START); -#endif - S9xNPSetAction ("Got HELLO from client...", TRUE); - if (len > 0x10000) - { - S9xNPSetWarning ("SERVER: Client HELLO message length error."); - S9xNPShutdownClient (c, TRUE); - return; - } - data = new uint8 [len - 7]; - if (!S9xNPSGetData (NPServer.Clients [c].Socket, data, len - 7)) - { - S9xNPSetWarning ("SERVER: Failed to get HELLO message content from client."); - S9xNPShutdownClient (c, TRUE); - return; - } - - if (NPServer.NumClients <= NP_ONE_CLIENT) - { - NPServer.FrameTime = READ_LONG (data); - strncpy (NPServer.ROMName, (char *) &data [4], 29); - NPServer.ROMName [29] = 0; - } - - NPServer.Clients [c].ROMName = strdup ((char *) &data [4]); -#ifdef NP_DEBUG - printf ("SERVER: Client is playing: %s, Frame Time: %d @%ld\n", data + 4, READ_LONG (data), S9xGetMilliTime () - START); -#endif - - NPServer.Clients [c].SendSequenceNum = 0; - - len = 7 + 1 + 1 + 4 + strlen (NPServer.ROMName) + 1; - - delete data; - ptr = data = new uint8 [len]; - *ptr++ = NP_SERV_MAGIC; - *ptr++ = NPServer.Clients [c].SendSequenceNum++; - - if (NPServer.SendROMImageOnConnect && - NPServer.NumClients > NP_ONE_CLIENT) - *ptr++ = NP_SERV_HELLO | 0x80; - else - *ptr++ = NP_SERV_HELLO; - WRITE_LONG (ptr, len); - ptr += 4; - *ptr++ = NP_VERSION; - *ptr++ = c + 1; - WRITE_LONG (ptr, NPServer.FrameCount); - ptr += 4; - strcpy ((char *) ptr, NPServer.ROMName); - -#ifdef NP_DEBUG - printf ("SERVER: Sending welcome information to client @%ld...\n", S9xGetMilliTime () - START); -#endif - S9xNPSetAction ("SERVER: Sending welcome information to new client...", TRUE); - if (!S9xNPSSendData (NPServer.Clients [c].Socket, data, len)) - { - S9xNPSetWarning ("SERVER: Failed to send welcome message to client."); - S9xNPShutdownClient (c, TRUE); - return; - } - delete data; -#ifdef NP_DEBUG - printf ("SERVER: Waiting for a response from the client @%ld...\n", S9xGetMilliTime () - START); -#endif - S9xNPSetAction ("SERVER: Waiting for a response from the client...", TRUE); - break; - - case NP_CLNT_LOADED_ROM: -#ifdef NP_DEBUG - printf ("SERVER: Client %d loaded requested ROM @%ld...\n", c, S9xGetMilliTime () - START); -#endif - NPServer.Clients [c].SaidHello = TRUE; - NPServer.Clients [c].Ready = FALSE; - NPServer.Clients [c].Paused = FALSE; - S9xNPRecomputePause (); - S9xNPWaitForEmulationToComplete (); - - if (NPServer.SyncByReset) - { - S9xNPServerAddTask (NP_SERVER_SEND_SRAM, (void *) c); - S9xNPServerAddTask (NP_SERVER_RESET_ALL, 0); - } - else - S9xNPServerAddTask (NP_SERVER_SYNC_CLIENT, (void *) c); - break; - - case NP_CLNT_RECEIVED_ROM_IMAGE: -#ifdef NP_DEBUG - printf ("SERVER: Client %d received ROM image @%ld...\n", c, S9xGetMilliTime () - START); -#endif - NPServer.Clients [c].SaidHello = TRUE; - NPServer.Clients [c].Ready = FALSE; - NPServer.Clients [c].Paused = FALSE; - S9xNPRecomputePause (); - S9xNPWaitForEmulationToComplete (); - - if (NPServer.SyncByReset) - { - S9xNPServerAddTask (NP_SERVER_SEND_SRAM, (void *) c); - S9xNPServerAddTask (NP_SERVER_RESET_ALL, 0); - } - else - S9xNPServerAddTask (NP_SERVER_SYNC_CLIENT, (void *) c); - - break; - - case NP_CLNT_WAITING_FOR_ROM_IMAGE: -#ifdef NP_DEBUG - printf ("SERVER: Client %d waiting for ROM image @%ld...\n", c, S9xGetMilliTime () - START); -#endif - NPServer.Clients [c].SaidHello = TRUE; - NPServer.Clients [c].Ready = FALSE; - NPServer.Clients [c].Paused = FALSE; - S9xNPRecomputePause (); - S9xNPSendROMImageToClient (c); - break; - - case NP_CLNT_READY: -#ifdef NP_DEBUG - printf ("SERVER: Client %d ready @%ld...\n", c, S9xGetMilliTime () - START); -#endif - if (NPServer.Clients [c].SaidHello) - { - NPServer.Clients [c].Paused = FALSE; - NPServer.Clients [c].Ready = TRUE; - - S9xNPRecomputePause (); - break; - } - NPServer.Clients [c].SaidHello = TRUE; - NPServer.Clients [c].Ready = TRUE; - NPServer.Clients [c].Paused = FALSE; - S9xNPRecomputePause (); - -//printf ("SERVER: SaidHello = TRUE, SeqNum = %d @%d\n", NPServer.Clients [c].SendSequenceNum, S9xGetMilliTime () - START); - if (NPServer.NumClients > NP_ONE_CLIENT) - { - if (!NPServer.SendROMImageOnConnect) - { - S9xNPWaitForEmulationToComplete (); - - if (NPServer.SyncByReset) - { - S9xNPServerAddTask (NP_SERVER_SEND_SRAM, (void *) c); - S9xNPServerAddTask (NP_SERVER_RESET_ALL, 0); - } - else - S9xNPServerAddTask (NP_SERVER_SYNC_CLIENT, (void *) c); - } - } - else - { - NPServer.Clients [c].Ready = TRUE; - S9xNPRecomputePause (); - } - break; - case NP_CLNT_JOYPAD: - NPServer.Joypads [c] = len; - break; - case NP_CLNT_PAUSE: -#ifdef NP_DEBUG - printf ("SERVER: Client %d Paused: %s @%ld\n", c, (header [2] & 0x80) ? "YES" : "NO", S9xGetMilliTime () - START); -#endif - NPServer.Clients [c].Paused = (header [2] & 0x80) != 0; - if (NPServer.Clients [c].Paused) - sprintf (NetPlay.WarningMsg, "SERVER: Client %d has paused.", c + 1); - else - sprintf (NetPlay.WarningMsg, "SERVER: Client %d has resumed.", c + 1); - S9xNPSetWarning (NetPlay.WarningMsg); - S9xNPRecomputePause (); - break; - } -} - -void S9xNPAcceptClient (int Listen, bool8 block) -{ - struct sockaddr_in remote_address; - struct linger val2; - struct hostent *host; - int new_fd; - int i; - -#ifdef NP_DEBUG - printf ("SERVER: attempting to accept new client connection @%ld\n", S9xGetMilliTime () - START); -#endif - S9xNPSetAction ("SERVER: Attempting to accept client connection...", TRUE); - memset (&remote_address, 0, sizeof (remote_address)); - ACCEPT_SIZE_T len = sizeof (remote_address); - - new_fd = accept (Listen, (struct sockaddr *)&remote_address, &len); - - S9xNPSetAction ("Setting socket options...", TRUE); - val2.l_onoff = 1; - val2.l_linger = 0; - if (setsockopt (new_fd, SOL_SOCKET, SO_LINGER, - (char *) &val2, sizeof (val2)) < 0) - { - S9xNPSetError ("Setting socket options failed."); - close (new_fd); - return; - } - - for (i = 0; i < NP_MAX_CLIENTS; i++) - { - if (!NPServer.Clients [i].Connected) - { - NPServer.NumClients++; - NPServer.Clients [i].Socket = new_fd; - NPServer.Clients [i].SendSequenceNum = 0; - NPServer.Clients [i].ReceiveSequenceNum = 0; - NPServer.Clients [i].Connected = TRUE; - NPServer.Clients [i].SaidHello = FALSE; - NPServer.Clients [i].Paused = FALSE; - NPServer.Clients [i].Ready = FALSE; - NPServer.Clients [i].ROMName = NULL; - NPServer.Clients [i].HostName = NULL; - NPServer.Clients [i].Who = NULL; - break; - } - } - - if (i >= NP_MAX_CLIENTS) - { - S9xNPSetError ("SERVER: Maximum number of NetPlay Clients have already connected."); - close (new_fd); - return; - } - - if (remote_address.sin_family == AF_INET) - { -#ifdef NP_DEBUG - printf ("SERVER: Looking up new client's hostname @%ld\n", S9xGetMilliTime () - START); -#endif - S9xNPSetAction ("SERVER: Looking up new client's hostname...", TRUE); - host = gethostbyaddr ((char *) &remote_address.sin_addr, - sizeof (remote_address.sin_addr), AF_INET); - - if (host) - { -#ifdef NP_DEBUG - printf ("SERVER: resolved new client's hostname (%s) @%ld\n", host->h_name, S9xGetMilliTime () - START); -#endif - sprintf (NetPlay.WarningMsg, "SERVER: Player %d on %s has connected.", i + 1, host->h_name); - NPServer.Clients [i].HostName = strdup (host->h_name); - } - else - { - char *ip = inet_ntoa (remote_address.sin_addr); - if (ip) - NPServer.Clients [i].HostName = strdup (ip); -#ifdef NP_DEBUG - printf ("SERVER: couldn't resolve new client's hostname (%s) @%ld\n", ip ? ip : "Unknown", S9xGetMilliTime () - START); -#endif - sprintf (NetPlay.WarningMsg, "SERVER: Player %d on %s has connected.", i + 1, ip ? ip : "Unknown"); - } - S9xNPSetWarning (NetPlay.WarningMsg); - } -#ifdef NP_DEBUG - printf ("SERVER: waiting for HELLO message from new client @%ld\n", S9xGetMilliTime () - START); -#endif - S9xNPSetAction ("SERVER: Waiting for HELLO message from new client..."); -} - -static bool8 server_continue = TRUE; - -static bool8 S9xNPServerInit (int port) -{ - struct sockaddr_in address; - int i; - int val; - - if (!S9xNPInitialise ()) - return (FALSE); - - for (i = 0; i < NP_MAX_CLIENTS; i++) - { - NPServer.Clients [i].SendSequenceNum = 0; - NPServer.Clients [i].ReceiveSequenceNum = 0; - NPServer.Clients [i].Connected = FALSE; - NPServer.Clients [i].SaidHello = FALSE; - NPServer.Clients [i].Paused = FALSE; - NPServer.Clients [i].Ready = FALSE; - NPServer.Clients [i].Socket = 0; - NPServer.Clients [i].ROMName = NULL; - NPServer.Clients [i].HostName = NULL; - NPServer.Clients [i].Who = NULL; - NPServer.Joypads [i] = 0; - } - - NPServer.NumClients = 0; - NPServer.FrameCount = 0; - -#ifdef NP_DEBUG - printf ("SERVER: Creating socket @%ld\n", S9xGetMilliTime () - START); -#endif - if ((NPServer.Socket = socket (AF_INET, SOCK_STREAM, 0)) < 0) - { - S9xNPSetError ("NetPlay Server: Can't create listening socket."); - return (FALSE); - } - - val = 1; - setsockopt (NPServer.Socket, SOL_SOCKET, SO_REUSEADDR, - (char *)&val, sizeof (val)); - - memset (&address, 0, sizeof (address)); - address.sin_family = AF_INET; - address.sin_addr.s_addr = htonl (INADDR_ANY); - address.sin_port = htons (port); - -#ifdef NP_DEBUG - printf ("SERVER: Binding socket to address and port @%ld\n", S9xGetMilliTime () - START); -#endif - if (bind (NPServer.Socket, (struct sockaddr *) &address, sizeof (address)) < 0) - { - S9xNPSetError ("NetPlay Server: Can't bind socket to port number.\nPort already in use?"); - return (FALSE); - } - -#ifdef NP_DEBUG - printf ("SERVER: Getting socket to listen @%ld\n", S9xGetMilliTime () - START); -#endif - if (listen (NPServer.Socket, NP_MAX_CLIENTS) < 0) - { - S9xNPSetError ("NetPlay Server: Can't get new socket to listen."); - return (FALSE); - } - -#ifdef NP_DEBUG - printf ("SERVER: Init complete @%ld\n", S9xGetMilliTime () - START); -#endif - return (TRUE); -} - -void S9xNPServerLoop (void *) -{ -#ifdef __WIN32__ - BOOL success = FALSE; -#else - bool8 success = FALSE; -#endif - - while (server_continue) - { - fd_set read_fds; - struct timeval timeout; - int res; - int i; - - int max_fd = NPServer.Socket; - -#ifdef __WIN32__ - Sleep (0); -#endif - - if (success && !Settings.Paused && !Settings.StopEmulation && - !Settings.ForcedPause && !NPServer.Paused) - { - S9xNPSendHeartBeat (); - } - - do - { - FD_ZERO (&read_fds); - FD_SET (NPServer.Socket, &read_fds); - for (i = 0; i < NP_MAX_CLIENTS; i++) - { - if (NPServer.Clients [i].Connected) - { - FD_SET (NPServer.Clients [i].Socket, &read_fds); - if (NPServer.Clients [i].Socket > max_fd) - max_fd = NPServer.Clients [i].Socket; - } - } - - timeout.tv_sec = 0; - timeout.tv_usec = 1000; - res = select (max_fd + 1, &read_fds, NULL, NULL, &timeout); - - if (res > 0) - { - if (FD_ISSET (NPServer.Socket, &read_fds)) - S9xNPAcceptClient (NPServer.Socket, FALSE); - - for (i = 0; i < NP_MAX_CLIENTS; i++) - { - if (NPServer.Clients [i].Connected && - FD_ISSET (NPServer.Clients [i].Socket, &read_fds)) - { - S9xNPProcessClient (i); - } - } - } - } while (res > 0); - -#ifdef __WIN32__ - success = WaitForSingleObject (GUI.ServerTimerSemaphore, 200) == WAIT_OBJECT_0; -#endif - - while (NPServer.TaskHead != NPServer.TaskTail) - { - void *task_data = NPServer.TaskQueue [NPServer.TaskHead].Data; - -#if defined(NP_DEBUG) && NP_DEBUG == 2 - printf ("SERVER: task %d @%ld\n", NPServer.TaskQueue [NPServer.TaskHead].Task, S9xGetMilliTime () - START); -#endif - - switch (NPServer.TaskQueue [NPServer.TaskHead].Task) - { - case NP_SERVER_SEND_ROM_IMAGE: - S9xNPSendROMImageToAllClients (); - break; - case NP_SERVER_SYNC_CLIENT: - NPServer.Clients [(int) task_data].Ready = FALSE; - S9xNPRecomputePause (); - S9xNPSyncClient ((int) task_data); - break; - case NP_SERVER_SYNC_ALL: - S9xNPSyncClients (); - break; - case NP_SERVER_SEND_FREEZE_FILE_ALL: - S9xNPSendFreezeFileToAllClients ((char *) task_data); - free ((char *) task_data); - break; - case NP_SERVER_SEND_ROM_LOAD_REQUEST_ALL: - S9xNPSendROMLoadRequest ((char *) task_data); - free ((char *) task_data); - break; - case NP_SERVER_RESET_ALL: - S9xNPNoClientReady (0); - S9xNPWaitForEmulationToComplete (); - S9xNPSetAction ("SERVER: Sending RESET to all clients...", TRUE); -#ifdef NP_DEBUG - printf ("SERVER: Sending RESET to all clients @%ld\n", S9xGetMilliTime () - START); -#endif - { - uint8 reset [7]; - uint8 *ptr; - - ptr = reset; - *ptr++ = NP_SERV_MAGIC; - *ptr++ = 0; - *ptr++ = NP_SERV_RESET; - WRITE_LONG (ptr, NPServer.FrameCount); - S9xNPSendToAllClients (reset, 7); - } - break; - case NP_SERVER_SEND_SRAM: - NPServer.Clients [(int) task_data].Ready = FALSE; - S9xNPRecomputePause (); - S9xNPWaitForEmulationToComplete (); - S9xNPSendSRAMToClient ((int) task_data); - break; - - case NP_SERVER_SEND_SRAM_ALL: - S9xNPNoClientReady (); - S9xNPWaitForEmulationToComplete (); - S9xNPSendSRAMToAllClients (); - break; - - default: - S9xNPSetError ("SERVER: *** Unknown task ***\n"); - break; - } - NPServer.TaskHead = (NPServer.TaskHead + 1) % NP_MAX_TASKS; - } - } -#ifdef NP_DEBUG - printf ("SERVER: Server thread exiting @%ld\n", S9xGetMilliTime () - START); -#endif - S9xNPStopServer (); -} - -bool8 S9xNPStartServer (int port) -{ - static int p; - -#ifdef NP_DEBUG - printf ("SERVER: Starting server on port %d @%ld\n", port, S9xGetMilliTime () - START); -#endif - p = port; - server_continue = TRUE; - if (S9xNPServerInit (port)) -#ifdef __WIN32__ - return (_beginthread (S9xNPServerLoop, 0, &p) != ~0); -#else - return (TRUE); -#endif - - return (FALSE); -} - -void S9xNPStopServer () -{ -#ifdef NP_DEBUG - printf ("SERVER: Stopping server @%ld\n", S9xGetMilliTime () - START); -#endif - server_continue = FALSE; - close (NPServer.Socket); - - for (int i = 0; i < NP_MAX_CLIENTS; i++) - { - if (NPServer.Clients [i].Connected) - { - close (NPServer.Clients [i].Socket); - NPServer.Clients [i].Connected = FALSE; - NPServer.Clients [i].SaidHello = FALSE; - } - } -} - -#ifdef __WIN32__ -void S9xGetTimeOfDay (struct timeval *n) -{ - unsigned long t = S9xGetMilliTime (); - - n->tv_sec = t / 1000; - n->tv_usec = (t % 1000) * 1000; -} -#endif - -void S9xNPSendROMImageToAllClients () -{ - S9xNPNoClientReady (); - S9xNPWaitForEmulationToComplete (); - - int c; - - for (c = NP_ONE_CLIENT; c < NP_MAX_CLIENTS; c++) - { - if (NPServer.Clients [c].SaidHello) - S9xNPSendROMImageToClient (c); - } - - if (NPServer.SyncByReset) - { - S9xNPServerAddTask (NP_SERVER_SEND_SRAM_ALL, 0); - S9xNPServerAddTask (NP_SERVER_RESET_ALL, 0); - } - else - S9xNPSyncClient (-1); -} - -bool8 S9xNPSendROMImageToClient (int c) -{ -#ifdef NP_DEBUG - printf ("SERVER: Sending ROM image to player %d @%ld\n", c + 1, S9xGetMilliTime () - START); -#endif - sprintf (NetPlay.ActionMsg, "Sending ROM image to player %d...", c + 1); - S9xNPSetAction (NetPlay.ActionMsg, TRUE); - - uint8 header [7 + 1 + 4]; - uint8 *ptr = header; - int len = sizeof (header) + Memory.CalculatedSize + - strlen (Memory.ROMFilename) + 1; - *ptr++ = NP_SERV_MAGIC; - *ptr++ = NPServer.Clients [c].SendSequenceNum++; - *ptr++ = NP_SERV_ROM_IMAGE; - WRITE_LONG (ptr, len); - ptr += 4; - *ptr++ = Memory.HiROM; - WRITE_LONG (ptr, Memory.CalculatedSize); - - if (!S9xNPSSendData (NPServer.Clients [c].Socket, header, sizeof (header)) || - !S9xNPSSendData (NPServer.Clients [c].Socket, Memory.ROM, - Memory.CalculatedSize) || - !S9xNPSSendData (NPServer.Clients [c].Socket, (uint8 *) Memory.ROMFilename, - strlen (Memory.ROMFilename) + 1)) - { - S9xNPShutdownClient (c, TRUE); - return (FALSE); - } - return (TRUE); -} - -void S9xNPSyncClients () -{ - S9xNPNoClientReady (); - S9xNPSyncClient (-1); -} - -void S9xNPSyncClient (int client) -{ -#ifdef HAVE_MKSTEMP - char fname[] = "/tmp/snes9x_fztmpXXXXXX"; -#else - char fname [L_tmpnam]; -#endif - - S9xNPWaitForEmulationToComplete (); - - S9xNPSetAction ("SERVER: Freezing game...", TRUE); -#ifdef HAVE_MKSTEMP - if ( (mkstemp(fname) < 0) && S9xFreezeGame(fname) ) -#else - if ( tmpnam(fname) && S9xFreezeGame(fname) ) -#endif - { - uint8 *data; - uint32 len; - - S9xNPSetAction ("SERVER: Loading freeze file...", TRUE); - if (S9xNPLoadFreezeFile (fname, data, len)) - { - int c; - - if (client < 0) - { - for (c = NP_ONE_CLIENT; c < NP_MAX_CLIENTS; c++) - { - if (NPServer.Clients [c].SaidHello) - { - NPServer.Clients [client].Ready = FALSE; - S9xNPRecomputePause (); - S9xNPSendFreezeFile (c, data, len); - } - } - } - else - { - NPServer.Clients [client].Ready = FALSE; - S9xNPRecomputePause (); - S9xNPSendFreezeFile (client, data, len); - } - delete data; - } - remove (fname); - } -} - -bool8 S9xNPLoadFreezeFile (const char *fname, uint8 *&data, uint32 &len) -{ - FILE *ff; - - if ((ff = fopen (fname, "rb"))) - { - fseek (ff, 0, SEEK_END); - len = ftell (ff); - fseek (ff, 0, SEEK_SET); - - data = new uint8 [len]; - bool8 ok = (fread (data, 1, len, ff) == len); - fclose (ff); - - return (ok); - } - return (FALSE); -} - -void S9xNPSendFreezeFile (int c, uint8 *data, uint32 len) -{ -#ifdef NP_DEBUG - printf ("SERVER: Sending freeze file to player %d @%ld\n", c + 1, S9xGetMilliTime () - START); -#endif - - sprintf (NetPlay.ActionMsg, "SERVER: Sending freeze-file to player %d...", c + 1); - S9xNPSetAction (NetPlay.ActionMsg, TRUE); - uint8 header [7 + 4]; - uint8 *ptr = header; - - *ptr++ = NP_SERV_MAGIC; - *ptr++ = NPServer.Clients [c].SendSequenceNum++; - *ptr++ = NP_SERV_FREEZE_FILE; - WRITE_LONG (ptr, len + 7 + 4); - ptr += 4; - WRITE_LONG (ptr, NPServer.FrameCount); - - if (!S9xNPSSendData (NPServer.Clients [c].Socket, header, 7 + 4) || - !S9xNPSSendData (NPServer.Clients [c].Socket, data, len)) - { - S9xNPShutdownClient (c, TRUE); - } -} - -void S9xNPRecomputePause () -{ - int c; - - for (c = 0; c < NP_MAX_CLIENTS; c++) - { - if (NPServer.Clients [c].SaidHello && - (!NPServer.Clients [c].Ready || NPServer.Clients [c].Paused)) - { -#if defined(NP_DEBUG) && NP_DEBUG == 2 - printf ("SERVER: Paused because of client %d (%d,%d) @%ld\n", c, NPServer.Clients [c].Ready, NPServer.Clients [c].Paused, S9xGetMilliTime () - START); -#endif - NPServer.Paused = TRUE; - return; - } - } -#if defined(NP_DEBUG) && NP_DEBUG == 2 - printf ("SERVER: not paused @%ld\n", S9xGetMilliTime () - START); -#endif - NPServer.Paused = FALSE; -} - -void S9xNPNoClientReady (int start_index) -{ - int c; - - for (c = start_index; c < NP_MAX_CLIENTS; c++) - NPServer.Clients [c].Ready = FALSE; - S9xNPRecomputePause (); -} - -void S9xNPSendROMLoadRequest (const char *filename) -{ - S9xNPNoClientReady (); - - int len = 7 + strlen (filename) + 1; - uint8 *data = new uint8 [len]; - uint8 *ptr = data; - *ptr++ = NP_SERV_MAGIC; - *ptr++ = 0; - *ptr++ = NP_SERV_LOAD_ROM; - WRITE_LONG (ptr, len); - ptr += 4; - strcpy ((char *) ptr, filename); - - for (int i = NP_ONE_CLIENT; i < NP_MAX_CLIENTS; i++) - { - if (NPServer.Clients [i].SaidHello) - { -#ifdef NP_DEBUG - printf ("SERVER: Sending load ROM requesting to player %d @%ld\n", i + 1, S9xGetMilliTime () - START); -#endif - sprintf (NetPlay.WarningMsg, "SERVER: sending ROM load request to player %d...", i + 1); - S9xNPSetAction (NetPlay.WarningMsg, TRUE); - data [1] = NPServer.Clients [i].SendSequenceNum++; - if (!S9xNPSSendData (NPServer.Clients [i].Socket, data, len)) - { - S9xNPShutdownClient (i, TRUE); - } - } - } - delete data; -} - -void S9xNPSendSRAMToAllClients () -{ - int i; - - for (i = NP_ONE_CLIENT; i < NP_MAX_CLIENTS; i++) - { - if (NPServer.Clients [i].SaidHello) - S9xNPSendSRAMToClient (i); - } -} - -void S9xNPSendSRAMToClient (int c) -{ -#ifdef NP_DEBUG - printf ("SERVER: Sending S-RAM data to player %d @%ld\n", c + 1, S9xGetMilliTime () - START); -#endif - uint8 sram [7]; - int SRAMSize = Memory.SRAMSize ? - (1 << (Memory.SRAMSize + 3)) * 128 : 0; - if (SRAMSize > 0x10000) - SRAMSize = 0x10000; - int len = 7 + SRAMSize; - - sprintf (NetPlay.ActionMsg, "SERVER: Sending S-RAM to player %d...", c + 1); - S9xNPSetAction (NetPlay.ActionMsg, TRUE); - - uint8 *ptr = sram; - *ptr++ = NP_SERV_MAGIC; - *ptr++ = NPServer.Clients [c].SendSequenceNum++; - *ptr++ = NP_SERV_SRAM_DATA; - WRITE_LONG (ptr, len); - if (!S9xNPSSendData (NPServer.Clients [c].Socket, - sram, sizeof (sram)) || - (len > 7 && - !S9xNPSSendData (NPServer.Clients [c].Socket, - ::SRAM, len - 7))) - { - S9xNPShutdownClient (c, TRUE); - } -} - -void S9xNPSendFreezeFileToAllClients (const char *filename) -{ - uint8 *data; - uint32 len; - - if (NPServer.NumClients > NP_ONE_CLIENT && S9xNPLoadFreezeFile (filename, data, len)) - { - S9xNPNoClientReady (); - - for (int c = NP_ONE_CLIENT; c < NP_MAX_CLIENTS; c++) - { - if (NPServer.Clients [c].SaidHello) - S9xNPSendFreezeFile (c, data, len); - } - delete data; - } -} - -void S9xNPServerAddTask (uint32 task, void *data) -{ - NPServer.TaskQueue [NPServer.TaskTail].Task = task; - NPServer.TaskQueue [NPServer.TaskTail].Data = data; - - NPServer.TaskTail = (NPServer.TaskTail + 1) % NP_MAX_TASKS; -} - -void S9xNPReset () -{ - S9xNPNoClientReady (0); - S9xNPServerAddTask (NP_SERVER_RESET_ALL, 0); -} - -void S9xNPWaitForEmulationToComplete () -{ -#ifdef NP_DEBUG - printf ("SERVER: WaitForEmulationToComplete start @%ld\n", S9xGetMilliTime () - START); -#endif - - while (!NetPlay.PendingWait4Sync && NetPlay.Connected && - !Settings.ForcedPause && !Settings.StopEmulation && - !Settings.Paused) - { -#ifdef __WIN32__ - Sleep (40); -#endif - } -#ifdef NP_DEBUG - printf ("SERVER: WaitForEmulationToComplete end @%ld\n", S9xGetMilliTime () - START); -#endif -} - -void S9xNPServerQueueSyncAll () -{ - if (Settings.NetPlay && Settings.NetPlayServer && - NPServer.NumClients > NP_ONE_CLIENT) - { - S9xNPNoClientReady (); - S9xNPDiscardHeartbeats (); - S9xNPServerAddTask (NP_SERVER_SYNC_ALL, 0); - } -} - -void S9xNPServerQueueSendingROMImage () -{ - if (Settings.NetPlay && Settings.NetPlayServer && - NPServer.NumClients > NP_ONE_CLIENT) - { - S9xNPNoClientReady (); - S9xNPDiscardHeartbeats (); - S9xNPServerAddTask (NP_SERVER_SEND_ROM_IMAGE, 0); - } -} - -void S9xNPServerQueueSendingFreezeFile (const char *filename) -{ - if (Settings.NetPlay && Settings.NetPlayServer && - NPServer.NumClients > NP_ONE_CLIENT) - { - S9xNPNoClientReady (); - S9xNPDiscardHeartbeats (); - S9xNPServerAddTask (NP_SERVER_SEND_FREEZE_FILE_ALL, - (void *) strdup (filename)); - } -} - -void S9xNPServerQueueSendingLoadROMRequest (const char *filename) -{ - if (Settings.NetPlay && Settings.NetPlayServer && - NPServer.NumClients > NP_ONE_CLIENT) - { - S9xNPNoClientReady (); - S9xNPDiscardHeartbeats (); - S9xNPServerAddTask (NP_SERVER_SEND_ROM_LOAD_REQUEST_ALL, - (void *) strdup (filename)); - } -} - -#ifndef __WIN32__ -uint32 S9xGetMilliTime () -{ - static bool8 first = TRUE; - static long start_sec; - struct timeval tv; - - gettimeofday (&tv, NULL); - if (first) - { - start_sec = tv.tv_sec; - first = FALSE; - } - return ((uint32) ((tv.tv_sec - start_sec) * 1000 + tv.tv_usec / 1000)); -} -#endif -#endif - |