<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://mupen64plus.org/wiki/index.php?action=history&amp;feed=atom&amp;title=Mupen64Plus_v2.0_Core_Netplay_Protocol</id>
	<title>Mupen64Plus v2.0 Core Netplay Protocol - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://mupen64plus.org/wiki/index.php?action=history&amp;feed=atom&amp;title=Mupen64Plus_v2.0_Core_Netplay_Protocol"/>
	<link rel="alternate" type="text/html" href="https://mupen64plus.org/wiki/index.php?title=Mupen64Plus_v2.0_Core_Netplay_Protocol&amp;action=history"/>
	<updated>2026-10-18T14:35:40Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.14</generator>
	<entry>
		<id>https://mupen64plus.org/wiki/index.php?title=Mupen64Plus_v2.0_Core_Netplay_Protocol&amp;diff=96&amp;oldid=prev</id>
		<title>Richard42: Created page with &quot;Mupen64Plus v2.0 API  = Mupen64Plus Netplay Protocol =  The Mupen64Plus netplay protocol is based on a client/server architecture. It suppor...&quot;</title>
		<link rel="alternate" type="text/html" href="https://mupen64plus.org/wiki/index.php?title=Mupen64Plus_v2.0_Core_Netplay_Protocol&amp;diff=96&amp;oldid=prev"/>
		<updated>2020-06-28T18:21:12Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;&lt;a href=&quot;/wiki/index.php/Mupen64Plus_v2.0_Core_API_v1.0&quot; title=&quot;Mupen64Plus v2.0 Core API v1.0&quot;&gt;Mupen64Plus v2.0 API&lt;/a&gt;  = Mupen64Plus Netplay Protocol =  The Mupen64Plus netplay protocol is based on a client/server architecture. It suppor...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;[[Mupen64Plus v2.0 Core API v1.0|Mupen64Plus v2.0 API]]&lt;br /&gt;
