⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server.cpp

📁 著名SFC模拟器Snes9x的源代码。
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. * * (c) Copyright 1996 - 2001 Gary Henderson (gary@daniver.demon.co.uk) and *                           Jerremy Koot (jkoot@snes9x.com) * * Super FX C emulator code  * (c) Copyright 1997 - 1999 Ivar (Ivar@snes9x.com) and *                           Gary Henderson. * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. * * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. * C4 C code (c) Copyright 2001 Gary Henderson (gary@daniver.demon.co.uk). * * DOS port code contains the works of other authors. See headers in * individual files. * * Snes9x homepage: 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. */#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>#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 1struct 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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -