91 lines
3.1 KiB
Plaintext
91 lines
3.1 KiB
Plaintext
|
FCE Ultra 0.91+ network play protocol.
|
||
|
Description v 0.0.1
|
||
|
--------------------------------------
|
||
|
|
||
|
In FCE Ultra, all data is sent to the server, and then the server
|
||
|
distributes, every emulated frame(60hz on NTSC), the collated data to the
|
||
|
clients.
|
||
|
|
||
|
The server should not block when it is receiving UDP data from the clients.
|
||
|
If no UDP data is available, then just go on.
|
||
|
|
||
|
The clients MUST block until the input data packet comes on every emulated
|
||
|
frame.
|
||
|
|
||
|
Packets from the server to the client are sent out over both TCP and UDP.
|
||
|
Duplicate packets should be discarded. Out-of-order packets can either
|
||
|
be cached, or discarded(what I recommend, as caching code gets a little
|
||
|
complex and wouldn't yield any benefit from what I've observed).
|
||
|
In the case of client->server UDP communications, the server should just use
|
||
|
the data from the UDP packet that has the highest packet number count, and
|
||
|
the server should then set its internal incoming packet counter to that
|
||
|
number(to prevent out-of-order packets from totally screwing up user input).
|
||
|
|
||
|
The "magic number"(used with UDP packets) is meant to reduce the chance of a hostile remote host
|
||
|
from disrupting the network play, without resorting to using extreme amounts
|
||
|
of network bandwidth. The server generates the magic number, and it is best
|
||
|
if the magic number is as random as possible.
|
||
|
UDP packets received with an incorrect magic number should be discarded, of
|
||
|
course.
|
||
|
|
||
|
Initialization, server->client:
|
||
|
|
||
|
uint32 Local UDP port(what the server is listening on).
|
||
|
uint32 Player number(0-3) for client.
|
||
|
uint32 Magic number(for UDP).
|
||
|
|
||
|
|
||
|
Initialization, client->server
|
||
|
|
||
|
uint32 Local UDP port(that the client is listening on).
|
||
|
|
||
|
|
||
|
Structure of UDP packet data:
|
||
|
|
||
|
uint32 CRC32 - Includes magic number, packet counter, and
|
||
|
data. For reference, CRC32 is calculated
|
||
|
with the zlib function crc32().
|
||
|
uint32 Magic number
|
||
|
uint32 Packet counter(linear, starts at 0).
|
||
|
uint8[variable] Data.
|
||
|
|
||
|
Structure of tcp packet data:
|
||
|
|
||
|
uint32 Packet counter(" ").
|
||
|
uint8[variable] Data.
|
||
|
|
||
|
|
||
|
|
||
|
Data format of server->client communications:
|
||
|
|
||
|
uint8[4] Controller data
|
||
|
uint8 Command byte. 0 if no command. Otherwise(in decimal):
|
||
|
|
||
|
1 Select FDS disk side.
|
||
|
2 Insert/eject FDS disk.
|
||
|
10 Toggle VS Unisystem dip switch editing.
|
||
|
11 ... 18 Toggle VS Unisystem dip switches.
|
||
|
19 Insert VS Unisystem coin.
|
||
|
30 Reset NES.
|
||
|
31 Power toggle NES.
|
||
|
40 Save state(not implemented correctly).
|
||
|
41 Load state(not implemented correctly).
|
||
|
42 ... 50 Select save state slot(minus 42).
|
||
|
|
||
|
Special message communications occurs if the "Packet counter" is
|
||
|
0xFFFFFFFF(only with TCP):
|
||
|
|
||
|
uint32 Length of text data, minus the null character(the null
|
||
|
character is sent, though).
|
||
|
uint8[variable] Text data. Convert all characters <32 to space, and
|
||
|
then display the text message(it's one line) as is.
|
||
|
|
||
|
Structure of client->server communication:
|
||
|
|
||
|
uint8 Controller data(for this client).
|
||
|
|
||
|
Over tcp channel, a text message can be sent. It is one line,
|
||
|
null terminated(remember the data and parse it and display it and
|
||
|
distribute it to the clients once the null byte is received).
|
||
|
Maximum size of message(including the null byte) should be 256 bytes.
|