&lt;br /&gt;
= Mupen64Plus Netplay Protocol =&lt;br /&gt;
&lt;br /&gt;
The Mupen64Plus netplay protocol is based on a client/server architecture. It supports syncing core settings and save files. It also supports raw input (tested with Raphnet input plugin).&lt;br /&gt;
TCP is used to deal with player registration, and syncing settings and saves.&lt;br /&gt;
UDP is used to transfer key input data.&lt;br /&gt;
Data is sent in Network Byte Order (Big Endian).&lt;br /&gt;
&lt;br /&gt;
The server is responsible for maintaining healthy buffers and also for detecting desyncs. The server is the source of truth for input data (for instance, when player 1 pushes &amp;quot;A&amp;quot;, it sends that information to the server via UDP. That &amp;quot;A&amp;quot; is not registered as input for player 1 until the client receives a packet from the server indicating what input frame to register that &amp;quot;A&amp;quot; in)&lt;br /&gt;
&lt;br /&gt;
== UDP Packet formats ==&lt;br /&gt;
* Request input for a player (sent by client):&lt;br /&gt;
** 12 bytes&lt;br /&gt;
** byte[0] = 2&lt;br /&gt;
** byte[1] = player number (this is the player we need key inputs for)&lt;br /&gt;
** byte[2-5] = client registration ID&lt;br /&gt;
** byte[6-9] = current event count&lt;br /&gt;
** byte[10] = whether client is a spectator&lt;br /&gt;
** byte[11] = local buffer size of the client&lt;br /&gt;
&lt;br /&gt;
* Key input data (sent by server):&lt;br /&gt;
** Variable length, payload cannot be larger than 512 bytes&lt;br /&gt;
** byte[0] = 1&lt;br /&gt;
** byte[1] = player number the key inputs pertain to&lt;br /&gt;
** byte[2] = current status. Bit 0 indicates whether the game has desynced (1 means desync). Bits 1-4 indicate whether a player has disconnected (for instance, if bit 2 is set, that means player 2 has disconnected). Bits 5-7 are currently unused.&lt;br /&gt;
** byte[3] = how far we lag behind the lead player&lt;br /&gt;
** byte[4] = number of events in this packet&lt;br /&gt;
** The following items will repeat/loop for the number of events in the packet&lt;br /&gt;
*** byte[5-8] = event count&lt;br /&gt;
*** byte[9-12] = key input data&lt;br /&gt;
*** byte[13] = current plugin&lt;br /&gt;
&lt;br /&gt;
* Key input data (sent by client):&lt;br /&gt;
** 11 bytes&lt;br /&gt;
** byte[0] = 0&lt;br /&gt;
** byte[1] = player number&lt;br /&gt;
** byte[2-5] = current event count&lt;br /&gt;
** byte[6-9] = key input data&lt;br /&gt;
** byte[10] = current plugin&lt;br /&gt;
&lt;br /&gt;
* Client sync data (sent by client):&lt;br /&gt;
** 133 bytes&lt;br /&gt;
** byte[0] = 4&lt;br /&gt;
** byte[1-4] = current VI count&lt;br /&gt;
** byte[5-132] = CP0 registers&lt;br /&gt;
&lt;br /&gt;
== TCP Packet formats ==&lt;br /&gt;
* Player disconnection notice (sent by client):&lt;br /&gt;
** 5 bytes&lt;br /&gt;
** byte[0] = 7&lt;br /&gt;
** byte[1-4] = client registration ID&lt;br /&gt;
&lt;br /&gt;
* Player registration request (sent by client):&lt;br /&gt;
** 8 bytes&lt;br /&gt;
** byte[0] = 5&lt;br /&gt;
** byte[1] = player the client is trying to register&lt;br /&gt;
** byte[2] = plugin for this player&lt;br /&gt;
** byte[3] = whether to use a raw input plugin&lt;br /&gt;
** byte[4-7] = client registration ID&lt;br /&gt;
&lt;br /&gt;
* Player registration response (sent by server):&lt;br /&gt;
** 2 bytes&lt;br /&gt;
** byte[0] = response (1 if registration was successful, 0 otherwise)&lt;br /&gt;
** byte[1] = local buffer target for the client&lt;br /&gt;
&lt;br /&gt;
* Send save file data (sent by client):&lt;br /&gt;
** Variable length&lt;br /&gt;
** byte[0] = 1&lt;br /&gt;
** byte[1 - next &amp;#039;\0&amp;#039;] = file name&lt;br /&gt;
** byte[4 bytes] = size of save file in bytes&lt;br /&gt;
** byte[size of file] = save file data&lt;br /&gt;
&lt;br /&gt;
* Request save file data (sent by client):&lt;br /&gt;
** Variable length&lt;br /&gt;
** byte[0] = 2&lt;br /&gt;
** byte[1 - next &amp;#039;\0&amp;#039;] = file name&lt;br /&gt;
&lt;br /&gt;
* Receive save file data (sent by server):&lt;br /&gt;
** Server responds with this data right after the above request&lt;br /&gt;
** Variable length&lt;br /&gt;
** byte[file size] = save file data&lt;br /&gt;
&lt;br /&gt;
* Send settings (sent by client):&lt;br /&gt;
** 21 bytes&lt;br /&gt;
** byte[0] = 3&lt;br /&gt;
** byte[1-4] = count_per_op&lt;br /&gt;
** byte[5-8] = disable_extra_mem&lt;br /&gt;
** byte[9-12] = si_dma_duration&lt;br /&gt;
** byte[13-16] = emumode&lt;br /&gt;
** byte[17-20] =  no_compiled_jump&lt;br /&gt;
&lt;br /&gt;
* Request settings (sent by client):&lt;br /&gt;
** 1 byte&lt;br /&gt;
** byte[0] = 4&lt;br /&gt;
&lt;br /&gt;
* Send settings (sent by server):&lt;br /&gt;
** Server responds with this data right after the above request&lt;br /&gt;
** 20 bytes&lt;br /&gt;
** byte[0-3] = count_per_op&lt;br /&gt;
** byte[4-7] = disable_extra_mem&lt;br /&gt;
** byte[8-11] = si_dma_duration&lt;br /&gt;
** byte[12-15] = emumode&lt;br /&gt;
** byte[16-19] = no_compiled_jump&lt;br /&gt;
&lt;br /&gt;
* Request player registration data (sent by client):&lt;br /&gt;
** 1 byte&lt;br /&gt;
** byte[0] = 6&lt;br /&gt;
&lt;br /&gt;
* Send player registration data (sent by server):&lt;br /&gt;
** 24 bytes&lt;br /&gt;
** The following bytes loop 4 times (once for each player)&lt;br /&gt;
*** byte[0-3] = player registration ID&lt;br /&gt;
*** byte[4] = player plugin&lt;br /&gt;
*** byte[5] = whether the player is using raw data input&lt;/div&gt;</summary>
		<author><name>Richard42</name></author>
	</entry>
</feed>