mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-21 21:49:15 +01:00
[SC64][SW] Changed firmware version reporting
This commit is contained in:
parent
56cdd3a709
commit
409ba28359
@ -5,7 +5,7 @@
|
||||
- [SC64 registers](#sc64-registers)
|
||||
- [`0x1FFF_0000`: **STATUS/COMMAND**](#0x1fff_0000-statuscommand)
|
||||
- [`0x1FFF_0004`: **DATA0** and `0x1FFF_0008`: **DATA1**](#0x1fff_0004-data0-and-0x1fff_0008-data1)
|
||||
- [`0x1FFF_000C`: **VERSION**](#0x1fff_000c-version)
|
||||
- [`0x1FFF_000C`: **IDENTIFIER**](#0x1fff_000c-identifier)
|
||||
- [`0x1FFF_0010`: **KEY**](#0x1fff_0010-key)
|
||||
- [Command execution flow](#command-execution-flow)
|
||||
|
||||
@ -87,13 +87,13 @@ SC64 contains small register region used for communication between N64 and contr
|
||||
Protocol is command based with support for up to 256 diferrent commands and two 32-bit argument/result values per operation.
|
||||
Support for interrupts is provided but currently no command relies on it, 64DD IRQ is handled separately.
|
||||
|
||||
| name | address | size | access | usage |
|
||||
| ------------------ | ------------- | ------- | ------ | -------------------------------- |
|
||||
| **STATUS/COMMAND** | `0x1FFF_0000` | 4 bytes | RW | Command execution and status |
|
||||
| **DATA0** | `0x1FFF_0004` | 4 bytes | RW | Command argument/result 0 |
|
||||
| **DATA1** | `0x1FFF_0008` | 4 bytes | RW | Command argument/result 1 |
|
||||
| **VERSION** | `0x1FFF_000C` | 4 bytes | RW | Hardware version and IRQ clear |
|
||||
| **KEY** | `0x1FFF_0010` | 4 bytes | W | SC64 register access lock/unlock |
|
||||
| name | address | size | access | usage |
|
||||
| ------------------ | ------------- | ------- | ------ | ---------------------------------- |
|
||||
| **STATUS/COMMAND** | `0x1FFF_0000` | 4 bytes | RW | Command execution and status |
|
||||
| **DATA0** | `0x1FFF_0004` | 4 bytes | RW | Command argument/result 0 |
|
||||
| **DATA1** | `0x1FFF_0008` | 4 bytes | RW | Command argument/result 1 |
|
||||
| **IDENTIFIER** | `0x1FFF_000C` | 4 bytes | RW | Flashcart identifier and IRQ clear |
|
||||
| **KEY** | `0x1FFF_0010` | 4 bytes | W | SC64 register access lock/unlock |
|
||||
|
||||
---
|
||||
|
||||
@ -121,11 +121,11 @@ Note: Result is valid only when command has executed and `CMD_BUSY` bit is reset
|
||||
|
||||
---
|
||||
|
||||
#### `0x1FFF_000C`: **VERSION**
|
||||
#### `0x1FFF_000C`: **IDENTIFIER**
|
||||
|
||||
| name | bits | access | meaning |
|
||||
| --------- | ------ | ------ | --------------------------------------------- |
|
||||
| `VERSION` | [31:0] | RW | Hardware version (ASCII `SCv2`) and IRQ clear |
|
||||
| name | bits | access | meaning |
|
||||
| ------------ | ------ | ------ | ------------------------------------------------- |
|
||||
| `IDENTIFIER` | [31:0] | RW | Flashcart identifier (ASCII `SCv2`) and IRQ clear |
|
||||
|
||||
Note: Writing any value to this register will clear pending flashcart interrupt.
|
||||
|
||||
|
@ -4,25 +4,25 @@
|
||||
|
||||
## USB commands
|
||||
|
||||
| id | name | arg0 | arg1 | data | response | description |
|
||||
| --- | ---------------------- | ------------ | ------------ | ---- | ---------------- | --------------------------------------------------- |
|
||||
| `v` | **HW_VERSION_GET** | --- | --- | --- | hw_version | Get HW version |
|
||||
| `V` | **API_VERSION_GET** | --- | --- | --- | api_version | Get USB command API version |
|
||||
| `R` | **STATE_RESET** | --- | --- | --- | --- | Reset entire flashcart state |
|
||||
| `B` | **CIC_PARAMS_SET** | cic_params_0 | cic_params_1 | --- | --- | Set CIC disable/mode/seed/checksum |
|
||||
| `c` | **CONFIG_GET** | config_id | --- | --- | current_value | Get config option |
|
||||
| `C` | **CONFIG_SET** | config_id | new_value | --- | --- | Set config option |
|
||||
| `a` | **SETTING_GET** | setting_id | --- | --- | current_value | Get persistent setting |
|
||||
| `A` | **SETTING_SET** | setting_id | new_value | --- | --- | Set persistent setting |
|
||||
| `t` | **TIME_GET** | --- | --- | --- | time | Get current RTC value |
|
||||
| `T` | **TIME_SET** | time_0 | time_1 | --- | --- | Set 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 |
|
||||
| `D` | **DD_SET_BLOCK_READY** | success | --- | --- | --- | Notify flashcart about 64DD block readiness |
|
||||
| `U` | **USB_WRITE** | type | length | data | N/A | Send data to be received by app running on N64 |
|
||||
| `f` | **FIRMWARE_BACKUP** | address | --- | --- | status/length | Backup firmware to specified memory address |
|
||||
| `F` | **FIRMWARE_UPDATE** | address | length | --- | status | Update firmware from specified memory address |
|
||||
| `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 |
|
||||
| `?` | **DEBUG_GET** | --- | --- | --- | debug_data | Get internal FPGA debug info |
|
||||
| `%` | **STACK_USAGE_GET** | --- | --- | --- | stack_usage | Get per task stack usage |
|
||||
| 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 | --- | --- | current_value | Get config option |
|
||||
| `C` | **CONFIG_SET** | config_id | new_value | --- | --- | Set config option |
|
||||
| `a` | **SETTING_GET** | setting_id | --- | --- | current_value | Get persistent setting option |
|
||||
| `A` | **SETTING_SET** | setting_id | new_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!) |
|
||||
| `D` | **DD_SET_BLOCK_READY** | success | --- | --- | --- | Notify flashcart about 64DD block readiness |
|
||||
| `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 |
|
||||
| `%` | **STACK_USAGE_GET** | --- | --- | --- | stack_usage | Get per task stack usage |
|
||||
|
@ -6,14 +6,14 @@
|
||||
|
||||
| id | name | arg0 | arg1 | rsp0 | rsp1 | description |
|
||||
| --- | --------------------- | ---------- | ------------ | ---------------- | -------------- | -------------------------------------------------- |
|
||||
| `v` | **HW_VERSION_GET** | --- | --- | hw_version | --- | Get HW version |
|
||||
| `V` | **API_VERSION_GET** | --- | --- | api_version | --- | Get N64 command API version |
|
||||
| `v` | **IDENTIFIER_GET** | --- | --- | identifier | --- | Get flashcart identifier `SCv2` |
|
||||
| `V` | **VERSION_GET** | --- | --- | version | --- | Get flashcart firmware version |
|
||||
| `c` | **CONFIG_GET** | config_id | --- | --- | current_value | Get config option |
|
||||
| `C` | **CONFIG_SET** | config_id | new_value | --- | previous_value | Set config option and get previous value |
|
||||
| `c` | **SETTING_GET** | setting_id | --- | --- | current_value | Get persistent setting option |
|
||||
| `C` | **SETTING_SET** | setting_id | new_value | --- | --- | Set persistent setting option |
|
||||
| `t` | **TIME_GET** | --- | --- | time_0 | time_1 | Get current RTC value |
|
||||
| `T` | **TIME_SET** | time_0 | time_1 | --- | --- | Set RTC value |
|
||||
| `T` | **TIME_SET** | time_0 | time_1 | --- | --- | Set new RTC value |
|
||||
| `m` | **USB_READ** | pi_address | length | --- | --- | Receive data from USB to flashcart |
|
||||
| `M` | **USB_WRITE** | pi_address | length/type | --- | --- | Send data from from flashcart to USB |
|
||||
| `u` | **USB_READ_STATUS** | --- | --- | read_status/type | length | Get USB read status and type/length |
|
||||
@ -27,4 +27,3 @@
|
||||
| `K` | **FLASH_PROGRAM** | pi_address | length | --- | --- | Program flash with bytes loaded into data buffer |
|
||||
| `p` | **FLASH_WAIT_BUSY** | wait | --- | erase_block_size | --- | Wait until flash ready / get block erase size |
|
||||
| `P` | **FLASH_ERASE_BLOCK** | pi_address | --- | --- | --- | Start flash block erase |
|
||||
| `?` | **DEBUG_GET** | --- | --- | debug_data_0 | debug_data_1 | Get internal FPGA debug info |
|
||||
|
@ -332,7 +332,7 @@ module mcu_top (
|
||||
REG_CFG_DATA_0,
|
||||
REG_CFG_DATA_1,
|
||||
REG_CFG_CMD,
|
||||
REG_CFG_VERSION,
|
||||
REG_CFG_IDENTIFIER,
|
||||
REG_FLASHRAM_SCR,
|
||||
REG_FLASH_SCR,
|
||||
REG_RTC_SCR,
|
||||
@ -363,7 +363,7 @@ module mcu_top (
|
||||
|
||||
logic bootloader_skip;
|
||||
|
||||
assign n64_scb.cfg_version = 32'h53437632;
|
||||
assign n64_scb.cfg_identifier = 32'h53437632;
|
||||
|
||||
logic dd_bm_ack;
|
||||
|
||||
@ -460,8 +460,8 @@ module mcu_top (
|
||||
};
|
||||
end
|
||||
|
||||
REG_CFG_VERSION: begin
|
||||
reg_rdata <= n64_scb.cfg_version;
|
||||
REG_CFG_IDENTIFIER: begin
|
||||
reg_rdata <= n64_scb.cfg_identifier;
|
||||
end
|
||||
|
||||
REG_FLASHRAM_SCR: begin
|
||||
|
@ -16,8 +16,8 @@ module n64_cfg (
|
||||
REG_DATA_0_L,
|
||||
REG_DATA_1_H,
|
||||
REG_DATA_1_L,
|
||||
REG_VERSION_H,
|
||||
REG_VERSION_L,
|
||||
REG_IDENTIFIER_H,
|
||||
REG_IDENTIFIER_L,
|
||||
REG_KEY_H,
|
||||
REG_KEY_L
|
||||
} e_reg;
|
||||
@ -39,8 +39,8 @@ module n64_cfg (
|
||||
REG_DATA_0_L: reg_bus.rdata = n64_scb.cfg_wdata[0][15:0];
|
||||
REG_DATA_1_H: reg_bus.rdata = n64_scb.cfg_wdata[1][31:16];
|
||||
REG_DATA_1_L: reg_bus.rdata = n64_scb.cfg_wdata[1][15:0];
|
||||
REG_VERSION_H: reg_bus.rdata = n64_scb.cfg_version[31:16];
|
||||
REG_VERSION_L: reg_bus.rdata = n64_scb.cfg_version[15:0];
|
||||
REG_IDENTIFIER_H: reg_bus.rdata = n64_scb.cfg_identifier[31:16];
|
||||
REG_IDENTIFIER_L: reg_bus.rdata = n64_scb.cfg_identifier[15:0];
|
||||
REG_KEY_H: reg_bus.rdata = 16'd0;
|
||||
REG_KEY_L: reg_bus.rdata = 16'd0;
|
||||
endcase
|
||||
@ -83,7 +83,7 @@ module n64_cfg (
|
||||
REG_DATA_0_L: n64_scb.cfg_rdata[0][15:0] <= reg_bus.wdata;
|
||||
REG_DATA_1_H: n64_scb.cfg_rdata[1][31:16] <= reg_bus.wdata;
|
||||
REG_DATA_1_L: n64_scb.cfg_rdata[1][15:0] <= reg_bus.wdata;
|
||||
REG_VERSION_H: irq <= 1'b0;
|
||||
REG_IDENTIFIER_H: irq <= 1'b0;
|
||||
REG_KEY_H, REG_KEY_L: begin
|
||||
lock_sequence_counter <= lock_sequence_counter + 1'd1;
|
||||
if (reg_bus.wdata != 16'hFFFF) begin
|
||||
|
@ -51,7 +51,7 @@ interface n64_scb ();
|
||||
logic [7:0] cfg_cmd;
|
||||
logic [31:0] cfg_rdata [0:1];
|
||||
logic [31:0] cfg_wdata [0:1];
|
||||
logic [31:0] cfg_version;
|
||||
logic [31:0] cfg_identifier;
|
||||
|
||||
logic [15:0] save_count;
|
||||
|
||||
@ -94,7 +94,7 @@ interface n64_scb ();
|
||||
input cfg_cmd,
|
||||
input cfg_rdata,
|
||||
output cfg_wdata,
|
||||
output cfg_version,
|
||||
output cfg_identifier,
|
||||
|
||||
input save_count,
|
||||
|
||||
@ -194,7 +194,7 @@ interface n64_scb ();
|
||||
output cfg_cmd,
|
||||
output cfg_rdata,
|
||||
input cfg_wdata,
|
||||
input cfg_version
|
||||
input cfg_identifier
|
||||
);
|
||||
|
||||
modport save_counter (
|
||||
|
@ -5,7 +5,7 @@
|
||||
typedef struct {
|
||||
io32_t SR_CMD;
|
||||
io32_t DATA[2];
|
||||
io32_t VERSION;
|
||||
io32_t IDENTIFIER;
|
||||
io32_t KEY;
|
||||
} sc64_regs_t;
|
||||
|
||||
@ -16,7 +16,7 @@ typedef struct {
|
||||
#define SC64_SR_CMD_ERROR (1 << 30)
|
||||
#define SC64_SR_CPU_BUSY (1 << 31)
|
||||
|
||||
#define SC64_VERSION_2 (0x53437632)
|
||||
#define SC64_V2_IDENTIFIER (0x53437632)
|
||||
|
||||
#define SC64_KEY_RESET (0x00000000UL)
|
||||
#define SC64_KEY_UNLOCK_1 (0x5F554E4CUL)
|
||||
@ -24,8 +24,8 @@ typedef struct {
|
||||
#define SC64_KEY_LOCK (0xFFFFFFFFUL)
|
||||
|
||||
typedef enum {
|
||||
SC64_CMD_HW_VERSION_GET = 'v',
|
||||
SC64_CMD_API_VERSION_GET = 'V',
|
||||
SC64_CMD_IDENTIFIER_GET = 'v',
|
||||
SC64_CMD_VERSION_GET = 'V',
|
||||
SC64_CMD_CONFIG_GET = 'c',
|
||||
SC64_CMD_CONFIG_SET = 'C',
|
||||
SC64_CMD_SETTING_GET = 'a',
|
||||
@ -45,7 +45,6 @@ typedef enum {
|
||||
SC64_CMD_FLASH_PROGRAM = 'K',
|
||||
SC64_CMD_FLASH_WAIT_BUSY = 'p',
|
||||
SC64_CMD_FLASH_ERASE_BLOCK = 'P',
|
||||
SC64_CMD_DEBUG_GET = '?',
|
||||
} cmd_id_t;
|
||||
|
||||
typedef enum {
|
||||
@ -98,8 +97,8 @@ void sc64_lock (void) {
|
||||
}
|
||||
|
||||
bool sc64_check_presence (void) {
|
||||
uint32_t version = pi_io_read(&SC64_REGS->VERSION);
|
||||
if (version == SC64_VERSION_2) {
|
||||
uint32_t identifier = pi_io_read(&SC64_REGS->IDENTIFIER);
|
||||
if (identifier == SC64_V2_IDENTIFIER) {
|
||||
sc64_wait_cpu_busy();
|
||||
return true;
|
||||
}
|
||||
@ -114,7 +113,7 @@ bool sc64_irq_pending (void) {
|
||||
}
|
||||
|
||||
void sc64_irq_clear (void) {
|
||||
pi_io_write(&SC64_REGS->VERSION, 0);
|
||||
pi_io_write(&SC64_REGS->IDENTIFIER, 0);
|
||||
}
|
||||
|
||||
uint32_t sc64_get_config (sc64_cfg_id_t id) {
|
||||
|
@ -221,8 +221,8 @@ static bool cfg_set_save_type (save_type_t save_type) {
|
||||
}
|
||||
|
||||
|
||||
uint32_t cfg_get_version (void) {
|
||||
return fpga_reg_get(REG_CFG_VERSION);
|
||||
uint32_t cfg_get_identifier (void) {
|
||||
return fpga_reg_get(REG_CFG_IDENTIFIER);
|
||||
}
|
||||
|
||||
bool cfg_query (uint32_t *args) {
|
||||
@ -468,11 +468,11 @@ void cfg_process (void) {
|
||||
|
||||
switch (cmd) {
|
||||
case 'v':
|
||||
args[0] = cfg_get_version();
|
||||
args[0] = cfg_get_identifier();
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
args[0] = version_api(API_N64);
|
||||
args[0] = version_firmware();
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
@ -666,11 +666,6 @@ void cfg_process (void) {
|
||||
}
|
||||
break;
|
||||
|
||||
case '?':
|
||||
args[0] = fpga_reg_get(REG_DEBUG_0);
|
||||
args[1] = fpga_reg_get(REG_DEBUG_1);
|
||||
break;
|
||||
|
||||
default:
|
||||
cfg_set_error(CFG_ERROR_UNKNOWN_CMD);
|
||||
return;
|
||||
|
@ -16,7 +16,7 @@ typedef enum {
|
||||
} save_type_t;
|
||||
|
||||
|
||||
uint32_t cfg_get_version (void);
|
||||
uint32_t cfg_get_identifier (void);
|
||||
bool cfg_query (uint32_t *args);
|
||||
bool cfg_update (uint32_t *args);
|
||||
bool cfg_query_setting (uint32_t *args);
|
||||
|
@ -28,7 +28,7 @@ typedef enum {
|
||||
REG_CFG_DATA_0,
|
||||
REG_CFG_DATA_1,
|
||||
REG_CFG_CMD,
|
||||
REG_CFG_VERSION,
|
||||
REG_CFG_IDENTIFIER,
|
||||
REG_FLASHRAM_SCR,
|
||||
REG_FLASH_SCR,
|
||||
REG_RTC_SCR,
|
||||
|
@ -160,14 +160,14 @@ static void usb_rx_process (void) {
|
||||
p.rx_state = RX_STATE_IDLE;
|
||||
p.response_pending = true;
|
||||
p.response_info.data_length = 4;
|
||||
p.response_info.data[0] = cfg_get_version();
|
||||
p.response_info.data[0] = cfg_get_identifier();
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
p.rx_state = RX_STATE_IDLE;
|
||||
p.response_pending = true;
|
||||
p.response_info.data_length = 4;
|
||||
p.response_info.data[0] = version_api(API_USB);
|
||||
p.response_info.data[0] = version_firmware();
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
@ -247,12 +247,6 @@ static void usb_rx_process (void) {
|
||||
}
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
dd_set_block_ready(p.rx_args[0] == 0);
|
||||
p.rx_state = RX_STATE_IDLE;
|
||||
p.response_pending = true;
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
if ((p.read_length > 0) && usb_dma_ready()) {
|
||||
uint32_t length = (p.read_length > p.rx_args[1]) ? p.rx_args[1] : p.read_length;
|
||||
@ -274,6 +268,28 @@ static void usb_rx_process (void) {
|
||||
}
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
dd_set_block_ready(p.rx_args[0] == 0);
|
||||
p.rx_state = RX_STATE_IDLE;
|
||||
p.response_pending = true;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (p.rx_args[0]) {
|
||||
flash_wait_busy();
|
||||
}
|
||||
p.rx_state = RX_STATE_IDLE;
|
||||
p.response_pending = true;
|
||||
p.response_info.data_length = 4;
|
||||
p.response_info.data[0] = FLASH_ERASE_BLOCK_SIZE;
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
p.response_error = flash_erase_block(p.rx_args[0]);
|
||||
p.rx_state = RX_STATE_IDLE;
|
||||
p.response_pending = true;
|
||||
break;
|
||||
|
||||
case 'f': {
|
||||
bool rom_write_enable_restore = cfg_set_rom_write_enable(false);
|
||||
p.response_info.data[0] = update_backup(p.rx_args[0], &p.response_info.data[1]);
|
||||
@ -300,22 +316,6 @@ static void usb_rx_process (void) {
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p':
|
||||
if (p.rx_args[0]) {
|
||||
flash_wait_busy();
|
||||
}
|
||||
p.rx_state = RX_STATE_IDLE;
|
||||
p.response_pending = true;
|
||||
p.response_info.data_length = 4;
|
||||
p.response_info.data[0] = FLASH_ERASE_BLOCK_SIZE;
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
p.response_error = flash_erase_block(p.rx_args[0]);
|
||||
p.rx_state = RX_STATE_IDLE;
|
||||
p.response_pending = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
p.rx_state = RX_STATE_IDLE;
|
||||
p.response_pending = true;
|
||||
|
@ -1,17 +1,10 @@
|
||||
#include "version.h"
|
||||
|
||||
|
||||
#define VERSION_API_USB (2)
|
||||
#define VERSION_API_N64 (2)
|
||||
#define VERSION_MAJOR (2)
|
||||
#define VERSION_MINOR (12)
|
||||
|
||||
|
||||
uint32_t version_api (version_api_type_t type) {
|
||||
switch (type) {
|
||||
case API_USB:
|
||||
return VERSION_API_USB;
|
||||
case API_N64:
|
||||
return VERSION_API_N64;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
uint32_t version_firmware (void) {
|
||||
return ((VERSION_MAJOR << 16) | (VERSION_MINOR));
|
||||
}
|
||||
|
@ -5,13 +5,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
typedef enum {
|
||||
API_USB,
|
||||
API_N64,
|
||||
} version_api_type_t;
|
||||
|
||||
|
||||
uint32_t version_api (version_api_type_t type);
|
||||
uint32_t version_firmware (void);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -200,6 +200,7 @@ class SC64:
|
||||
FLASH = 0x0400_0000
|
||||
BUFFER = 0x0500_0000
|
||||
EEPROM = 0x0500_2000
|
||||
END = 0x0500_297F
|
||||
FIRMWARE = 0x0200_0000
|
||||
DDIPL = 0x03BC_0000
|
||||
SAVE = 0x03FE_0000
|
||||
@ -321,7 +322,8 @@ class SC64:
|
||||
SCREENSHOT = 4
|
||||
GDB = 0xDB
|
||||
|
||||
__MIN_SUPPORTED_API_VERSION = 2
|
||||
__SUPPORTED_MAJOR_VERSION = 2
|
||||
__SUPPORTED_MINOR_VERSION = 12
|
||||
|
||||
__isv_line_buffer: bytes = b''
|
||||
__debug_header: Optional[bytes] = None
|
||||
@ -329,21 +331,24 @@ class SC64:
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.__link = SC64Serial()
|
||||
version = self.__link.execute_cmd(cmd=b'v')
|
||||
if (version != b'SCv2'):
|
||||
raise ConnectionException('Unknown SC64 HW version')
|
||||
identifier = self.__link.execute_cmd(cmd=b'v')
|
||||
if (identifier != b'SCv2'):
|
||||
raise ConnectionException('Unknown SC64 v2 identifier')
|
||||
|
||||
def __get_int(self, data: bytes) -> int:
|
||||
return int.from_bytes(data[:4], byteorder='big')
|
||||
|
||||
def check_api_version(self) -> None:
|
||||
def check_firmware_version(self) -> None:
|
||||
try:
|
||||
data = self.__link.execute_cmd(cmd=b'V')
|
||||
version = self.__link.execute_cmd(cmd=b'V')
|
||||
major = self.__get_int(version[0:2])
|
||||
minor = self.__get_int(version[2:4])
|
||||
if (major != self.__SUPPORTED_MAJOR_VERSION):
|
||||
raise ConnectionException()
|
||||
if (minor < self.__SUPPORTED_MINOR_VERSION):
|
||||
raise ConnectionException()
|
||||
except ConnectionException:
|
||||
raise ConnectionException('Outdated SC64 API, please update firmware')
|
||||
version = self.__get_int(data)
|
||||
if (version < self.__MIN_SUPPORTED_API_VERSION):
|
||||
raise ConnectionException('Unsupported SC64 API version, please update firmware')
|
||||
raise ConnectionException(f'Unsupported SC64 version ({major}.{minor}), please update firmware')
|
||||
|
||||
def __set_config(self, config: __CfgId, value: int) -> None:
|
||||
try:
|
||||
@ -461,8 +466,10 @@ class SC64:
|
||||
raise ValueError('Debug data size too big')
|
||||
self.__link.execute_cmd(cmd=b'U', args=[datatype, len(data)], data=data, response=False)
|
||||
|
||||
def download_memory(self) -> bytes:
|
||||
return self.__read_memory(self.__Address.MEMORY, self.__Length.MEMORY)
|
||||
def download_memory(self, address: int, length: int) -> bytes:
|
||||
if ((address < 0) or (length < 0) or ((address + length) > self.__Address.END)):
|
||||
raise ValueError('Invalid address or length')
|
||||
return self.__read_memory(address, length)
|
||||
|
||||
def upload_rom(self, data: bytes, use_shadow: bool=True) -> None:
|
||||
rom_length = len(data)
|
||||
@ -582,7 +589,7 @@ class SC64:
|
||||
raise ConnectionException('Error while getting firmware backup')
|
||||
return self.__read_memory(address, length)
|
||||
|
||||
def set_cic_parameters(self, seed: Optional[int]=None, disabled=False) -> tuple[int, int, bool]:
|
||||
def update_cic_parameters(self, seed: Optional[int]=None, disabled=False) -> tuple[int, int, bool]:
|
||||
if ((seed != None) and (seed < 0 or seed > 0xFF)):
|
||||
raise ValueError('CIC seed outside of allowed values')
|
||||
boot_mode = self.__get_config(self.__CfgId.BOOT_MODE)
|
||||
@ -884,7 +891,7 @@ class SC64:
|
||||
current_image = 0
|
||||
next_image = 0
|
||||
|
||||
self.__set_config(self.__CfgId.ROM_WRITE_ENABLE, isv)
|
||||
self.__set_config(self.__CfgId.ROM_WRITE_ENABLE, 1 if (isv != 0) else 0)
|
||||
self.__set_config(self.__CfgId.ISV_ADDRESS, isv)
|
||||
if (isv != 0):
|
||||
print(f'IS-Viewer64 support set to [ENABLED] at ROM offset [0x{(isv):08X}]')
|
||||
@ -992,16 +999,24 @@ if __name__ == '__main__':
|
||||
disabled = bool(int(params[1])) if len(params) >= 2 else None
|
||||
return (seed, disabled)
|
||||
|
||||
def download_memory_type(argument: str):
|
||||
params = argument.split(',')
|
||||
if (len(params) < 2 or len(params) > 3):
|
||||
raise argparse.ArgumentError()
|
||||
address = int(params[0], 0)
|
||||
length = int(params[1], 0)
|
||||
file = params[2] if len(params) >= 3 else 'sc64dump.bin'
|
||||
return (address, length, file)
|
||||
|
||||
parser = argparse.ArgumentParser(description='SC64 control software')
|
||||
parser.add_argument('--backup-firmware', metavar='file', help='backup SC64 firmware and write it to specified file')
|
||||
parser.add_argument('--update-firmware', metavar='file', help='update SC64 firmware from specified file')
|
||||
parser.add_argument('--update-bootloader', metavar='file', help='update SC64 bootloader (not recommended, use --update-firmware instead)')
|
||||
parser.add_argument('--reset-state', action='store_true', help='reset SC64 internal state')
|
||||
parser.add_argument('--print-state', action='store_true', help='print SC64 internal state')
|
||||
parser.add_argument('--led-enabled', metavar='{true,false}', help='disable or enable LED I/O activity blinking')
|
||||
parser.add_argument('--led-blink', metavar='{yes,no}', help='disable or enable LED I/O activity blinking')
|
||||
parser.add_argument('--boot', type=SC64.BootMode, action=EnumAction, help='set boot mode')
|
||||
parser.add_argument('--tv', type=SC64.TVType, action=EnumAction, help='force TV type to set value')
|
||||
parser.add_argument('--cic', type=SC64.CICSeed, action=EnumAction, help='force CIC seed to set value')
|
||||
parser.add_argument('--tv', type=SC64.TVType, action=EnumAction, help='force TV type to set value, not used when direct boot mode is enabled')
|
||||
parser.add_argument('--cic', type=SC64.CICSeed, action=EnumAction, help='force CIC seed to set value, not used when direct boot mode is enabled')
|
||||
parser.add_argument('--cic-params', metavar='seed,[disabled]', type=cic_params_type, help='set CIC emulation parameters')
|
||||
parser.add_argument('--rtc', action='store_true', help='update clock in SC64 to system time')
|
||||
parser.add_argument('--no-shadow', action='store_false', help='do not put last 128 kB of ROM inside flash memory (can corrupt non EEPROM saves)')
|
||||
@ -1014,7 +1029,7 @@ if __name__ == '__main__':
|
||||
parser.add_argument('--isv', type=lambda x: int(x, 0), default=0, help='enable IS-Viewer64 support at provided ROM offset')
|
||||
parser.add_argument('--gdb', metavar='port', type=int, help='expose socket port for GDB debugging')
|
||||
parser.add_argument('--debug', action='store_true', help='run debug loop')
|
||||
parser.add_argument('--download-memory', metavar='file', help='download whole memory space and write it to specified file')
|
||||
parser.add_argument('--download-memory', metavar='address,length,[file]', type=download_memory_type, help='download specified memory region and write it to file')
|
||||
|
||||
if (len(sys.argv) <= 1):
|
||||
parser.print_help()
|
||||
@ -1039,13 +1054,7 @@ if __name__ == '__main__':
|
||||
sc64.update_firmware(f.read(), status_callback)
|
||||
print('done')
|
||||
|
||||
sc64.check_api_version()
|
||||
|
||||
if (args.update_bootloader):
|
||||
with open(args.update_bootloader, 'rb') as f:
|
||||
print('Uploading Bootloader... ', end='', flush=True)
|
||||
sc64.upload_bootloader(f.read())
|
||||
print('done')
|
||||
sc64.check_firmware_version()
|
||||
|
||||
if (args.reset_state):
|
||||
sc64.reset_state()
|
||||
@ -1059,10 +1068,10 @@ if __name__ == '__main__':
|
||||
value = getattr(value, 'name')
|
||||
print(f' {key}: {value}')
|
||||
|
||||
if (args.led_enabled != None):
|
||||
value = (args.led_enabled == 'true')
|
||||
sc64.set_led_enable(value)
|
||||
print(f'LED blinking set to [{"ENABLED" if value else "DISABLED"}]')
|
||||
if (args.led_blink):
|
||||
blink = (args.led_blink == 'yes')
|
||||
sc64.set_led_enable(blink)
|
||||
print(f'LED blinking set to [{"ENABLED" if blink else "DISABLED"}]')
|
||||
|
||||
if (args.tv != None):
|
||||
sc64.set_tv_type(args.tv)
|
||||
@ -1085,6 +1094,12 @@ if __name__ == '__main__':
|
||||
autodetected_save_type = sc64.autodetect_save_type(rom_data)
|
||||
print('done')
|
||||
|
||||
if (args.ddipl):
|
||||
with open(args.ddipl, 'rb') as f:
|
||||
print('Uploading 64DD IPL... ', end='', flush=True)
|
||||
sc64.upload_ddipl(f.read())
|
||||
print('done')
|
||||
|
||||
if (args.save_type != None or autodetected_save_type != None):
|
||||
save_type = args.save_type if args.save_type != None else autodetected_save_type
|
||||
sc64.set_save_type(save_type)
|
||||
@ -1096,26 +1111,20 @@ if __name__ == '__main__':
|
||||
sc64.upload_save(f.read())
|
||||
print('done')
|
||||
|
||||
if (args.ddipl):
|
||||
with open(args.ddipl, 'rb') as f:
|
||||
print('Uploading 64DD IPL... ', end='', flush=True)
|
||||
sc64.upload_ddipl(f.read())
|
||||
print('done')
|
||||
|
||||
if (args.boot != None):
|
||||
sc64.set_boot_mode(args.boot)
|
||||
print(f'Boot mode set to [{args.boot.name}]')
|
||||
|
||||
if (args.cic_params != None):
|
||||
(seed, disabled) = args.cic_params
|
||||
(seed, checksum, dd_mode) = sc64.set_cic_parameters(seed, disabled)
|
||||
(seed, checksum, dd_mode) = sc64.update_cic_parameters(seed, disabled)
|
||||
print('CIC parameters set to [', end='')
|
||||
print(f'{"DISABLED" if disabled else "ENABLED"}, ', end='')
|
||||
print(f'{"DDIPL" if dd_mode else "ROM"}, ', end='')
|
||||
print(f'seed: 0x{seed:02X}, checksum: 0x{checksum:012X}', end='')
|
||||
print(']')
|
||||
else:
|
||||
sc64.set_cic_parameters()
|
||||
sc64.update_cic_parameters()
|
||||
|
||||
if (args.debug or args.isv or args.disk or args.gdb):
|
||||
sc64.debug_loop(isv=args.isv, disks=args.disk, gdb_port=args.gdb)
|
||||
@ -1126,10 +1135,11 @@ if __name__ == '__main__':
|
||||
f.write(sc64.download_save())
|
||||
print('done')
|
||||
|
||||
if (args.download_memory):
|
||||
with open(args.download_memory, 'wb') as f:
|
||||
if (args.download_memory != None):
|
||||
(address, length, file) = args.download_memory
|
||||
with open(file, 'wb') as f:
|
||||
print('Downloading memory... ', end='', flush=True)
|
||||
f.write(sc64.download_memory())
|
||||
f.write(sc64.download_memory(address, length))
|
||||
print('done')
|
||||
except ValueError as e:
|
||||
print(f'\nValue error: {e}')
|
||||
|
Loading…
Reference in New Issue
Block a user