CFG error handling, TLOZ MM debug ISV support

This commit is contained in:
Polprzewodnikowy 2022-10-02 23:45:05 +02:00
parent fa561b4728
commit 567818ce35
11 changed files with 149 additions and 84 deletions

View File

@ -6,6 +6,7 @@ PACKAGE_FILE_NAME="SC64"
FILES=( FILES=(
"./fw/ftdi/ft232h_config.xml" "./fw/ftdi/ft232h_config.xml"
"./fw/project/lcmxo2/impl1/sc64_impl1.mrp"
"./fw/project/lcmxo2/impl1/sc64_impl1.twr" "./fw/project/lcmxo2/impl1/sc64_impl1.twr"
"./sw/pc/dd64.py" "./sw/pc/dd64.py"
"./sw/pc/sc64.py" "./sw/pc/sc64.py"

View File

@ -24,7 +24,7 @@ typedef enum {
CFG_ID_SAVE_TYPE, CFG_ID_SAVE_TYPE,
CFG_ID_CIC_SEED, CFG_ID_CIC_SEED,
CFG_ID_TV_TYPE, CFG_ID_TV_TYPE,
CFG_ID_DD_SD_MODE, CFG_ID_DD_SD_ENABLE,
CFG_ID_DD_DRIVE_TYPE, CFG_ID_DD_DRIVE_TYPE,
CFG_ID_DD_DISK_STATE, CFG_ID_DD_DISK_STATE,
CFG_ID_BUTTON_STATE, CFG_ID_BUTTON_STATE,

View File

@ -20,11 +20,15 @@ bool button_get_state (void) {
return p.state; return p.state;
} }
void button_set_mode (button_mode_t mode) { bool button_set_mode (button_mode_t mode) {
if (mode > BUTTON_MODE_DD_DISK_SWAP) {
return true;
}
p.mode = mode; p.mode = mode;
if (p.mode == BUTTON_MODE_NONE) { if (p.mode == BUTTON_MODE_NONE) {
p.trigger = false; p.trigger = false;
} }
return false;
} }
button_mode_t button_get_mode (void) { button_mode_t button_get_mode (void) {

View File

@ -14,7 +14,7 @@ typedef enum {
bool button_get_state (void); bool button_get_state (void);
void button_set_mode (button_mode_t mode); bool button_set_mode (button_mode_t mode);
button_mode_t button_get_mode (void); button_mode_t button_get_mode (void);
void button_init (void); void button_init (void);
void button_process (void); void button_process (void);

View File

@ -14,12 +14,12 @@ typedef enum {
CFG_ID_ROM_WRITE_ENABLE, CFG_ID_ROM_WRITE_ENABLE,
CFG_ID_ROM_SHADOW_ENABLE, CFG_ID_ROM_SHADOW_ENABLE,
CFG_ID_DD_MODE, CFG_ID_DD_MODE,
CFG_ID_ISV_ENABLE, CFG_ID_ISV_ADDRESS,
CFG_ID_BOOT_MODE, CFG_ID_BOOT_MODE,
CFG_ID_SAVE_TYPE, CFG_ID_SAVE_TYPE,
CFG_ID_CIC_SEED, CFG_ID_CIC_SEED,
CFG_ID_TV_TYPE, CFG_ID_TV_TYPE,
CFG_ID_DD_SD_MODE, CFG_ID_DD_SD_ENABLE,
CFG_ID_DD_DRIVE_TYPE, CFG_ID_DD_DRIVE_TYPE,
CFG_ID_DD_DISK_STATE, CFG_ID_DD_DISK_STATE,
CFG_ID_BUTTON_STATE, CFG_ID_BUTTON_STATE,
@ -172,7 +172,11 @@ static void cfg_change_scr_bits (uint32_t mask, bool value) {
} }
} }
static void cfg_set_save_type (save_type_t save_type) { static bool cfg_set_save_type (save_type_t save_type) {
if (save_type > SAVE_TYPE_SRAM_BANKED) {
return true;
}
uint32_t save_reset_mask = ( uint32_t save_reset_mask = (
CFG_SCR_EEPROM_16K | CFG_SCR_EEPROM_16K |
CFG_SCR_EEPROM_ENABLED | CFG_SCR_EEPROM_ENABLED |
@ -207,6 +211,8 @@ static void cfg_set_save_type (save_type_t save_type) {
} }
p.save_type = save_type; p.save_type = save_type;
return false;
} }
@ -236,8 +242,8 @@ bool cfg_query (uint32_t *args) {
args[1] |= DD_MODE_REGS; args[1] |= DD_MODE_REGS;
} }
break; break;
case CFG_ID_ISV_ENABLE: case CFG_ID_ISV_ADDRESS:
args[1] = isv_get_enabled(); args[1] = isv_get_address();
break; break;
case CFG_ID_BOOT_MODE: case CFG_ID_BOOT_MODE:
args[1] = p.boot_mode; args[1] = p.boot_mode;
@ -251,6 +257,9 @@ bool cfg_query (uint32_t *args) {
case CFG_ID_TV_TYPE: case CFG_ID_TV_TYPE:
args[1] = p.tv_type; args[1] = p.tv_type;
break; break;
case CFG_ID_DD_SD_ENABLE:
args[1] = dd_get_sd_mode();
break;
case CFG_ID_DD_DRIVE_TYPE: case CFG_ID_DD_DRIVE_TYPE:
args[1] = dd_get_drive_type(); args[1] = dd_get_drive_type();
break; break;
@ -266,9 +275,6 @@ bool cfg_query (uint32_t *args) {
case CFG_ID_ROM_EXTENDED_ENABLE: case CFG_ID_ROM_EXTENDED_ENABLE:
args[1] = (scr & CFG_SCR_ROM_EXTENDED_ENABLED); args[1] = (scr & CFG_SCR_ROM_EXTENDED_ENABLED);
break; break;
case CFG_ID_DD_SD_MODE:
args[1] = dd_get_sd_mode();
break;
default: default:
return true; return true;
} }
@ -296,43 +302,55 @@ bool cfg_update (uint32_t *args) {
} else if (args[1] == DD_MODE_IPL) { } else if (args[1] == DD_MODE_IPL) {
cfg_change_scr_bits(CFG_SCR_DD_ENABLED, false); cfg_change_scr_bits(CFG_SCR_DD_ENABLED, false);
cfg_change_scr_bits(CFG_SCR_DDIPL_ENABLED, true); cfg_change_scr_bits(CFG_SCR_DDIPL_ENABLED, true);
} else { } else if (args[1] == DD_MODE_FULL) {
cfg_change_scr_bits(CFG_SCR_DD_ENABLED | CFG_SCR_DDIPL_ENABLED, true); cfg_change_scr_bits(CFG_SCR_DD_ENABLED | CFG_SCR_DDIPL_ENABLED, true);
} else {
return true;
} }
break; break;
case CFG_ID_ISV_ENABLE: case CFG_ID_ISV_ADDRESS:
isv_set_enabled(args[1]); return isv_set_address(args[1]);
break; break;
case CFG_ID_BOOT_MODE: case CFG_ID_BOOT_MODE:
if (args[1] > BOOT_MODE_DIRECT) {
return true;
}
p.boot_mode = args[1]; p.boot_mode = args[1];
cfg_change_scr_bits(CFG_SCR_BOOTLOADER_SKIP, (args[1] == BOOT_MODE_DIRECT)); cfg_change_scr_bits(CFG_SCR_BOOTLOADER_SKIP, (args[1] == BOOT_MODE_DIRECT));
break; break;
case CFG_ID_SAVE_TYPE: case CFG_ID_SAVE_TYPE:
cfg_set_save_type((save_type_t) (args[1])); return cfg_set_save_type((save_type_t) (args[1]));
break; break;
case CFG_ID_CIC_SEED: case CFG_ID_CIC_SEED:
if ((args[1] != 0xFFFF) && (args[1] > 0x1FF)) {
return true;
}
p.cic_seed = (cic_seed_t) (args[1] & 0xFFFF); p.cic_seed = (cic_seed_t) (args[1] & 0xFFFF);
break; break;
case CFG_ID_TV_TYPE: case CFG_ID_TV_TYPE:
if (args[1] > TV_TYPE_UNKNOWN) {
return true;
}
p.tv_type = (tv_type_t) (args[1] & 0x03); p.tv_type = (tv_type_t) (args[1] & 0x03);
break; break;
case CFG_ID_DD_SD_ENABLE:
dd_set_sd_mode(args[1]);
break;
case CFG_ID_DD_DRIVE_TYPE: case CFG_ID_DD_DRIVE_TYPE:
dd_set_drive_type(args[1]); return dd_set_drive_type(args[1]);
break; break;
case CFG_ID_DD_DISK_STATE: case CFG_ID_DD_DISK_STATE:
dd_set_disk_state(args[1]); return dd_set_disk_state(args[1]);
break; break;
case CFG_ID_BUTTON_STATE: case CFG_ID_BUTTON_STATE:
return true; return true;
break;
case CFG_ID_BUTTON_MODE: case CFG_ID_BUTTON_MODE:
button_set_mode(args[1]); return button_set_mode(args[1]);
break; break;
case CFG_ID_ROM_EXTENDED_ENABLE: case CFG_ID_ROM_EXTENDED_ENABLE:
cfg_change_scr_bits(CFG_SCR_ROM_EXTENDED_ENABLED, args[1]); cfg_change_scr_bits(CFG_SCR_ROM_EXTENDED_ENABLED, args[1]);
break; break;
case CFG_ID_DD_SD_MODE:
dd_set_sd_mode(args[1]);
break;
default: default:
return true; return true;
} }
@ -374,7 +392,7 @@ void cfg_reset_state (void) {
dd_set_drive_type(DD_DRIVE_TYPE_RETAIL); dd_set_drive_type(DD_DRIVE_TYPE_RETAIL);
dd_set_disk_state(DD_DISK_STATE_EJECTED); dd_set_disk_state(DD_DISK_STATE_EJECTED);
dd_set_sd_mode(false); dd_set_sd_mode(false);
isv_set_enabled(false); isv_set_address(0);
p.cic_seed = CIC_SEED_UNKNOWN; p.cic_seed = CIC_SEED_UNKNOWN;
p.tv_type = TV_TYPE_UNKNOWN; p.tv_type = TV_TYPE_UNKNOWN;
p.boot_mode = BOOT_MODE_MENU; p.boot_mode = BOOT_MODE_MENU;

View File

@ -209,7 +209,7 @@ dd_drive_type_t dd_get_drive_type (void) {
return p.drive_type; return p.drive_type;
} }
void dd_set_drive_type (dd_drive_type_t type) { bool dd_set_drive_type (dd_drive_type_t type) {
switch (type) { switch (type) {
case DD_DRIVE_TYPE_RETAIL: case DD_DRIVE_TYPE_RETAIL:
fpga_reg_set(REG_DD_DRIVE_ID, DD_DRIVE_ID_RETAIL); fpga_reg_set(REG_DD_DRIVE_ID, DD_DRIVE_ID_RETAIL);
@ -220,7 +220,11 @@ void dd_set_drive_type (dd_drive_type_t type) {
fpga_reg_set(REG_DD_DRIVE_ID, DD_DRIVE_ID_DEVELOPMENT); fpga_reg_set(REG_DD_DRIVE_ID, DD_DRIVE_ID_DEVELOPMENT);
p.drive_type = type; p.drive_type = type;
break; break;
default:
return true;
} }
return false;
} }
dd_disk_state_t dd_get_disk_state (void) { dd_disk_state_t dd_get_disk_state (void) {
@ -234,7 +238,10 @@ dd_disk_state_t dd_get_disk_state (void) {
return DD_DISK_STATE_EJECTED; return DD_DISK_STATE_EJECTED;
} }
void dd_set_disk_state (dd_disk_state_t state) { bool dd_set_disk_state (dd_disk_state_t state) {
if (state > DD_DISK_STATE_CHANGED) {
return true;
}
uint32_t scr = fpga_reg_get(REG_DD_SCR); uint32_t scr = fpga_reg_get(REG_DD_SCR);
scr &= ~(DD_SCR_DISK_CHANGED | DD_SCR_DISK_INSERTED); scr &= ~(DD_SCR_DISK_CHANGED | DD_SCR_DISK_INSERTED);
switch (state) { switch (state) {
@ -250,6 +257,7 @@ void dd_set_disk_state (dd_disk_state_t state) {
break; break;
} }
fpga_reg_set(REG_DD_SCR, scr); fpga_reg_set(REG_DD_SCR, scr);
return false;
} }
bool dd_get_sd_mode (void) { bool dd_get_sd_mode (void) {

View File

@ -3,6 +3,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
typedef enum { typedef enum {
@ -19,9 +20,9 @@ typedef enum {
void dd_set_block_ready (bool valid); void dd_set_block_ready (bool valid);
dd_drive_type_t dd_get_drive_type (void); dd_drive_type_t dd_get_drive_type (void);
void dd_set_drive_type (dd_drive_type_t type); bool dd_set_drive_type (dd_drive_type_t type);
dd_disk_state_t dd_get_disk_state (void); dd_disk_state_t dd_get_disk_state (void);
void dd_set_disk_state (dd_disk_state_t state); bool dd_set_disk_state (dd_disk_state_t state);
bool dd_get_sd_mode (void); bool dd_get_sd_mode (void);
void dd_set_sd_mode (bool value); void dd_set_sd_mode (bool value);
void dd_set_sd_disk_info (uint32_t address, uint32_t length); void dd_set_sd_disk_info (uint32_t address, uint32_t length);

View File

@ -4,70 +4,94 @@
#include "usb.h" #include "usb.h"
#define ISV_READ_POINTER_ADDRESS (0x03FF0004) #define ISV_TOKEN (0x49533634)
#define ISV_WRITE_POINTER_ADDRESS (0x03FF0014)
#define ISV_BUFFER_ADDRESS (0x03FF0020) #define ISV_SETUP_TOKEN_ADDRESS (0x00000100)
#define ISV_BUFFER_SIZE ((64 * 1024) - 0x20) #define ISV_SETUP_OFFSET_ADDRESS (0x00000104)
#define ISV_SETUP_READY_ADDRESS (0x0000010C)
#define ISV_TOKEN_OFFSET (0x00000000)
#define ISV_READ_POINTER_OFFSET (0x00000004)
#define ISV_WRITE_POINTER_OFFSET (0x00000014)
#define ISV_BUFFER_OFFSET (0x00000020)
#define ISV_BUFFER_SIZE ((64 * 1024) - ISV_BUFFER_OFFSET)
struct process { struct process {
bool enabled; bool ready;
uint32_t current_read_pointer; uint32_t address;
uint32_t next_read_pointer;
}; };
static struct process p; static struct process p;
static void isv_set_pointer (uint32_t address, uint32_t data) { static void isv_set_value (uint32_t address, uint32_t data) {
data = SWAP32(data); data = SWAP32(data);
fpga_mem_write(address, 4, (uint8_t *) (&data)); fpga_mem_write(address, 4, (uint8_t *) (&data));
} }
static uint32_t isv_get_pointer (uint32_t address) { static uint32_t isv_get_value (uint32_t address) {
uint32_t data; uint32_t data;
fpga_mem_read(address, 4, (uint8_t *) (&data)); fpga_mem_read(address, 4, (uint8_t *) (&data));
return SWAP32(data); return SWAP32(data);
} }
static void isv_update_read_pointer (void) { static void isv_update_read_pointer (void) {
isv_set_pointer(ISV_READ_POINTER_ADDRESS, p.current_read_pointer); p.ready = true;
isv_set_value(p.address + ISV_READ_POINTER_OFFSET, p.next_read_pointer);
} }
void isv_set_enabled (bool enabled) { bool isv_set_address (uint32_t address) {
if (enabled) { if ((address > 0x03FF0000) || (address % 4)) {
p.enabled = true; return true;
p.current_read_pointer = 0;
isv_set_pointer(ISV_READ_POINTER_ADDRESS, 0);
isv_set_pointer(ISV_WRITE_POINTER_ADDRESS, 0);
} else {
p.enabled = false;
} }
p.address = address;
return false;
} }
bool isv_get_enabled (void) { uint32_t isv_get_address (void) {
return p.enabled; return p.address;
} }
void isv_init (void) { void isv_init (void) {
p.enabled = false; p.address = 0;
p.ready = true;
} }
void isv_process (void) { void isv_process (void) {
if (p.enabled) { if ((p.address != 0) && p.ready) {
uint32_t write_pointer = isv_get_pointer(ISV_WRITE_POINTER_ADDRESS); if (isv_get_value(ISV_SETUP_TOKEN_ADDRESS) == ISV_TOKEN) {
isv_set_value(ISV_SETUP_TOKEN_ADDRESS, 0);
if (p.current_read_pointer == write_pointer) { isv_set_value(ISV_SETUP_OFFSET_ADDRESS, (p.address | 0x10000000));
isv_set_value(ISV_SETUP_READY_ADDRESS, ISV_TOKEN);
return; return;
} }
if (isv_get_value(p.address + ISV_TOKEN_OFFSET) != ISV_TOKEN) {
return;
}
uint32_t read_pointer = isv_get_value(p.address + ISV_READ_POINTER_OFFSET);
if (read_pointer >= ISV_BUFFER_SIZE) {
return;
}
uint32_t write_pointer = isv_get_value(p.address + ISV_WRITE_POINTER_OFFSET);
if (write_pointer >= ISV_BUFFER_SIZE) { if (write_pointer >= ISV_BUFFER_SIZE) {
return; return;
} }
bool wrap = write_pointer < p.current_read_pointer; if (read_pointer == write_pointer) {
uint32_t length = (wrap ? ISV_BUFFER_SIZE : write_pointer) - p.current_read_pointer; return;
uint32_t offset = ISV_BUFFER_ADDRESS + p.current_read_pointer; }
bool wrap = write_pointer < read_pointer;
uint32_t length = (wrap ? ISV_BUFFER_SIZE : write_pointer) - read_pointer;
uint32_t offset = p.address + ISV_BUFFER_OFFSET + read_pointer;
usb_tx_info_t packet_info; usb_tx_info_t packet_info;
usb_create_packet(&packet_info, PACKET_CMD_ISV_OUTPUT); usb_create_packet(&packet_info, PACKET_CMD_ISV_OUTPUT);
@ -75,7 +99,8 @@ void isv_process (void) {
packet_info.dma_address = offset; packet_info.dma_address = offset;
packet_info.done_callback = isv_update_read_pointer; packet_info.done_callback = isv_update_read_pointer;
if (usb_enqueue_packet(&packet_info)) { if (usb_enqueue_packet(&packet_info)) {
p.current_read_pointer = wrap ? 0 : write_pointer; p.ready = false;
p.next_read_pointer = wrap ? 0 : write_pointer;
} }
} }
} }

View File

@ -3,10 +3,11 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
void isv_set_enabled (bool enabled); bool isv_set_address (uint32_t address);
bool isv_get_enabled (void); uint32_t isv_get_address (void);
void isv_init (void); void isv_init (void);
void isv_process (void); void isv_process (void);

View File

@ -203,12 +203,6 @@ static void usb_rx_process (void) {
p.response_pending = true; p.response_pending = true;
break; break;
case 'd':
dd_set_block_ready(p.rx_args[0] == 0);
p.rx_state = RX_STATE_IDLE;
p.response_pending = true;
break;
case 'm': case 'm':
p.rx_state = RX_STATE_IDLE; p.rx_state = RX_STATE_IDLE;
p.response_pending = true; p.response_pending = true;
@ -216,7 +210,6 @@ static void usb_rx_process (void) {
p.response_info.dma_length = p.rx_args[1]; p.response_info.dma_length = p.rx_args[1];
break; break;
case 'D':
case 'M': case 'M':
if (usb_dma_ready()) { if (usb_dma_ready()) {
if (!p.rx_dma_running) { if (!p.rx_dma_running) {
@ -227,13 +220,16 @@ static void usb_rx_process (void) {
} else { } else {
p.rx_state = RX_STATE_IDLE; p.rx_state = RX_STATE_IDLE;
p.response_pending = true; p.response_pending = true;
if (p.rx_cmd == 'D') {
dd_set_block_ready(true);
}
} }
} }
break; 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': case 'U':
if ((p.read_length > 0) && usb_dma_ready()) { 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; uint32_t length = (p.read_length > p.rx_args[1]) ? p.rx_args[1] : p.read_length;

View File

@ -230,12 +230,12 @@ class SC64:
ROM_WRITE_ENABLE = 1 ROM_WRITE_ENABLE = 1
ROM_SHADOW_ENABLE = 2 ROM_SHADOW_ENABLE = 2
DD_MODE = 3 DD_MODE = 3
ISV_ENABLE = 4 ISV_ADDRESS = 4
BOOT_MODE = 5 BOOT_MODE = 5
SAVE_TYPE = 6 SAVE_TYPE = 6
CIC_SEED = 7 CIC_SEED = 7
TV_TYPE = 8 TV_TYPE = 8
DD_SD_MODE = 9 DD_SD_ENABLE = 9
DD_DRIVE_TYPE = 10 DD_DRIVE_TYPE = 10
DD_DISK_STATE = 11 DD_DISK_STATE = 11
BUTTON_STATE = 12 BUTTON_STATE = 12
@ -327,10 +327,16 @@ class SC64:
return int.from_bytes(data[:4], byteorder='big') return int.from_bytes(data[:4], byteorder='big')
def __set_config(self, config: __CfgId, value: int) -> None: def __set_config(self, config: __CfgId, value: int) -> None:
try:
self.__link.execute_cmd(cmd=b'C', args=[config, value]) self.__link.execute_cmd(cmd=b'C', args=[config, value])
except ConnectionException:
raise ValueError(f'Could not set config {config.name} to {value:08X}')
def __get_config(self, config: __CfgId) -> int: def __get_config(self, config: __CfgId) -> int:
try:
data = self.__link.execute_cmd(cmd=b'c', args=[config, 0]) data = self.__link.execute_cmd(cmd=b'c', args=[config, 0])
except ConnectionException:
raise ValueError(f'Could not get config {config.name}')
return self.__get_int(data) return self.__get_int(data)
def __write_memory(self, address: int, data: bytes) -> None: def __write_memory(self, address: int, data: bytes) -> None:
@ -342,6 +348,9 @@ class SC64:
return self.__link.execute_cmd(cmd=b'm', args=[address, length], timeout=20.0) return self.__link.execute_cmd(cmd=b'm', args=[address, length], timeout=20.0)
return bytes([]) return bytes([])
def __dd_set_block_ready(self, error: int) -> None:
self.__link.execute_cmd(cmd=b'D', args=[error, 0])
def __flash_wait_busy(self) -> int: def __flash_wait_busy(self) -> int:
data = self.__link.execute_cmd(cmd=b'p') data = self.__link.execute_cmd(cmd=b'p')
return self.__get_int(data[0:4]) return self.__get_int(data[0:4])
@ -379,7 +388,7 @@ class SC64:
'rom_write_enable': bool(self.__get_config(self.__CfgId.ROM_WRITE_ENABLE)), 'rom_write_enable': bool(self.__get_config(self.__CfgId.ROM_WRITE_ENABLE)),
'rom_shadow_enable': bool(self.__get_config(self.__CfgId.ROM_SHADOW_ENABLE)), 'rom_shadow_enable': bool(self.__get_config(self.__CfgId.ROM_SHADOW_ENABLE)),
'dd_mode': self.__DDMode(self.__get_config(self.__CfgId.DD_MODE)), 'dd_mode': self.__DDMode(self.__get_config(self.__CfgId.DD_MODE)),
'isv_enable': bool(self.__get_config(self.__CfgId.ISV_ENABLE)), 'isv_address': self.__get_config(self.__CfgId.ISV_ADDRESS),
'boot_mode': self.BootMode(self.__get_config(self.__CfgId.BOOT_MODE)), 'boot_mode': self.BootMode(self.__get_config(self.__CfgId.BOOT_MODE)),
'save_type': self.SaveType(self.__get_config(self.__CfgId.SAVE_TYPE)), 'save_type': self.SaveType(self.__get_config(self.__CfgId.SAVE_TYPE)),
'cic_seed': self.CICSeed(self.__get_config(self.__CfgId.CIC_SEED)), 'cic_seed': self.CICSeed(self.__get_config(self.__CfgId.CIC_SEED)),
@ -537,14 +546,16 @@ class SC64:
raise BadBlockError raise BadBlockError
if (cmd == CMD_READ_BLOCK): if (cmd == CMD_READ_BLOCK):
block_data = dd.read_block(track, head, block) block_data = dd.read_block(track, head, block)
self.__link.execute_cmd(cmd=b'D', args=[address, len(block_data)], data=block_data) self.__write_memory(address, block_data)
self.__dd_set_block_ready(0)
elif (cmd == CMD_WRITE_BLOCK): elif (cmd == CMD_WRITE_BLOCK):
dd.write_block(track, head, block, data[12:]) block_data = data[12:]
self.__link.execute_cmd(cmd=b'd', args=[0, 0]) dd.write_block(track, head, block, block_data)
self.__dd_set_block_ready(0)
else: else:
self.__link.execute_cmd(cmd=b'd', args=[-1, 0]) self.__dd_set_block_ready(1)
except BadBlockError: except BadBlockError:
self.__link.execute_cmd(cmd=b'd', args=[1, 0]) self.__dd_set_block_ready(1)
def __handle_isv_packet(self, data: bytes) -> None: def __handle_isv_packet(self, data: bytes) -> None:
print(data.decode('EUC-JP', errors='backslashreplace'), end='') print(data.decode('EUC-JP', errors='backslashreplace'), end='')
@ -618,15 +629,15 @@ class SC64:
except EOFError: except EOFError:
running = False running = False
def debug_loop(self, isv: bool=False, disks: Optional[list[str]]=None) -> None: def debug_loop(self, isv: int=0, disks: Optional[list[str]]=None) -> None:
dd = None dd = None
current_image = 0 current_image = 0
next_image = 0 next_image = 0
self.__set_config(self.__CfgId.ROM_WRITE_ENABLE, isv) self.__set_config(self.__CfgId.ROM_WRITE_ENABLE, isv)
self.__set_config(self.__CfgId.ISV_ENABLE, isv) self.__set_config(self.__CfgId.ISV_ADDRESS, isv)
if (isv): if (isv != 0):
print('IS-Viewer64 support set to [ENABLED]') print(f'IS-Viewer64 support set to [ENABLED] at ROM offset [0x{(isv):08X}]')
if (self.__get_config(self.__CfgId.ROM_SHADOW_ENABLE)): if (self.__get_config(self.__CfgId.ROM_SHADOW_ENABLE)):
print('ROM shadow enabled - IS-Viewer64 will NOT work (use --no-shadow option to disable it)') print('ROM shadow enabled - IS-Viewer64 will NOT work (use --no-shadow option to disable it)')
@ -694,8 +705,8 @@ class SC64:
if (dd and dd.loaded): if (dd and dd.loaded):
self.__set_config(self.__CfgId.DD_DISK_STATE, self.__DDDiskState.EJECTED) self.__set_config(self.__CfgId.DD_DISK_STATE, self.__DDDiskState.EJECTED)
if (isv): if (isv != 0):
self.__set_config(self.__CfgId.ISV_ENABLE, False) self.__set_config(self.__CfgId.ISV_ADDRESS, 0)
class EnumAction(argparse.Action): class EnumAction(argparse.Action):
@ -735,7 +746,7 @@ if __name__ == '__main__':
parser.add_argument('--backup-save', metavar='file', help='download save and write it to specified file') parser.add_argument('--backup-save', metavar='file', help='download save and write it to specified file')
parser.add_argument('--ddipl', metavar='file', help='upload 64DD IPL from specified file') parser.add_argument('--ddipl', metavar='file', help='upload 64DD IPL from specified file')
parser.add_argument('--disk', metavar='file', action='append', help='path to 64DD disk (.ndd format), can be specified multiple times') parser.add_argument('--disk', metavar='file', action='append', help='path to 64DD disk (.ndd format), can be specified multiple times')
parser.add_argument('--isv', action='store_true', help='enable IS-Viewer64 support') parser.add_argument('--isv', type=lambda x: int(x, 0), default=0, help='enable IS-Viewer64 support at provided ROM offset')
parser.add_argument('--debug', action='store_true', help='run debug loop (required for 64DD and IS-Viewer64)') parser.add_argument('--debug', action='store_true', help='run debug loop (required for 64DD and IS-Viewer64)')
parser.add_argument('--download-memory', metavar='file', help='download whole memory space and write it to specified file') parser.add_argument('--download-memory', metavar='file', help='download whole memory space and write it to specified file')