03_usb_interface.md

December 24, 2024 ยท View on GitHub


Protocol

SC64 exposes itself in the system as a simple serial device. This allows it to work without manually installed drivers. Serial communication is also well supported in almost all programming languages making it easy to work with. USB protocol use simple packet based communication. Every packet starts with 3 byte identifier and 1 byte data ID. Every argument/data is sent as big-endian value.

Resetting communication

Due to serial communication nature, data transfer between PC and flashcart might get out of sync (for example when long data transfer is aborted before sending/receiving all bytes). Communication reset is done via emulated DTR/DSR pins. Start reset procedure by setting DTR pin value to high (1). Next, observe DSR pin until its state is set to high (1). At this point communication has been reset and USB interface is disabled. Now it is a good moment to clear/purge any buffers. Finish reset procedure by setting DTR pin value to low (0) and observe DSR pin until its state is set to low (0). Flashcart should be ready to accept new commands.

PC -> SC64 packets

identifierdescription
CMDSend command to the SC64

SC64 understands only one packet identifier - CMD. Fourth byte denotes command ID listed in supported commands section.

CMD packet

General structure of packet:

offsettypedescription
0char[3]CMD identifier
3char[1]Command ID
4uint32_tFirst argument (arg0)
8uint32_tSecond argument (arg1)
12uint8_t[data_length]Command data (if required)

CMD packet always require arguments to be sent even if command does not require them. Packet data length is derived from the argument if specific command supports it.

SC64 -> PC packets

identifierdescription
CMPSuccess response to the received command
ERRError response to the received command
PKTAsynchronous data packet

SC64 sends response packet CMP/ERR to almost every command received from the PC. Fourth byte is the same as in the command that triggered the response. If command execution was not successful, then CMP identifier is replaced by the ERR identifier.

SC64 can also send PKT packet at any time as a response to action triggered by the N64 or the flashcart itself. Fourth byte denotes packet ID listed in the asynchronous packets section.

CMP/ERR packets

General structure of packet:

offsettypedescription
0char[3]CMP/ERR identifier
3char[1]Command ID
4uint32_tResponse data length
8uint8_t[data_length]Response data (if any)

CMP/ERR packet is sent as a response to the command sent by the PC. ERR response might contain no (or undefined) data in the arbitrary data field compared to regular CMP packet.

PKT packet

General structure of packet:

offsettypedescription
0char[3]PKT identifier
3char[1]Packet ID
4uint32_tPacket data length
8uint8_t[data_length]Packet data (if any)

Available packet IDs are listed in the asynchronous packets section.


Supported commands

idnamearg0arg1dataresponsedescription
vIDENTIFIER_GET---------identifierGet flashcart identifier SCv2
VVERSION_GET---------versionGet flashcart firmware version
RSTATE_RESET------------Reset flashcart state (CIC params and config options)
BCIC_PARAMS_SETcic_params_0cic_params_1------Set CIC emulation parameters (disable/seed/checksum)
cCONFIG_GETconfig_id------config_valueGet config option
CCONFIG_SETconfig_idconfig_value------Set config option
aSETTING_GETsetting_id------setting_valueGet persistent setting option
ASETTING_SETsetting_idsetting_value------Set persistent setting option
tTIME_GET---------timeGet current RTC value
TTIME_SETtime_0time_1------Set new RTC value
mMEMORY_READaddresslength---dataRead data from specified memory address
MMEMORY_WRITEaddresslengthdata---Write data to specified memory address
UUSB_WRITEtypelengthdataN/ASend data to be received by app running on N64 (no response!)
XAUX_WRITEdata---------Send small auxiliary data to be received by app running on N64
iSD_CARD_OPaddressoperation---result/statusPerform special operation on the SD card
sSD_READaddresssector_countsectorresultRead sectors from the SD card to flashcart memory space
SSD_WRITEaddresssector_countsectorresultWrite sectors from the flashcart memory space to the SD card
DDD_SET_BLOCK_READYerror---------Notify flashcart about 64DD block readiness
WWRITEBACK_ENABLE------------Enable save writeback through USB packet
pFLASH_WAIT_BUSYwait------erase_block_sizeWait until flash ready / Get flash block erase size
PFLASH_ERASE_BLOCKaddress---------Start flash block erase
fFIRMWARE_BACKUPaddress------status/lengthBackup firmware to specified memory address
FFIRMWARE_UPDATEaddresslength---statusUpdate firmware from specified memory address
?DEBUG_GET---------debug_dataGet internal FPGA debug info
%DIAGNOSTIC_GET---------diagnostic_dataGet diagnostic data

v: IDENTIFIER_GET

Get flashcart identifier SCv2

This command does not require arguments or data.

response (identifier)

offsettypedescription
0char[4]Identifier

Identifier is always SCv2 represented in ASCII code.


V: VERSION_GET

Get flashcart firmware version

This command does not require arguments or data.

response (version)

offsettypedescription
0uint16_tMajor version
2uint16_tMinor version
4uint32_tRevision

Increment in major version represents breaking API changes.

Increment in minor version represents non breaking API changes.

Increment in revision field represents no API changes, usually it's denoting bugfixes.


R: STATE_RESET

Reset flashcart state (CIC params and config options)

This command does not require arguments or data.

This command does not send response data.

This command is used to reset most of the config options to default state (same as on power-up). Additionally, CIC emulation is enabled, 6102/7101 seed/checksum values are set and SD card lock is released.


B: CIC_PARAMS_SET

Set CIC emulation parameters (disable/seed/checksum)

arg0 (cic_params_0)

bitsdescription
[32:25]Unused
[24]Disable CIC
[23:16]CIC seed (IPL2 and IPL3 stages)
[15:0]Checksum (upper 16 bits)

arg1 (cic_params_1)

bitsdescription
[31:0]Checksum (lower 32 bits)

This command does not send response data.

Use this command to set custom seed/checksum CIC values. Very useful for testing custom IPL3 replacements.


c: CONFIG_GET

Get config option

arg0 (config_id)

bitsdescription
[31:0]Config ID

response (config_value)

offsettypedescription
0uint32_tConfig value

Use this command to get value of config option. Available config options are listed here.


C: CONFIG_SET

Set config option

arg0 (config_id)

bitsdescription
[31:0]Config ID

arg1 (config_value)

bitsdescription
[31:0]Config value

This command does not send response data.

Use this command to set value of config option. Available config options are listed here.


a: SETTING_GET

Get persistent setting option

arg0 (setting_id)

bitsdescription
[31:0]Setting ID

response (setting_value)

offsettypedescription
0uint32_tSetting value

Use this command to get value of persistent setting option. Available persistent setting options are listed here.


A: SETTING_SET

Set persistent setting option

arg0 (setting_id)

bitsdescription
[31:0]Setting ID

arg1 (setting_value)

bitsdescription
[31:0]Setting value

This command does not send response data.

Use this command to set value of persistent setting option. Available persistent setting options are listed here.


t: TIME_GET

Get current RTC value

This command does not require arguments or data.

response (time)

offsettypedescription
0uint8_tWeekday (1 - 7), 1 represents Monday
1uint8_tHours (0 - 23)
2uint8_tMinutes (0 - 59)
3uint8_tSeconds (0 - 59)
4uint8_tCentury (0 - 7), 0 represents year 1900
5uint8_tYear (0 - 99)
6uint8_tMonth (1 - 12)
7uint8_tDay (1 - 31)

Date/time values use the BCD format.


T: TIME_SET

Set new RTC value

arg0 (time_0)

bitsdescription
[31:24]Weekday (1 - 7), 1 represents Monday
[23:16]Hours (0 - 23)
[15:8]Minutes (0 - 59)
[7:0]Seconds (0 - 59)

arg1 (time_1)

bitsdescription
[31:24]Century (0 - 7), 0 represents year 1900
[23:16]Year (0 - 99)
[15:8]Month (1 - 12)
[7:0]Day (1 - 31)

This command does not send response data.

Date/time values use the BCD format.


m: MEMORY_READ

Read data from specified memory address

arg0 (address)

