OoT-Randomizer
OoT-Randomizer copied to clipboard
Multiworld on EverDrive
Now that we have a proof of concept of communicating with the game via the EverDrive's USB protocol (PC side, N64 side), it's time to figure out what the communication protocol is supposed to look like. Here's my current draft:
Design notes
All PC→N64 packets are exactly 16 bytes long to simplify the receiving code on the N64 side. N64→PC packets may be of any size supported by the EverDrive, i.e. anywhere between 16 and 512 bytes; the packet's size depends on its ID (first byte). This is because we may want to have N64 send large amounts of data when a file is selected, to make auto-tracking integration work. Unless noted otherwise, packets in either direction with a total length less than 16 bytes are padded with trailing zero bytes which are reserved for use in future versions of the protocol.
The protocol must seamlessly recover from state loss due to console reset. Fortunately, the console being reset causes the PC to see an existing connection as timed out even if the game is restarted within the timeout. It can then reconnect and start over. To achieve this, N64 sends periodic pings (every 100 frames, which corresponds to every 5 seconds while in-game and not paused), and PC sets a read timeout of 10 seconds (twice the ping interval).
Handshake
-
Communication is initiated by PC sending ASCII
cmdt
followed by a null suffix. The format of this handshake is chosen to also be a valid command if N64 is in the EverDrive's main menu, which allows PC to determine the console's state based on the reply. The suffix must remain null in future versions for compatibility with the main menu. -
N64 sends ASCII
OoTR
followed by:- The protocol version byte (currently
0x01
). If PC does not support this protocol version, it must close the connection now, any reply indicates support for this version. -
get_version_bytes
, i.e. a 5-byte sequence encoding the randomizer version number: major, minor, patch, branch identifier, supplementary version. - The world number.
-
CFG_FILE_SELECT_HASH
, i.e. the 5 icons displayed at the top of the file select screen, represented as indices into theHASH_ICONS
list in Spoiler.py.
If PC instead receives ASCII
cmdr
orcmdk
, the N64 is in the EverDrive main menu. PC can either continue to use this connection via the main menu protocol, or disconnect and retry after an amount of time. - The protocol version byte (currently
-
PC sends ASCII
MW
followed by:- the protocol version byte (must be the same one that was received)
-
MW_SEND_OWN_ITEMS
(a Boolean flag indicating whether to enable this feature) -
MW_PROGRESSIVE_ITEMS_ENABLE
(a Boolean flag indicating whether to enable this feature)
This step is designed to allow reusing the handshake for something other than multiworld, e.g. auto-tracking, debugging, or crowd control. For those alternative use-cases, the PC would respond with a different packet prefix here, and the “normal operation” part of this protocol would be ignored in favor of a different protocol for the given purpose.
-
Normal operation commences with N64 sending a state packet and PC simultaneously sending player names. Once PC has received the state packet, it may also immediately send items to restore the queue. More info in the following two sections.
Normal operation: PC→N64
The following packet IDs are used:
-
0x00
Ping- sent every 5 seconds
-
0x01
Player Data- the world number (1 byte)
- the player name (8 bytes in OoT's internal player name format)
- progressive items state (4 bytes, see
mw_progressive_items_state_t
initem_upgrades.c
, PC may set this to 0 ifMW_PROGRESSIVE_ITEMS_ENABLE
is off)
-
0x02
Get Item- item kind (2 bytes)
- Only one item may be sent after each time the N64 sends “State: In Game” or “Item Received”, and only items past the internal item count are sent
-
0x63
(ASCIIc
) indicates that PC has reset (e.g. the multiworld app has been relaunched). N64 should reset its connection state and treat the incoming packet as the first part of a new handshake.
Normal operation: N64→PC
The following packet IDs are used:
-
0x00
Ping- sent every 5 seconds
-
0x01
State: File Select- the player name: 8 bytes in the internal player name format, 8 spaces (
DFDFDFDFDFDFDFDF
) if not set - Sent after completion of the handshake if not ingame, or if the selected filename changes
- the player name: 8 bytes in the internal player name format, 8 spaces (
-
0x02
State: In Game- internal item count (2 bytes)
- relevant parts of save data (TODO which?)
- Sent after completion of the handshake if ingame, or if a file is opened
-
0x03
Send Item- override key (8 bytes)
- item kind (2 bytes)
- target world (1 byte)
-
0x04
Item Received- tells PC that another Get Item packet may be sent