📄 netplay.cpp
字号:
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; } char fname [L_tmpnam]; FILE *tmp; if (tmpnam (fname)) { if ((tmp = fopen (fname, "wb"))) { if (fwrite (data, 1, len, tmp) == len) { fclose (tmp); if (!S9xUnfreezeGame (fname)) S9xNPSetError ("Unable to load freeze file just received."); } else fclose (tmp); } remove (fname); } 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 (){ static bool8 initialised = FALSE;#ifdef __WIN32__ 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); }#endifvoid 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}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -