33 KiB
- Protocol
- Supported commands
- Asynchronous packets
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
identifier | description |
---|---|
CMD |
Send 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:
offset | type | description |
---|---|---|
0 |
char[3] | CMD identifier |
3 |
char[1] | Command ID |
4 |
uint32_t | First argument (arg0) |
8 |
uint32_t | Second argument (arg1) |
12 |
uint8_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
identifier | description |
---|---|
RSP |
Success response to the received command |
ERR |
Error response to the received command |
PKT |
Asynchronous data packet |
SC64 sends response packet RSP
/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 RSP
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.
RSP
/ERR
packets
General structure of packet:
offset | type | description |
---|---|---|
0 |
char[3] | RSP /ERR identifier |
3 |
char[1] | Command ID |
4 |
uint32_t | Response data length |
8 |
uint8_t[data_length] | Response data (if any) |
RSP
/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 RSP
packet.
PKT
packet
General structure of packet:
offset | type | description |
---|---|---|
0 |
char[3] | PKT identifier |
3 |
char[1] | Packet ID |
4 |
uint32_t | Packet data length |
8 |
uint8_t[data_length] | Packet data (if any) |
Available packet IDs are listed in the asynchronous packets section.
Supported commands
id | name | arg0 | arg1 | data | response | description |
---|---|---|---|---|---|---|
v |
IDENTIFIER_GET | --- | --- | --- | identifier | Get flashcart identifier SCv2 |
V |
VERSION_GET | --- | --- | --- | version | Get flashcart firmware version |
R |
STATE_RESET | --- | --- | --- | --- | Reset flashcart state (CIC params and config options) |
B |
CIC_PARAMS_SET | cic_params_0 | cic_params_1 | --- | --- | Set CIC emulation parameters (disable/seed/checksum) |
c |
CONFIG_GET | config_id | --- | --- | config_value | Get config option |
C |
CONFIG_SET | config_id | config_value | --- | --- | Set config option |
a |
SETTING_GET | setting_id | --- | --- | setting_value | Get persistent setting option |
A |
SETTING_SET | setting_id | setting_value | --- | --- | Set persistent setting option |
t |
TIME_GET | --- | --- | --- | time | Get current RTC value |
T |
TIME_SET | time_0 | time_1 | --- | --- | Set new RTC value |
m |
MEMORY_READ | address | length | --- | data | Read data from specified memory address |
M |
MEMORY_WRITE | address | length | data | --- | Write data to specified memory address |
U |
USB_WRITE | type | length | data | N/A | Send data to be received by app running on N64 (no response!) |
X |
AUX_WRITE | data | --- | --- | --- | Send small auxiliary data to be received by app running on N64 |
i |
SD_CARD_OP | address | operation | --- | result/status | Perform special operation on the SD card |
s |
SD_READ | address | sector_count | sector | result | Read sectors from the SD card to flashcart memory space |
S |
SD_WRITE | address | sector_count | sector | result | Write sectors from the flashcart memory space to the SD card |
D |
DD_SET_BLOCK_READY | error | --- | --- | --- | Notify flashcart about 64DD block readiness |
W |
WRITEBACK_ENABLE | --- | --- | --- | --- | Enable save writeback through USB packet |
p |
FLASH_WAIT_BUSY | wait | --- | --- | erase_block_size | Wait until flash ready / Get flash block erase size |
P |
FLASH_ERASE_BLOCK | address | --- | --- | --- | Start flash block erase |
f |
FIRMWARE_BACKUP | address | --- | --- | status/length | Backup firmware to specified memory address |
F |
FIRMWARE_UPDATE | address | length | --- | status | Update firmware from specified memory address |
? |
DEBUG_GET | --- | --- | --- | debug_data | Get internal FPGA debug info |
% |
DIAGNOSTIC_GET | --- | --- | --- | diagnostic_data | Get diagnostic data |
v
: IDENTIFIER_GET
Get flashcart identifier SCv2
This command does not require arguments or data.
response
(identifier)
offset | type | description |
---|---|---|
0 |
char[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)
offset | type | description |
---|---|---|
0 |
uint16_t | Major version |
2 |
uint16_t | Minor version |
4 |
uint32_t | Revision |
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)
bits | description |
---|---|
[32:25] |
Unused |
[24] |
Disable CIC |
[23:16] |
CIC seed (IPL2 and IPL3 stages) |
[15:0] |
Checksum (upper 16 bits) |
arg1
(cic_params_1)
bits | description |
---|---|
[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)
bits | description |
---|---|
[31:0] |
Config ID |
response
(config_value)
offset | type | description |
---|---|---|
0 |
uint32_t | Config 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)
bits | description |
---|---|
[31:0] |
Config ID |
arg1
(config_value)
bits | description |
---|---|
[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)
bits | description |
---|---|
[31:0] |
Setting ID |
response
(setting_value)
offset | type | description |
---|---|---|
0 |
uint32_t | Setting 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)
bits | description |
---|---|
[31:0] |
Setting ID |
arg1
(setting_value)
bits | description |
---|---|
[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)
offset | type | description |
---|---|---|
0 |
uint8_t | Weekday (1 - 7), 1 represents Monday |
1 |
uint8_t | Hours (0 - 23) |
2 |
uint8_t | Minutes (0 - 59) |
3 |
uint8_t | Seconds (0 - 59) |
4 |
uint8_t | Century (0 - 7), 0 represents year 1900 |
5 |
uint8_t | Year (0 - 99) |
6 |
uint8_t | Month (1 - 12) |
7 |
uint8_t | Day (1 - 31) |
Date/time values use the BCD format.
T
: TIME_SET
Set new RTC value
arg0
(time_0)
bits | description |
---|---|
[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)
bits | description |
---|---|
[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)
bits | description |
---|---|
[31:0] |
Starting memory address |
arg1
(length)
bits | description |
---|---|
[31:0] |
Number of bytes to read from the memory |
response
(data)
offset | type | description |
---|---|---|
0 |
uint8_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)
bits | description |
---|---|
[31:0] |
Starting memory address |
arg1
(length)
bits | description |
---|---|
[31:0] |
Number of bytes to write to the memory |
data
(data)
offset | type | description |
---|---|---|
0 |
uint8_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)
bits | description |
---|---|
[31:8] |
Unused |
[7:0] |
Datatype |
arg1
(length)
bits | description |
---|---|
[31:0] |
Data length |
data
(data)
offset | type | description |
---|---|---|
0 |
uint8_t[length] | Arbitrary data |
This command does not send response data.
This command does not send RSP
/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)
bits | description |
---|---|
[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)
bits | description |
---|---|
[31:0] |
Address |
arg1
(operation)
bits | description |
---|---|
[31:0] |
Operation |
response
(result/status)
offset | type | description |
---|---|---|
0 |
uint32_t | Operation result (valid values are listed in the sd_error_t enum) |
4 |
uint32_t | SD card status (always returned 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
operation | description |
---|---|
0 |
Init SD card |
1 |
Deinit SD card |
2 |
Get SD card status |
3 |
Get SD card info (loads CSD and CID registers to a specified address, data length is 32 bytes) |
4 |
Turn on byte swap |
5 |
Turn off byte swap |
SD card status
bits | description |
---|---|
[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)
bits | description |
---|---|
[31:0] |
Address |
arg1
(sector_count)
bits | description |
---|---|
[31:0] |
Sector count |
data
(sector)
offset | type | description |
---|---|---|
0 |
uint32_t | Starting sector |
response
(result)
offset | type | description |
---|---|---|
0 |
uint32_t | Operation 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)
bits | description |
---|---|
[31:0] |
Address |
arg1
(sector_count)
bits | description |
---|---|
[31:0] |
Sector count |
data
(sector)
offset | type | description |
---|---|---|
0 |
uint32_t | Starting sector |
response
(result)
offset | type | description |
---|---|---|
0 |
uint32_t | Operation 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)
bits | description |
---|---|
[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
id | name | data | description |
---|---|---|---|
X |
AUX_DATA | data | Data was written to the AUX register from the N64 side |
B |
BUTTON | --- | Button on the back of the SC64 was pressed |
U |
DATA | data | Data sent from the N64 |
G |
DATA_FLUSHED | --- | Data from U USB_WRITE USB command was discarded |
D |
DISK_REQUEST | disk_info/block_data | 64DD disk block R/W request |
I |
IS_VIEWER_64 | text | IS-Viewer 64 printf text |
S |
SAVE_WRITEBACK | save_contents | Flushed save data |
F |
UPDATE_STATUS | progress | Firmware 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)
offset | type | description |
---|---|---|
0 |
uint32_t | Data |
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)
offset | type | description |
---|---|---|
0 |
uint8_t | Datatype |
1 |
uint24_t | Data length |
4 |
uint8_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)
offset | type | description |
---|---|---|
0 |
uint32_t | Disk command |
4 |
uint32_t | Memory address |
8 |
uint32_t | Disk track/head/block |
12 |
uint8_t[packet_length - 12] | Data to be written to the 64DD disk block (optional) |
Fields details
Disk command:
value | description |
---|---|
1 |
Read data from 64DD disk block |
2 |
Write data to 64DD disk block |
Memory address:
Internal SC64 address where data is expected to be written for read command
Disk track/head/block:
bits | description |
---|---|
[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)
offset | type | description |
---|---|---|
0 |
uint8_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)
offset | type | description |
---|---|---|
0 |
uint32_t | Save type (same as in SAVE_TYPE config option) |
4 |
uint8_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)
offset | type | description |
---|---|---|
0 |
uint32_t | Progress |
Fields details
Progress:
value | description |
---|---|
1 |
Update process has started flashing MCU software |
2 |
Update process has started flashing FPGA firmware |
3 |
Update process has started flashing bootloader software |
0x80 |
Firmware update process was successful |
0xFF |
Error encountered during firmware update process |