Open fenhl opened 1 year ago
What about flashcarts other than EverDrive64? N64 homebrew community has developed an universal USB library - UNFLoader - that supports most common flashcarts available on the market. It's been successfully integrated in several projects, including:
Locking this feature to EverDrive64 v3/X7 doesn't really make sense since other flashcarts (64drive/SummerCart64) include USB port as a standard feature, while most EverDrive64 models out there doesn't even have this port available.
I'm not familiar enough with projects like libultra and libdragon to be able to integrate this into OoTR, but I think if someone were to contribute support for these additional flashcarts, it would most likely be accepted.
The current work-in-progress implementation of this protocol can be found on my fork of the randomizer.
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
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: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.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.PC sends ASCII
MW
followed by: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: PC→N64
The following packet IDs are used:
0x00
Ping0x01
Player Datamw_progressive_items_state_t
initem_upgrades.c
, PC may set this to 0 ifMW_PROGRESSIVE_ITEMS_ENABLE
is off)0x02
Get Item0x63
(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
Ping0x01
State: File SelectDFDFDFDFDFDFDFDF
) if not set0x02
State: In Game0x03
Send Item0x04
Item ReceivedTODO