-
Notifications
You must be signed in to change notification settings - Fork 34
4) The EverDrive 3.0 and X7
This page describes how the UNFLoader tool and USB library handles the EverDrive flash carts.
The EverDrive 3.0 and X7 are made by KRIKzz, with the X7 still being sold on his website. It features a slower 1MB/s USB FTDI chip, and all documentation is available solely through the official OS code on KRIKzz's git page. There is a current ongoing effort by NetworkFusion to improve the documentation for the cart.
Unlike the 64Drive, the EverDrive must first be booted into for USB functions to work. This is because the initial ROM loading process has to be done through whatever OS is currently running on the cart. For simplification reasons, this wiki page will assume you are using either KRIKzz's OS, or NetworkFusion's unofficial OS (which uses the same OS USB protocol as KRIKzz's). However, an SD card is not a requirement for loading ROMs through USB!
UNFLoader implemented EverDrive communication using the D2XX FTDI library.
As of the 3.04 update, the EverDrive 3.0 and X7 do not have any major differences in their USB protocol. Originally, the two were completely different and code had to be written to handle both carts seperately, but that update has since then simplified it, making the 3.0's addresses and communication protocol match the X7's.
This page will assume either device is on the 3.04+ update. The 3.0 behaves completely differently prior to that firmware update.
Unlike the 64Drive, the EverDrive's device description does not contain useful information, with the description being "FT245R USB FIFO" and the ID being 0x04036001. Instead, we must send the 't' command (with the size, address and extra arguments being irrelevant). If the device replies back 16 bytes, with the third byte being an 'r', then an EverDrive can be assumed to be is connected. This must be done with the console turned on and the EverDrive in the menu.
Unlike the 64Drive, the EverDrive does not feature a magic value which we can read from easily by design. In order to detect whether the game is running on an EverDrive, you need to write 0xAA55 to the register located at 0x1F808004 using usb_io_write, then call usb_io_read to the register at 0x1F808004. Use the following table to check the resulting values against:
| EverDrive Revision |
usb_io_read result |
|---|---|
| EverDrive 2.5 (USB unsupported) | 0xED640007 |
| EverDrive 3.0 | 0xED640008 |
| EverDrive X7 | 0xED640013 |
Writing to random registers is a bit of a risky thing, but it is how the ED is designed. Therefore, the EverDrive is checked last in the USB library in order to avoid crashing other flashcarts. In practice, writing to these addresses hasn't caused problems for the 64Drive, but the potential is always there...
Once the device is confirmed to be a 3.0 or X7, use usb_io_write to write a zero to 0x1F808000 and 0xC400 to 0x1F800004 in order to initialize the USB subsystem.
Open the device and set its timeouts to a large enough value (by default, 500 milliseconds). It is recommended to purge the receive and transmission buffers before continuing any further.
The EverDrive's USB protocol is only used before/during the ROM USB upload process. All commands begin with 'c', 'm', 'd', followed by a fourth byte which dictates the command (check the OS source code for a list of commands). Afterwards, 4 bytes are used for the address, 4 for the size, and 4 more for any extra arguments. 16 bytes must be always sent.
If the ROM is less than 1MB, the c command with 0x10000000 and 0x100000 + 4096 as arguments must be sent, as well as the t command right after. The ED will echo back 16 bytes as an acknowledgement. This is to ensure that the ED will know to pad the ROM. Afterwards, the W command can be sent, once again with 0x10000000 and the actual size of the ROM (with padding if needed) as arguments. Now the ROM can be uploaded in chunks with multiple USB write calls. Once finished, you must send the s command to boot the ROM. It is recommended that the pifboot command be sent with a delay after the ROM has been fully uploaded to prevent any problems with the boot process.
If you wish to change the savetype through USB, the save values must be appended to the ROM itself (It is recommended that you make a copy of the ROM and upload the copy, so that you can modify the header without affecting the original ROM). To do so, modify byte 0x3C with 0x45 (ASCII value for E) and modify byte 0x3D with 0x44 (ASCII value for D). This tells the EverDrive that the ROM will contain extra information in the offset 0x3F. The high nibble will represent which save type to use (The full table of values can be accessed here, while the low nibble with represent whether to use the Real Time Clock or not (0x01 for true, 0x00 for false. Using the value 0x02 will state that your ROM is region free). Once the save value has been set, you must send 256 bytes with the filename that will be used to store the save file in. The filename should preferably match your ROM, and should not have an extension attached. The save file will only be created if any save data is actually made.
In order to send data to the connected PC, you can check out the source code to ED64-XIO in KRIKzz's git repo, specifically, the function sysPI_wr in sys.c, and bi_reg_wr + bi_usb_wr in bios.c. Make sure that you 16 byte align all data before sending it.
The EverDrive does not have a standard USB communication protocol, therefore, if you want your code to be compatible with UNFLoader, you must append the DMA@ header to the start of your data, and the CMPH signal to the end.
CMPH if needed.
On the PC side, simply just write data to USB as everything should be handled by the executing ROM. The EverDrive does not have a standard USB communication protocol, therefore, if you want your code to be compatible with UNFLoader, you must append the DMA@ header to the start of your data, and the CMPH signal to the end. The data itself should be aligned to the nearest 2 bytes (not after the CMPH signal like during N64 -> PC communication, to the end of the data itself). The USB library will ignore the extra byte of padding as it knows the real size of the data from the data header included after the DMA@ packet.
In order to read the USB buffer on the N64, you can check out the source code to ED64-XIO in KRIKzz's git repo, specifically, the function sysPI_rd in sys.c, and bi_reg_rd + bi_usb_rd in bios.c.