2018-11-16 00:42:29 +01:00
|
|
|
/*****************************************************************************\
|
|
|
|
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
|
|
|
|
This file is licensed under the Snes9x License.
|
|
|
|
For further information, consult the LICENSE file in the root directory.
|
|
|
|
\*****************************************************************************/
|
|
|
|
|
2010-09-25 17:46:12 +02:00
|
|
|
#include <glib.h>
|
|
|
|
|
|
|
|
#include "gtk_s9x.h"
|
|
|
|
#include "gtk_netplay_dialog.h"
|
|
|
|
#include "gtk_netplay.h"
|
|
|
|
#include "gtk_sound.h"
|
|
|
|
|
|
|
|
uint16 MovieGetJoypad (int i);
|
|
|
|
void MovieSetJoypad (int i, uint16 buttons);
|
|
|
|
|
|
|
|
static uint32 local_joypads[8], joypads[8];
|
|
|
|
static GThread *npthread;
|
|
|
|
|
|
|
|
extern SNPServer NPServer;
|
|
|
|
|
|
|
|
static void
|
2018-11-02 21:52:26 +01:00
|
|
|
S9xNetplayPreconnect ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
S9xNetplayDisconnect ();
|
|
|
|
|
|
|
|
if (gui_config->rom_loaded)
|
|
|
|
{
|
|
|
|
S9xAutoSaveSRAM ();
|
|
|
|
}
|
|
|
|
|
|
|
|
NetPlay.MaxBehindFrameCount = gui_config->netplay_max_frame_loss;
|
2018-12-28 23:32:32 +01:00
|
|
|
NetPlay.Waiting4EmulationThread = false;
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2018-11-02 21:52:26 +01:00
|
|
|
S9xNetplayConnect ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
GtkWidget *msg;
|
|
|
|
|
|
|
|
S9xNetplayPreconnect ();
|
|
|
|
|
|
|
|
uint32 flags = CPU.Flags;
|
|
|
|
|
2018-12-29 01:36:23 +01:00
|
|
|
if (!gui_config->netplay_last_rom.empty () &&
|
|
|
|
!top_level->try_open_rom (gui_config->netplay_last_rom.c_str ()))
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-12-29 01:36:23 +01:00
|
|
|
if (!S9xNPConnectToServer (gui_config->netplay_last_host.c_str (),
|
2010-09-25 17:46:12 +02:00
|
|
|
gui_config->netplay_last_port,
|
|
|
|
Memory.ROMName))
|
|
|
|
{
|
|
|
|
msg = gtk_message_dialog_new (NULL,
|
|
|
|
GTK_DIALOG_DESTROY_WITH_PARENT,
|
|
|
|
GTK_MESSAGE_ERROR,
|
|
|
|
GTK_BUTTONS_CLOSE,
|
|
|
|
"Couldn't connect to server: %s:%d",
|
2018-12-29 01:36:23 +01:00
|
|
|
gui_config->netplay_last_host.c_str (),
|
2010-09-25 17:46:12 +02:00
|
|
|
gui_config->netplay_last_port);
|
2010-09-26 11:19:15 +02:00
|
|
|
gtk_window_set_title (GTK_WINDOW (msg), _("Connection Error"));
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
gtk_dialog_run (GTK_DIALOG (msg));
|
|
|
|
gtk_widget_destroy (msg);
|
|
|
|
}
|
|
|
|
|
2018-12-28 23:32:32 +01:00
|
|
|
gui_config->netplay_activated = true;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
/* If no rom is specified, assume we'll get it from the server */
|
2018-12-29 01:36:23 +01:00
|
|
|
if (gui_config->netplay_last_rom.empty ())
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
2018-12-28 23:32:32 +01:00
|
|
|
Settings.StopEmulation = false;
|
2010-09-25 17:46:12 +02:00
|
|
|
S9xROMLoaded ();
|
|
|
|
}
|
|
|
|
|
|
|
|
S9xReset ();
|
|
|
|
|
|
|
|
CPU.Flags = flags;
|
|
|
|
|
|
|
|
top_level->configure_widgets ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
S9xNetplaySyncClients ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
if (Settings.NetPlay && Settings.NetPlayServer)
|
|
|
|
S9xNPServerQueueSyncAll ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
S9xNetplayStopServer ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
S9xNPStopServer ();
|
|
|
|
|
|
|
|
g_thread_join (npthread);
|
2018-12-28 23:32:32 +01:00
|
|
|
Settings.NetPlayServer = false;
|
|
|
|
gui_config->netplay_server_up = false;
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
S9xNetplayDisconnect ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
if (Settings.NetPlay)
|
|
|
|
{
|
|
|
|
if (NetPlay.Connected)
|
|
|
|
S9xNPDisconnect ();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gui_config->netplay_server_up)
|
|
|
|
{
|
|
|
|
S9xNetplayStopServer ();
|
|
|
|
}
|
|
|
|
|
2018-12-28 23:32:32 +01:00
|
|
|
gui_config->netplay_activated = false;
|
|
|
|
NetPlay.Paused = false;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
top_level->configure_widgets ();
|
|
|
|
}
|
|
|
|
|
|
|
|
static gpointer
|
|
|
|
S9xNetplayServerThread (gpointer)
|
|
|
|
{
|
|
|
|
S9xNPStartServer (gui_config->netplay_default_port);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
S9xNetplayStartServer ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
uint32 flags;
|
|
|
|
|
|
|
|
S9xNetplayPreconnect ();
|
|
|
|
|
|
|
|
flags = CPU.Flags;
|
|
|
|
|
2018-12-29 01:36:23 +01:00
|
|
|
if (gui_config->netplay_last_rom.empty () ||
|
|
|
|
!top_level->try_open_rom (gui_config->netplay_last_rom.c_str ()))
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-12-28 23:32:32 +01:00
|
|
|
Settings.NetPlayServer = true;
|
2010-09-25 17:46:12 +02:00
|
|
|
NPServer.SyncByReset = gui_config->netplay_sync_reset;
|
|
|
|
NPServer.SendROMImageOnConnect = gui_config->netplay_send_rom;
|
|
|
|
|
2017-09-12 02:32:10 +02:00
|
|
|
npthread = g_thread_new (NULL, S9xNetplayServerThread, NULL);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
/* Sleep to let the server create itself */
|
|
|
|
usleep (10000);
|
|
|
|
|
|
|
|
S9xNPConnectToServer ("127.0.0.1",
|
|
|
|
gui_config->netplay_default_port,
|
|
|
|
Memory.ROMName);
|
|
|
|
|
|
|
|
S9xReset ();
|
|
|
|
|
|
|
|
S9xROMLoaded ();
|
|
|
|
|
2018-12-28 23:32:32 +01:00
|
|
|
gui_config->netplay_activated = true;
|
|
|
|
gui_config->netplay_server_up = true;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
CPU.Flags = flags;
|
|
|
|
|
|
|
|
top_level->configure_widgets ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
S9xNetplayDialogOpen ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
Snes9xNetplayDialog *np_dialog;
|
|
|
|
|
|
|
|
top_level->pause_from_focus_change ();
|
|
|
|
|
|
|
|
np_dialog = new Snes9xNetplayDialog (gui_config);
|
|
|
|
|
|
|
|
gtk_window_set_transient_for (np_dialog->get_window (),
|
|
|
|
top_level->get_window ());
|
|
|
|
|
|
|
|
if (np_dialog->show ())
|
|
|
|
{
|
|
|
|
if (!gui_config->netplay_is_server)
|
|
|
|
{
|
|
|
|
S9xNetplayConnect ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
S9xNetplayStartServer ();
|
|
|
|
}
|
|
|
|
|
|
|
|
S9xSoundStart ();
|
|
|
|
}
|
|
|
|
|
|
|
|
delete np_dialog;
|
|
|
|
|
|
|
|
top_level->unpause_from_focus_change ();
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-11-02 21:52:26 +01:00
|
|
|
S9xNetplaySyncSpeed ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
if (!Settings.NetPlay || !NetPlay.Connected)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// Send 1st joypad's position update to server
|
|
|
|
S9xNPSendJoypadUpdate (local_joypads[0]);
|
|
|
|
|
|
|
|
// set input from network
|
|
|
|
for (int i = 0; i < NP_MAX_CLIENTS; i++)
|
|
|
|
joypads[i] = S9xNPGetJoypad (i);
|
|
|
|
|
|
|
|
if (!S9xNPCheckForHeartBeat ())
|
|
|
|
{
|
|
|
|
// No heartbeats already arrived, have to wait for one.
|
|
|
|
NetPlay.PendingWait4Sync = !S9xNPWaitForHeartBeatDelay (100);
|
|
|
|
|
2018-12-28 23:32:32 +01:00
|
|
|
IPPU.RenderThisFrame = true;
|
2010-09-25 17:46:12 +02:00
|
|
|
IPPU.SkippedFrames = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int difference = (int) (NetPlay.MySequenceNum) -
|
|
|
|
(int) (NetPlay.ServerSequenceNum);
|
|
|
|
|
|
|
|
if (difference < 0)
|
|
|
|
difference += 256;
|
|
|
|
|
|
|
|
if (NetPlay.Waiting4EmulationThread)
|
|
|
|
{
|
|
|
|
if ((unsigned int) difference <= (NetPlay.MaxBehindFrameCount / 2))
|
|
|
|
{
|
2018-12-28 23:32:32 +01:00
|
|
|
NetPlay.Waiting4EmulationThread = false;
|
|
|
|
S9xNPSendPause (false);
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((unsigned int) difference >= (NetPlay.MaxBehindFrameCount))
|
|
|
|
{
|
2018-12-28 23:32:32 +01:00
|
|
|
NetPlay.Waiting4EmulationThread = true;
|
|
|
|
S9xNPSendPause (true);
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NetPlay.PendingWait4Sync = !S9xNPWaitForHeartBeatDelay (200);
|
|
|
|
|
|
|
|
if (IPPU.SkippedFrames < NetPlay.MaxFrameSkip)
|
|
|
|
{
|
|
|
|
IPPU.SkippedFrames++;
|
2018-12-28 23:32:32 +01:00
|
|
|
IPPU.RenderThisFrame = false;
|
2010-09-25 17:46:12 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-12-28 23:32:32 +01:00
|
|
|
IPPU.RenderThisFrame = true;
|
2010-09-25 17:46:12 +02:00
|
|
|
IPPU.SkippedFrames = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!NetPlay.PendingWait4Sync)
|
|
|
|
{
|
|
|
|
NetPlay.FrameCount++;
|
|
|
|
S9xNPStepJoypadHistory ();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2018-11-02 21:52:26 +01:00
|
|
|
S9xNetplayPush ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
if (gui_config->netplay_activated &&
|
|
|
|
(!Settings.NetPlay || !NetPlay.Connected))
|
|
|
|
S9xNetplayDisconnect ();
|
|
|
|
|
|
|
|
if (!Settings.NetPlay)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (NetPlay.PendingWait4Sync && !S9xNPWaitForHeartBeatDelay (100))
|
|
|
|
{
|
2018-12-28 23:32:32 +01:00
|
|
|
S9xProcessEvents (false);
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
S9xSoundStop ();
|
2018-12-28 23:32:32 +01:00
|
|
|
NetPlay.Paused = true;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-12-28 23:32:32 +01:00
|
|
|
NetPlay.Paused = false;
|
2010-09-25 17:46:12 +02:00
|
|
|
|
|
|
|
S9xSoundStart ();
|
|
|
|
|
|
|
|
/* Save the joypad input */
|
|
|
|
for (int i = 0; i < 8; i++)
|
|
|
|
{
|
|
|
|
local_joypads[i] = MovieGetJoypad (i);
|
|
|
|
|
|
|
|
MovieSetJoypad (i, joypads[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NetPlay.PendingWait4Sync)
|
|
|
|
{
|
2018-12-28 23:32:32 +01:00
|
|
|
NetPlay.PendingWait4Sync = false;
|
2010-09-25 17:46:12 +02:00
|
|
|
NetPlay.FrameCount++;
|
|
|
|
S9xNPStepJoypadHistory ();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-11-02 21:52:26 +01:00
|
|
|
S9xNetplayPop ()
|
2010-09-25 17:46:12 +02:00
|
|
|
{
|
|
|
|
if (!Settings.NetPlay)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (int i = 0; i < 8; i++)
|
|
|
|
MovieSetJoypad (i, local_joypads[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|