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=(
"./fw/ftdi/ft232h_config.xml"
"./fw/project/lcmxo2/impl1/sc64_impl1.mrp"
"./fw/project/lcmxo2/impl1/sc64_impl1.twr"
"./sw/pc/dd64.py"
"./sw/pc/sc64.py"

View File

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

View File

@ -20,11 +20,15 @@ bool button_get_state (void) {
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;
if (p.mode == BUTTON_MODE_NONE) {
p.trigger = false;
}
return false;
}
button_mode_t button_get_mode (void) {

View File

@ -14,7 +14,7 @@ typedef enum {
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);
void button_init (void);
void button_process (void);

View File

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

View File

@ -3,6 +3,7 @@
#include <stdbool.h>
#include <stdint.h>
typedef enum {
@ -19,9 +20,9 @@ typedef enum {
void dd_set_block_ready (bool valid);
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);
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);
void dd_set_sd_mode (bool value);
void dd_set_sd_disk_info (uint32_t address, uint32_t length);

View File

@ -4,70 +4,94 @@
#include "usb.h"
#define ISV_READ_POINTER_ADDRESS (0x03FF0004)
#define ISV_WRITE_POINTER_ADDRESS (0x03FF0014)
#define ISV_BUFFER_ADDRESS (0x03FF0020)
#define ISV_BUFFER_SIZE ((64 * 1024) - 0x20)
#define ISV_TOKEN (0x49533634)
#define ISV_SETUP_TOKEN_ADDRESS (0x00000100)
#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 {
bool enabled;
uint32_t current_read_pointer;
bool ready;
uint32_t address;
uint32_t next_read_pointer;
};
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);
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;
fpga_mem_read(address, 4, (uint8_t *) (&data));
return SWAP32(data);
}
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) {
if (enabled) {
p.enabled = 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;
bool isv_set_address (uint32_t address) {
if ((address > 0x03FF0000) || (address % 4)) {
return true;
}
p.address = address;
return false;
}
bool isv_get_enabled (void) {
return p.enabled;
uint32_t isv_get_address (void) {
return p.address;
}
void isv_init (void) {
p.enabled = false;
p.address = 0;
p.ready = true;
}
void isv_process (void) {
if (p.enabled) {
uint32_t write_pointer = isv_get_pointer(ISV_WRITE_POINTER_ADDRESS);
if (p.current_read_pointer == write_pointer) {
if ((p.address != 0) && p.ready) {
if (isv_get_value(ISV_SETUP_TOKEN_ADDRESS) == ISV_TOKEN) {
isv_set_value(ISV_SETUP_TOKEN_ADDRESS, 0);
isv_set_value(ISV_SETUP_OFFSET_ADDRESS, (p.address | 0x10000000));
isv_set_value(ISV_SETUP_READY_ADDRESS, ISV_TOKEN);
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) {
return;
}
bool wrap = write_pointer < p.current_read_pointer;
uint32_t length = (wrap ? ISV_BUFFER_SIZE : write_pointer) - p.current_read_pointer;
uint32_t offset = ISV_BUFFER_ADDRESS + p.current_read_pointer;
if (read_pointer == write_pointer) {
return;
}
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_create_packet(&packet_info, PACKET_CMD_ISV_OUTPUT);
@ -75,7 +99,8 @@ void isv_process (void) {
packet_info.dma_address = offset;
packet_info.done_callback = isv_update_read_pointer;
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 <stdint.h>
void isv_set_enabled (bool enabled);
bool isv_get_enabled (void);
bool isv_set_address (uint32_t address);
uint32_t isv_get_address (void);
void isv_init (void);
void isv_process (void);

View File

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

View File

@ -230,12 +230,12 @@ class SC64:
ROM_WRITE_ENABLE = 1
ROM_SHADOW_ENABLE = 2
DD_MODE = 3
ISV_ENABLE = 4
ISV_ADDRESS = 4
BOOT_MODE = 5
SAVE_TYPE = 6
CIC_SEED = 7
TV_TYPE = 8
DD_SD_MODE = 9
DD_SD_ENABLE = 9
DD_DRIVE_TYPE = 10
DD_DISK_STATE = 11
BUTTON_STATE = 12
@ -327,10 +327,16 @@ class SC64:
return int.from_bytes(data[:4], byteorder='big')
def __set_config(self, config: __CfgId, value: int) -> None:
self.__link.execute_cmd(cmd=b'C', args=[config, value])
try:
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:
data = self.__link.execute_cmd(cmd=b'c', args=[config, 0])
try:
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)
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 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:
data = self.__link.execute_cmd(cmd=b'p')
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_shadow_enable': bool(self.__get_config(self.__CfgId.ROM_SHADOW_ENABLE)),
'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)),
'save_type': self.SaveType(self.__get_config(self.__CfgId.SAVE_TYPE)),
'cic_seed': self.CICSeed(self.__get_config(self.__CfgId.CIC_SEED)),
@ -537,14 +546,16 @@ class SC64:
raise BadBlockError
if (cmd == CMD_READ_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):
dd.write_block(track, head, block, data[12:])
self.__link.execute_cmd(cmd=b'd', args=[0, 0])
block_data = data[12:]
dd.write_block(track, head, block, block_data)
self.__dd_set_block_ready(0)
else:
self.__link.execute_cmd(cmd=b'd', args=[-1, 0])
self.__dd_set_block_ready(1)
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:
print(data.decode('EUC-JP', errors='backslashreplace'), end='')
@ -618,15 +629,15 @@ class SC64:
except EOFError:
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
current_image = 0
next_image = 0
self.__set_config(self.__CfgId.ROM_WRITE_ENABLE, isv)
self.__set_config(self.__CfgId.ISV_ENABLE, isv)
if (isv):
print('IS-Viewer64 support set to [ENABLED]')
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}]')
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)')
@ -694,8 +705,8 @@ class SC64:
if (dd and dd.loaded):
self.__set_config(self.__CfgId.DD_DISK_STATE, self.__DDDiskState.EJECTED)
if (isv):
self.__set_config(self.__CfgId.ISV_ENABLE, False)
if (isv != 0):
self.__set_config(self.__CfgId.ISV_ADDRESS, 0)
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('--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('--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('--download-memory', metavar='file', help='download whole memory space and write it to specified file')