bitsdescription
[31:0]Starting memory address

arg1 (length)

bitsdescription
[31:0]Number of bytes to read from the memory

response (data)

offsettypedescription
0uint8_t[length]Memory contents

Reads bytes from the specified memory address. Please refer to the internal memory map for available memory ranges.


M: MEMORY_WRITE

Write data to specified memory address

arg0 (address)

bitsdescription
[31:0]Starting memory address

arg1 (length)

bitsdescription
[31:0]Number of bytes to write to the memory

data (data)

offsettypedescription
0uint8_t[length]Data to write to the memory

This command does not send response data.

Writes bytes to the specified memory address. Please refer to the internal memory map for available memory ranges.


U: USB_WRITE

Send data to be received by app running on N64 (no response!)

arg0 (type)

bitsdescription
[31:8]Unused
[7:0]Datatype

arg1 (length)

bitsdescription
[31:0]Data length

data (data)

offsettypedescription
0uint8_t[length]Arbitrary data

This command does not send response data.

This command does not send CMP/ERR packet response!

This command notifies N64 that data is waiting to be acknowledged. If N64 side doesn't acknowledge data via m USB_READ N64 command within 1 second then data is flushed and G DATA_FLUSHED asynchronous packet is sent to the PC. If N64 acknowledge the request, then data is written to the flashcart memory to address specified in m USB_READ N64 command.


X: AUX_WRITE

Send small auxiliary data to be received by app running on N64

arg0 (data)

bitsdescription
[31:0]Data

This command does not send response data.

This command puts 32 bits of data to the AUX register accessible from the N64 side, and generates cart interrupt (if enabled).


i: SD_CARD_OP

Perform special operation on the SD card

arg0 (address)

bitsdescription
[31:0]Address

arg1 (operation)

bitsdescription
[31:0]Operation

response (result/status)

offsettypedescription
0uint32_tOperation result (valid values are listed in the sd_error_t enum)
4uint32_tSD card status (always returned and valid regardless of the SD card operation result)

This command performs special operation on the SD card. When operation result is not SD_OK, then ERR packet is returned. PC and N64 cannot use the SD card interface at the same time. Lock mechanism is implemented to prevent data corruption. SD card access is locked when PC or N64 requests SD card initialization, and unlocked when the card is uninitialized. Lock is also released when certain conditions occur - when N64 side lock is active then it is released when the console is powered off and save writeback operation is not pending. PC side lock is released when USB interface is in reset state, or the USB cable is unplugged.

Available SD card operations

operationdescription
0Init SD card
1Deinit SD card
2Get SD card status
3Get SD card info (loads CSD and CID registers to a specified address, data length is 32 bytes)
4Turn on byte swap
5Turn off byte swap

SD card status

bitsdescription
[31:5]Unused
[4]0 - Byte swap disabled, 1 - Byte swap enabled (valid when initialized)
[3]0 - 25 MHz clock, 1 - 50 MHz clock (valid when initialized)
[2]0 - Byte addressed, 1 - Sector addressed (valid when initialized)
[1]0 - SD card not initialized, 1 - SD card initialized
[0]0 - SD card not inserted, 1 - SD card inserted

s: SD_READ

Read sectors from the SD card to flashcart memory space

arg0 (address)

bitsdescription
[31:0]Address

arg1 (sector_count)

bitsdescription
[31:0]Sector count

data (sector)

offsettypedescription
0uint32_tStarting sector

response (result)

offsettypedescription
0uint32_tOperation result (valid values are listed in the sd_error_t enum)

This command reads sectors from the SD card to a specified memory address. When operation result is not SD_OK, then ERR packet is returned.


S: SD_WRITE

Write sectors from the flashcart memory space to the SD card

arg0 (address)

bitsdescription
[31:0]Address

arg1 (sector_count)

bitsdescription
[31:0]Sector count

data (sector)

offsettypedescription
0uint32_tStarting sector

response (result)

offsettypedescription
0uint32_tOperation result (valid values are listed in the sd_error_t enum)

This command writes sectors from a specified memory address to the SD card. When operation result is not SD_OK, then ERR packet is returned.


