- Note [1]: Flash memory region `0x04E0_0000` - `0x04FD_FFFF` is write protected as it contains N64 bootloader. This section can be overwritten only via firmware update process.
- Note [2]: Due to BlockRAM usage optimization this section is read only.
- Note [4]: FlashRAM read access is multiplexed between mem and reg bus, writes are always mapped to reg bus.
- Note [5]: Write access is available when `ROM_WRITE_ENABLE` config is enabled.
- Note [6]: This address overlaps last 128 kiB of ROM space allowing SRAM and FlashRAM save types to work with games occupying almost all of ROM space (for example Pokemon Stadium 2). Reads are redirected to last 128 kiB of flash.
- Note [7]: Always accessible regardless of ROM shadow switch.
- Note [8]: Used internally and exposed only for debugging.
### Address decoding limitations
Current implementation of PI interface checks only upper 16 bits of address. Bus and device are chosen only from value of starting address.
In specific situations this could lead to unexpected behavior when performing R/W operations crossing 64 kiB boundaries.
Page size (as called by N64 docs) is configurable by `PI_BSD_DOMn_PGS` register. Maximum page size can be set up to 128 kiB blocks.
PI controller inside N64 will automatically reissue address at set boundary when performing R/W operation that crosses it.
For example, setting largest page size then doing 128 kiB read starting from address `0x1FFE_0000` will select *mem bus* and start fetching data from mapped internal address `0x0500_0000`.
SC64 registers are available at base address `0x1FFF_0000` (`0x1FFE_0000` + 64 kiB), but are connected to *reg bus*.
As a consequence of this design data read by N64 in single transaction will not contain values of SC64 registers at 64 kiB offset.
Note: All interrupts are cleared and disabled when any of the following events occur:
- Hard reset
- NMI reset
- SC64 registers lock
SC64 interrupts are completely disabled when register access is not enabled.
---
### `0x1FFF_0018`: **AUX**
This register can be used as a very simple interface to the PC via USB.
Writing to this register generates an USB transfer with the contents of the written data.
New data available in the register are signaled via cart interrupt that needs to be enabled beforehand by setting `AUX_IRQ_ENABLE` bit in the **IRQ** register.
Status can be also manually polled by checking `AUX_IRQ_PENDING` bit in **SCR** register.
Interrupt needs to be acknowledged by setting `AUX_CLEAR` bit in the **IRQ** register.
There is no flow control, use this register as a ping-pong interface.
For example, PC sends AUX data, N64 receives interrupt, reads the data then writes to this register with a response.
This flow can be reversed if needed - N64 can be the initiating side.
| name | bits | access | meaning |
| ------ | ------ | ------ | -------------- |
| `DATA` | [31:0] | RW | Arbitrary data |
This register is used by the upload process in the `sc64deployer` to notify running app on the N64 about certain events.
All `DATA` values with upper 8 bits set to `1` (`0xFFxxxxxx`) are reserved for internal use by the SC64.
Refrain from using these values in your app for uses other than listed below.
Currently defined reserved `DATA` values are:
-`0xFF000000` - **Ping** - no-op command to test if app running on the N64 is listening to the AUX events.
-`0xFF000001` - **Halt** - causes the running app to stop all activity and wait in preparation for uploading new ROM to the SC64.
App still should listen to the AUX interrupt and respond to other messages.
-`0xFF000002` - **Reboot** - causes the running app to perform soft reboot by reloading IPL3 from the ROM and start executing it.
App running on the N64 shall respond to the AUX message with the same `DATA` value as incoming event for all events listed above, unless it's specified otherwise.
# Command execution flow
### Without interrupt
1. Check if command is already executing by reading `CMD_BUSY` bit in **SCR** register (optional).
2. Write command argument values to **DATA0** and **DATA1** registers, can be skipped if command doesn't require it.
3. Write command ID to **SCR** register.
4. Wait for `CMD_BUSY` bit in **SCR** register to go low.
5. Check if `CMD_ERROR` bit in **SCR** is set:
- If error is set then read **DATA0** register containing error code.
- If error is not set then read **DATA0** and **DATA1** registers containing command result values, can be skipped if command doesn't return any values.
- If error is set then read **DATA0** register containing error code.
- If error is not set then read **DATA0** and **DATA1** registers containing command result values, can be skipped if command doesn't return any values.