aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--source/netplay.cpp1048
-rw-r--r--source/server.cpp1303
3 files changed, 2 insertions, 2353 deletions
diff --git a/Makefile b/Makefile
index a2a1280..0d8faeb 100644
--- a/Makefile
+++ b/Makefile
@@ -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
-