D: DD_SET_BLOCK_READY

Notify flashcart about 64DD block readiness

arg0 (error)

bitsdescription
[31:1]Unused
[0]0 - Success, 1 - Error

This command does not send response data.

This command informs SC64 that 64DD disk block data was successfully (or not) read to the requested buffer or written to the 64DD disk file. This command must be sent for each incoming DISK_REQUEST asynchronous packet.


W: WRITEBACK_ENABLE

Enable save writeback through USB packet

This command does not require arguments or data.

This command does not send response data.

This command is used to enable save writeback module and set its mode to send data to the USB interface instead of writing to the SD card. To disable save writeback change save type via SAVE_TYPE config option (setting the same save type as currently enabled will also disable writeback module). Save data is sent via SAVE_WRITEBACK asynchronous packet.


Asynchronous packets

idnamedatadescription
XAUX_DATAdataData was written to the AUX register from the N64 side
BBUTTON---Button on the back of the SC64 was pressed
UDATAdataData sent from the N64
GDATA_FLUSHED---Data from U USB_WRITE USB command was discarded
DDISK_REQUESTdisk_info/block_data64DD disk block R/W request
IIS_VIEWER_64textIS-Viewer 64 printf text
SSAVE_WRITEBACKsave_contentsFlushed save data
FUPDATE_STATUSprogressFirmware update progress

X: AUX_DATA

Data was written to the AUX register from the N64 side

This packet is sent when N64 writes to the AUX register in the SC64 register block.

data (data)

offsettypedescription
0uint32_tData

B: BUTTON

Button on the back of the SC64 was pressed

This packet is sent only when BUTTON_MODE config option is set to value "2 - Button press sends USB packet".

This packet does not send additional data.


U: DATA

Data sent from the N64

This packet is sent when N64 command USB_WRITE is executed.

data (data)

offsettypedescription
0uint8_tDatatype
1uint24_tData length
4uint8_t[data_length]Packet data

G: DATA_FLUSHED

Data from U USB_WRITE USB command was discarded

This packet is sent only when data sent with USB command U USB_WRITE was not acknowledged by the N64 side with m USB_READ within 1 second time limit.

This packet does not send additional data.


D: DISK_REQUEST

64DD disk block R/W request

This packet is sent when 64DD mode is set to pass R/W requests to the USB interface with DD_SD_ENABLE config option. Every disk request packet must be acknowledged by the PC side with D DD_SET_BLOCK_READY USB command.

data (disk_info/block_data)

offsettypedescription
0uint32_tDisk command
4uint32_tMemory address
8uint32_tDisk track/head/block
12uint8_t[packet_length - 12]Data to be written to the 64DD disk block (optional)

Fields details

Disk command:

valuedescription
1Read data from 64DD disk block
2Write data to 64DD disk block

Memory address:

Internal SC64 address where data is expected to be written for read command

Disk track/head/block:

bitsdescription
[31:13]Unused
[12:2]Track
[1]Head
[0]Block

I: IS_VIEWER_64

IS-Viewer 64 printf text

This packet is sent when IS-Viewer 64 module is enabled in the SC64 with ISV_ADDRESS config option, and data is written to the IS-Viewer 64 buffer.

data (text)

offsettypedescription
0uint8_t[packet_length]Text

S: SAVE_WRITEBACK

Flushed save data

This packet is sent when save writeback module is enabled and set to send data to the USB interface with W WRITEBACK_ENABLE USB command. Save data is flushed after 1 second delay from the last write to the save region by the app/game running on the N64.

data (save_contents)

offsettypedescription
0uint32_tSave type (same as in SAVE_TYPE config option)
4uint8_t[packet_length - 4]Save data

F: UPDATE_STATUS

Firmware update progress

This packet is sent during firmware update process to indicate progress and errors.

data (progress)

offsettypedescription
0uint32_tProgress

Fields details

Progress:

valuedescription
1Update process has started flashing MCU software
2Update process has started flashing FPGA firmware
3Update process has started flashing bootloader software
0x80Firmware update process was successful
0xFFError encountered during firmware update process