[SC64][SW] Changed firmware version reporting

This commit is contained in:
Mateusz Faderewski 2023-02-20 18:17:09 +01:00
parent 56cdd3a709
commit 409ba28359
14 changed files with 142 additions and 152 deletions

View File

@ -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.

View File

@ -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 |

View File

@ -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 |

View File

@ -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

View File

@ -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

View File

@ -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 (

View File

@ -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) {

View File

@ -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;

View File

@ -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);

View File

@ -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,

View File

@ -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;

View File

@ -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));
}

View File

@ -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

View File

@ -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}')