extended ROM and ISV fixes

This commit is contained in:
Polprzewodnikowy 2022-09-02 22:48:47 +02:00
parent dbf4b5e3c8
commit 2cc618b268
7 changed files with 175 additions and 119 deletions

View File

@ -429,7 +429,8 @@ module mcu_top (
REG_CFG_SCR: begin REG_CFG_SCR: begin
reg_rdata <= { reg_rdata <= {
21'd0, 20'd0,
n64_scb.rom_extended_enabled,
n64_scb.eeprom_16k_mode, n64_scb.eeprom_16k_mode,
n64_scb.eeprom_enabled, n64_scb.eeprom_enabled,
n64_scb.ddipl_enabled, n64_scb.ddipl_enabled,
@ -638,6 +639,7 @@ module mcu_top (
if (reset) begin if (reset) begin
mcu_int <= 1'b0; mcu_int <= 1'b0;
sd_scb.clock_mode <= 2'd0; sd_scb.clock_mode <= 2'd0;
n64_scb.rom_extended_enabled <= 1'b0;
n64_scb.eeprom_16k_mode <= 1'b0; n64_scb.eeprom_16k_mode <= 1'b0;
n64_scb.eeprom_enabled <= 1'b0; n64_scb.eeprom_enabled <= 1'b0;
n64_scb.dd_enabled <= 1'b0; n64_scb.dd_enabled <= 1'b0;
@ -695,6 +697,7 @@ module mcu_top (
REG_CFG_SCR: begin REG_CFG_SCR: begin
{ {
n64_scb.rom_extended_enabled,
n64_scb.eeprom_16k_mode, n64_scb.eeprom_16k_mode,
n64_scb.eeprom_enabled, n64_scb.eeprom_enabled,
n64_scb.ddipl_enabled, n64_scb.ddipl_enabled,
@ -706,7 +709,7 @@ module mcu_top (
n64_scb.rom_write_enabled, n64_scb.rom_write_enabled,
bootloader_skip, bootloader_skip,
n64_scb.bootloader_enabled n64_scb.bootloader_enabled
} <= reg_wdata[10:0]; } <= reg_wdata[11:0];
end end
REG_CFG_DATA_0: begin REG_CFG_DATA_0: begin

View File

@ -214,10 +214,12 @@ module n64_pi (
end end
end end
if (n64_pi_dq_in >= 16'h1400 && n64_pi_dq_in < 16'h14E0) begin if (n64_scb.rom_extended_enabled) begin
read_port <= PORT_MEM; if (n64_pi_dq_in >= 16'h1400 && n64_pi_dq_in < 16'h14E0) begin
write_port <= PORT_NONE; read_port <= PORT_MEM;
mem_offset <= (-32'h1400_0000) + FLASH_OFFSET; write_port <= PORT_NONE;
mem_offset <= (-32'h1400_0000) + FLASH_OFFSET;
end
end end
if (n64_scb.cfg_unlock) begin if (n64_scb.cfg_unlock) begin

View File

@ -6,6 +6,7 @@ interface n64_scb ();
logic bootloader_enabled; logic bootloader_enabled;
logic rom_write_enabled; logic rom_write_enabled;
logic rom_shadow_enabled; logic rom_shadow_enabled;
logic rom_extended_enabled;
logic sram_enabled; logic sram_enabled;
logic sram_banked; logic sram_banked;
logic flashram_enabled; logic flashram_enabled;
@ -57,6 +58,7 @@ interface n64_scb ();
output bootloader_enabled, output bootloader_enabled,
output rom_write_enabled, output rom_write_enabled,
output rom_shadow_enabled, output rom_shadow_enabled,
output rom_extended_enabled,
output sram_enabled, output sram_enabled,
output sram_banked, output sram_banked,
output flashram_enabled, output flashram_enabled,
@ -94,6 +96,7 @@ interface n64_scb ();
input bootloader_enabled, input bootloader_enabled,
input rom_write_enabled, input rom_write_enabled,
input rom_shadow_enabled, input rom_shadow_enabled,
input rom_extended_enabled,
input sram_enabled, input sram_enabled,
input sram_banked, input sram_banked,
input flashram_enabled, input flashram_enabled,

View File

@ -23,6 +23,7 @@ typedef enum {
CFG_ID_DD_DISK_STATE, CFG_ID_DD_DISK_STATE,
CFG_ID_BUTTON_STATE, CFG_ID_BUTTON_STATE,
CFG_ID_BUTTON_MODE, CFG_ID_BUTTON_MODE,
CFG_ID_ROM_EXTENDED_ENABLE,
} cfg_id_t; } cfg_id_t;
typedef enum { typedef enum {
@ -211,6 +212,9 @@ bool cfg_query (uint32_t *args) {
case CFG_ID_BUTTON_MODE: case CFG_ID_BUTTON_MODE:
args[1] = button_get_mode(); args[1] = button_get_mode();
break; break;
case CFG_ID_ROM_EXTENDED_ENABLE:
args[1] = (scr & CFG_SCR_ROM_EXTENDED_ENABLED);
break;
default: default:
return true; return true;
} }
@ -273,6 +277,9 @@ bool cfg_update (uint32_t *args) {
case CFG_ID_BUTTON_MODE: case CFG_ID_BUTTON_MODE:
button_set_mode(args[1]); button_set_mode(args[1]);
break; break;
case CFG_ID_ROM_EXTENDED_ENABLE:
cfg_change_scr_bits(CFG_SCR_ROM_EXTENDED_ENABLED, args[1]);
break;
default: default:
return true; return true;
} }

View File

@ -56,95 +56,98 @@ typedef enum {
} fpga_reg_t; } fpga_reg_t;
#define FPGA_ID (0x64) #define FPGA_ID (0x64)
#define FPGA_MAX_MEM_TRANSFER (1024) #define FPGA_MAX_MEM_TRANSFER (1024)
#define USB_STATUS_RXNE (1 << 0) #define USB_STATUS_RXNE (1 << 0)
#define USB_STATUS_TXE (1 << 1) #define USB_STATUS_TXE (1 << 1)
#define MEM_SCR_START (1 << 0) #define MEM_SCR_START (1 << 0)
#define MEM_SCR_STOP (1 << 1) #define MEM_SCR_STOP (1 << 1)
#define MEM_SCR_DIRECTION (1 << 2) #define MEM_SCR_DIRECTION (1 << 2)
#define MEM_SCR_BUSY (1 << 3) #define MEM_SCR_BUSY (1 << 3)
#define MEM_SCR_LENGTH_BIT (4) #define MEM_SCR_LENGTH_BIT (4)
#define STATUS_BUTTON (1 << 0) #define STATUS_BUTTON (1 << 0)
#define STATUS_SD_INSERTED (1 << 1) #define STATUS_SD_INSERTED (1 << 1)
#define STATUS_CFG_PENDING (1 << 2) #define STATUS_CFG_PENDING (1 << 2)
#define USB_SCR_FIFO_FLUSH (1 << 0) #define USB_SCR_FIFO_FLUSH (1 << 0)
#define USB_SCR_RXNE (1 << 1) #define USB_SCR_RXNE (1 << 1)
#define USB_SCR_TXE (1 << 2) #define USB_SCR_TXE (1 << 2)
#define USB_SCR_RESET_PENDING (1 << 3) #define USB_SCR_RESET_PENDING (1 << 3)
#define USB_SCR_RESET_ACK (1 << 4) #define USB_SCR_RESET_ACK (1 << 4)
#define USB_SCR_WRITE_FLUSH (1 << 5) #define USB_SCR_WRITE_FLUSH (1 << 5)
#define DMA_SCR_START (1 << 0) #define DMA_SCR_START (1 << 0)
#define DMA_SCR_STOP (1 << 1) #define DMA_SCR_STOP (1 << 1)
#define DMA_SCR_DIRECTION (1 << 2) #define DMA_SCR_DIRECTION (1 << 2)
#define DMA_SCR_BUSY (1 << 3) #define DMA_SCR_BUSY (1 << 3)
#define CFG_SCR_BOOTLOADER_ENABLED (1 << 0) #define CFG_SCR_BOOTLOADER_ENABLED (1 << 0)
#define CFG_SCR_BOOTLOADER_SKIP (1 << 1) #define CFG_SCR_BOOTLOADER_SKIP (1 << 1)
#define CFG_SCR_ROM_WRITE_ENABLED (1 << 2) #define CFG_SCR_ROM_WRITE_ENABLED (1 << 2)
#define CFG_SCR_ROM_SHADOW_ENABLED (1 << 3) #define CFG_SCR_ROM_SHADOW_ENABLED (1 << 3)
#define CFG_SCR_SRAM_ENABLED (1 << 4) #define CFG_SCR_SRAM_ENABLED (1 << 4)
#define CFG_SCR_SRAM_BANKED (1 << 5) #define CFG_SCR_SRAM_BANKED (1 << 5)
#define CFG_SCR_FLASHRAM_ENABLED (1 << 6) #define CFG_SCR_FLASHRAM_ENABLED (1 << 6)
#define CFG_SCR_DD_ENABLED (1 << 7) #define CFG_SCR_DD_ENABLED (1 << 7)
#define CFG_SCR_DDIPL_ENABLED (1 << 8) #define CFG_SCR_DDIPL_ENABLED (1 << 8)
#define CFG_SCR_EEPROM_ENABLED (1 << 9) #define CFG_SCR_EEPROM_ENABLED (1 << 9)
#define CFG_SCR_EEPROM_16K (1 << 10) #define CFG_SCR_EEPROM_16K (1 << 10)
#define CFG_SCR_ROM_EXTENDED_ENABLED (1 << 11)
#define CFG_CMD_DONE (1 << 0) #define CFG_CMD_DONE (1 << 0)
#define CFG_CMD_ERROR (1 << 1) #define CFG_CMD_ERROR (1 << 1)
#define CFG_CMD_IRQ (1 << 2) #define CFG_CMD_IRQ (1 << 2)
#define FLASHRAM_SCR_DONE (1 << 0) #define FLASHRAM_SCR_DONE (1 << 0)
#define FLASHRAM_SCR_PENDING (1 << 1) #define FLASHRAM_SCR_PENDING (1 << 1)
#define FLASHRAM_SCR_PAGE_BIT (2) #define FLASHRAM_SCR_PAGE_BIT (2)
#define FLASHRAM_SCR_PAGE_MASK (0x3FF << FLASHRAM_SCR_PAGE_BIT) #define FLASHRAM_SCR_PAGE_MASK (0x3FF << FLASHRAM_SCR_PAGE_BIT)
#define FLASHRAM_SCR_SECTOR_OR_ALL (1 << 12) #define FLASHRAM_SCR_SECTOR_OR_ALL (1 << 12)
#define FLASHRAM_SCR_WRITE_OR_ERASE (1 << 13) #define FLASHRAM_SCR_WRITE_OR_ERASE (1 << 13)
#define FLASH_SCR_BUSY (1 << 0) #define FLASH_SCR_BUSY (1 << 0)
#define RTC_SCR_PENDING (1 << 0) #define RTC_SCR_PENDING (1 << 0)
#define RTC_SCR_DONE (1 << 1) #define RTC_SCR_DONE (1 << 1)
#define RTC_SCR_MAGIC (0x52544300) #define RTC_SCR_MAGIC (0x52544300)
#define RTC_SCR_MAGIC_MASK (0xFFFFFF00) #define RTC_SCR_MAGIC_MASK (0xFFFFFF00)
#define SD_SCR_CLOCK_MODE_OFF (0 << 0) #define SD_SCR_CLOCK_MODE_OFF (0 << 0)
#define SD_SCR_CLOCK_MODE_400KHZ (1 << 0) #define SD_SCR_CLOCK_MODE_400KHZ (1 << 0)
#define SD_SCR_CLOCK_MODE_25MHZ (2 << 0) #define SD_SCR_CLOCK_MODE_25MHZ (2 << 0)
#define SD_SCR_CLOCK_MODE_50MHZ (3 << 0) #define SD_SCR_CLOCK_MODE_50MHZ (3 << 0)
#define DD_SCR_HARD_RESET (1 << 0) #define DD_SCR_HARD_RESET (1 << 0)
#define DD_SCR_HARD_RESET_CLEAR (1 << 1) #define DD_SCR_HARD_RESET_CLEAR (1 << 1)
#define DD_SCR_CMD_PENDING (1 << 2) #define DD_SCR_CMD_PENDING (1 << 2)
#define DD_SCR_CMD_READY (1 << 3) #define DD_SCR_CMD_READY (1 << 3)
#define DD_SCR_BM_PENDING (1 << 4) #define DD_SCR_BM_PENDING (1 << 4)
#define DD_SCR_BM_READY (1 << 5) #define DD_SCR_BM_READY (1 << 5)
#define DD_SCR_DISK_INSERTED (1 << 6) #define DD_SCR_DISK_INSERTED (1 << 6)
#define DD_SCR_DISK_CHANGED (1 << 7) #define DD_SCR_DISK_CHANGED (1 << 7)
#define DD_SCR_BM_START (1 << 8) #define DD_SCR_BM_START (1 << 8)
#define DD_SCR_BM_START_CLEAR (1 << 9) #define DD_SCR_BM_START_CLEAR (1 << 9)
#define DD_SCR_BM_STOP (1 << 10) #define DD_SCR_BM_STOP (1 << 10)
#define DD_SCR_BM_STOP_CLEAR (1 << 11) #define DD_SCR_BM_STOP_CLEAR (1 << 11)
#define DD_SCR_BM_TRANSFER_MODE (1 << 12) #define DD_SCR_BM_TRANSFER_MODE (1 << 12)
#define DD_SCR_BM_TRANSFER_BLOCKS (1 << 13) #define DD_SCR_BM_TRANSFER_BLOCKS (1 << 13)
#define DD_SCR_BM_TRANSFER_DATA (1 << 14) #define DD_SCR_BM_TRANSFER_DATA (1 << 14)
#define DD_SCR_BM_TRANSFER_C2 (1 << 15) #define DD_SCR_BM_TRANSFER_C2 (1 << 15)
#define DD_SCR_BM_MICRO_ERROR (1 << 16) #define DD_SCR_BM_MICRO_ERROR (1 << 16)
#define DD_SCR_BM_ACK (1 << 17) #define DD_SCR_BM_ACK (1 << 17)
#define DD_SCR_BM_ACK_CLEAR (1 << 18) #define DD_SCR_BM_ACK_CLEAR (1 << 18)
#define DD_SCR_BM_CLEAR (1 << 19) #define DD_SCR_BM_CLEAR (1 << 19)
#define DD_TRACK_MASK (0x0FFF) #define DD_TRACK_MASK (0x0FFF)
#define DD_HEAD_MASK (0x1000) #define DD_HEAD_MASK (0x1000)
#define DD_HEAD_TRACK_MASK (DD_HEAD_MASK | DD_TRACK_MASK) #define DD_HEAD_TRACK_MASK (DD_HEAD_MASK | DD_TRACK_MASK)
#define DD_HEAD_TRACK_INDEX_LOCK (1 << 13) #define DD_HEAD_TRACK_INDEX_LOCK (1 << 13)
#define SWAP32(x) ((x & 0xFF) << 24 | (x & 0xFF00) << 8 | (x & 0xFF0000) >> 8 | (x & 0xFF000000) >> 24)
uint8_t fpga_id_get (void); uint8_t fpga_id_get (void);

View File

@ -4,7 +4,8 @@
#include "usb.h" #include "usb.h"
#define ISV_READ_POINTER_ADDRESS (0x03FF0014) #define ISV_READ_POINTER_ADDRESS (0x03FF0004)
#define ISV_WRITE_POINTER_ADDRESS (0x03FF0014)
#define ISV_BUFFER_ADDRESS (0x03FF0020) #define ISV_BUFFER_ADDRESS (0x03FF0020)
#define ISV_BUFFER_SIZE ((64 * 1024) - 0x20) #define ISV_BUFFER_SIZE ((64 * 1024) - 0x20)
@ -18,24 +19,28 @@ struct process {
static struct process p; static struct process p;
static uint32_t isv_get_read_pointer (void) { static void isv_set_pointer (uint32_t address, uint32_t data) {
uint32_t read_pointer; data = SWAP32(data);
fpga_mem_read(ISV_READ_POINTER_ADDRESS, 4, (uint8_t *) (&read_pointer)); fpga_mem_write(address, 4, (uint8_t *) (&data));
return ( }
(read_pointer & 0x000000FF) << 24 |
(read_pointer & 0x0000FF00) << 8 | static uint32_t isv_get_pointer (uint32_t address) {
(read_pointer & 0x00FF0000) >> 8 | uint32_t data;
(read_pointer & 0xFF000000) >> 24 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);
} }
void isv_set_enabled (bool enabled) { void isv_set_enabled (bool enabled) {
uint32_t read_pointer = 0;
if (enabled) { if (enabled) {
p.enabled = true; p.enabled = true;
p.current_read_pointer = 0; p.current_read_pointer = 0;
fpga_mem_write(ISV_READ_POINTER_ADDRESS, 4, (uint8_t *) (&read_pointer)); isv_set_pointer(ISV_READ_POINTER_ADDRESS, 0);
isv_set_pointer(ISV_WRITE_POINTER_ADDRESS, 0);
} else { } else {
p.enabled = false; p.enabled = false;
} }
@ -51,20 +56,26 @@ void isv_init (void) {
void isv_process (void) { void isv_process (void) {
if (p.enabled) { if (p.enabled) {
uint32_t read_pointer = isv_get_read_pointer(); uint32_t write_pointer = isv_get_pointer(ISV_WRITE_POINTER_ADDRESS);
if (read_pointer < ISV_BUFFER_SIZE && read_pointer != p.current_read_pointer) {
bool wrap = read_pointer < p.current_read_pointer;
uint32_t length = ((wrap ? ISV_BUFFER_SIZE : read_pointer) - p.current_read_pointer); if (p.current_read_pointer == write_pointer) {
uint32_t offset = ISV_BUFFER_ADDRESS + p.current_read_pointer; return;
}
if (write_pointer >= ISV_BUFFER_SIZE) {
return;
}
usb_tx_info_t packet_info; bool wrap = write_pointer < p.current_read_pointer;
usb_create_packet(&packet_info, PACKET_CMD_ISV_OUTPUT); uint32_t length = (wrap ? ISV_BUFFER_SIZE : write_pointer) - p.current_read_pointer;
packet_info.dma_length = length; uint32_t offset = ISV_BUFFER_ADDRESS + p.current_read_pointer;
packet_info.dma_address = offset;
if (usb_enqueue_packet(&packet_info)) { usb_tx_info_t packet_info;
p.current_read_pointer = wrap ? 0 : read_pointer; usb_create_packet(&packet_info, PACKET_CMD_ISV_OUTPUT);
} packet_info.dma_length = length;
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;
} }
} }
} }

View File

@ -199,6 +199,8 @@ class SC64:
FIRMWARE = 0x0200_0000 FIRMWARE = 0x0200_0000
DDIPL = 0x03BC_0000 DDIPL = 0x03BC_0000
SAVE = 0x03FE_0000 SAVE = 0x03FE_0000
EXTENDED = 0x0400_0000
BOOTLOADER = 0x04E0_0000
SHADOW = 0x04FE_0000 SHADOW = 0x04FE_0000
class __Length(IntEnum): class __Length(IntEnum):
@ -208,6 +210,8 @@ class SC64:
EEPROM = (2 * 1024) EEPROM = (2 * 1024)
DDIPL = (4 * 1024 * 1024) DDIPL = (4 * 1024 * 1024)
SAVE = (128 * 1024) SAVE = (128 * 1024)
EXTENDED = (14 * 1024 * 1024)
BOOTLOADER = (1920 * 1024)
SHADOW = (128 * 1024) SHADOW = (128 * 1024)
class __SaveLength(IntEnum): class __SaveLength(IntEnum):
@ -233,6 +237,7 @@ class SC64:
DD_DISK_STATE = 11 DD_DISK_STATE = 11
BUTTON_STATE = 12 BUTTON_STATE = 12
BUTTON_MODE = 13 BUTTON_MODE = 13
ROM_EXTENDED_ENABLE = 14
class __UpdateError(IntEnum): class __UpdateError(IntEnum):
OK = 0 OK = 0
@ -283,7 +288,7 @@ class SC64:
EEPROM_16K = 2 EEPROM_16K = 2
SRAM = 3 SRAM = 3
FLASHRAM = 4 FLASHRAM = 4
SRAM_X3 = 5 SRAM_3X = 5
class CICSeed(IntEnum): class CICSeed(IntEnum):
ALECK = 0xAC ALECK = 0xAC
@ -333,11 +338,20 @@ class SC64:
if ((address + length) > (self.__Address.FLASH + self.__Length.FLASH)): if ((address + length) > (self.__Address.FLASH + self.__Length.FLASH)):
raise ValueError('Flash erase address or length outside of possible range') raise ValueError('Flash erase address or length outside of possible range')
erase_block_size = self.__get_config(self.__CfgId.FLASH_ERASE_BLOCK) erase_block_size = self.__get_config(self.__CfgId.FLASH_ERASE_BLOCK)
if ((address % erase_block_size != 0) or (length % erase_block_size != 0)): if (address % erase_block_size != 0):
raise ValueError('Flash erase address or length not aligned to block size') raise ValueError('Flash erase address not aligned to block size')
for offset in range(address, address + length, erase_block_size): for offset in range(address, address + length, erase_block_size):
self.__set_config(self.__CfgId.FLASH_ERASE_BLOCK, offset) self.__set_config(self.__CfgId.FLASH_ERASE_BLOCK, offset)
def __program_flash(self, address: int, data: bytes):
program_chunk_size = (128 * 1024)
if (self.__read_memory(address, len(data)) != data):
self.__erase_flash_region(address, len(data))
for offset in range(0, len(data), program_chunk_size):
self.__write_memory(address + offset, data[offset:offset + program_chunk_size])
if (self.__read_memory(address, len(data)) != data):
raise ConnectionException('Flash memory program failure')
def reset_state(self) -> None: def reset_state(self) -> None:
self.__set_config(self.__CfgId.ROM_WRITE_ENABLE, False) self.__set_config(self.__CfgId.ROM_WRITE_ENABLE, False)
self.__set_config(self.__CfgId.ROM_SHADOW_ENABLE, False) self.__set_config(self.__CfgId.ROM_SHADOW_ENABLE, False)
@ -350,6 +364,7 @@ class SC64:
self.__set_config(self.__CfgId.DD_DRIVE_TYPE, self.__DDDriveType.RETAIL) self.__set_config(self.__CfgId.DD_DRIVE_TYPE, self.__DDDriveType.RETAIL)
self.__set_config(self.__CfgId.DD_DISK_STATE, self.__DDDiskState.EJECTED) self.__set_config(self.__CfgId.DD_DISK_STATE, self.__DDDiskState.EJECTED)
self.__set_config(self.__CfgId.BUTTON_MODE, self.__ButtonMode.NONE) self.__set_config(self.__CfgId.BUTTON_MODE, self.__ButtonMode.NONE)
self.__set_config(self.__CfgId.ROM_EXTENDED_ENABLE, False)
self.set_cic_parameters() self.set_cic_parameters()
def get_state(self): def get_state(self):
@ -368,24 +383,29 @@ class SC64:
'dd_disk_state': self.__DDDiskState(self.__get_config(self.__CfgId.DD_DISK_STATE)), 'dd_disk_state': self.__DDDiskState(self.__get_config(self.__CfgId.DD_DISK_STATE)),
'button_state': bool(self.__get_config(self.__CfgId.BUTTON_STATE)), 'button_state': bool(self.__get_config(self.__CfgId.BUTTON_STATE)),
'button_mode': self.__ButtonMode(self.__get_config(self.__CfgId.BUTTON_MODE)), 'button_mode': self.__ButtonMode(self.__get_config(self.__CfgId.BUTTON_MODE)),
'rom_extended_enable': bool(self.__get_config(self.__CfgId.ROM_EXTENDED_ENABLE)),
} }
def upload_rom(self, data: bytes, use_shadow: bool=True): def download_memory(self) -> bytes:
return self.__read_memory(self.__Address.SDRAM, self.__Length.SDRAM + self.__Length.FLASH)
def upload_rom(self, data: bytes, use_shadow: bool=True) -> None:
rom_length = len(data) rom_length = len(data)
if (rom_length > self.__Length.SDRAM): if (rom_length > (self.__Length.SDRAM + self.__Length.EXTENDED)):
raise ValueError('ROM size too big') raise ValueError('ROM size too big')
sdram_length = rom_length sdram_length = self.__Length.SDRAM
shadow_enabled = use_shadow and rom_length > (self.__Length.SDRAM - self.__Length.SHADOW) shadow_enabled = use_shadow and rom_length > (self.__Length.SDRAM - self.__Length.SHADOW)
extended_enabled = rom_length > self.__Length.SDRAM
if (shadow_enabled): if (shadow_enabled):
sdram_length = (self.__Length.SDRAM - self.__Length.SHADOW) sdram_length = (self.__Length.SDRAM - self.__Length.SHADOW)
shadow_length = rom_length - sdram_length shadow_data = data[sdram_length:sdram_length + self.__Length.SHADOW]
if (self.__read_memory(self.__Address.SHADOW, shadow_length) != data[sdram_length:]): self.__program_flash(self.__Address.SHADOW, shadow_data)
self.__erase_flash_region(self.__Address.SHADOW, self.__Length.SHADOW)
self.__write_memory(self.__Address.SHADOW, data[sdram_length:])
if (self.__read_memory(self.__Address.SHADOW, shadow_length) != data[sdram_length:]):
raise ConnectionException('Shadow ROM program failure')
self.__write_memory(self.__Address.SDRAM, data[:sdram_length])
self.__set_config(self.__CfgId.ROM_SHADOW_ENABLE, shadow_enabled) self.__set_config(self.__CfgId.ROM_SHADOW_ENABLE, shadow_enabled)
if (extended_enabled):
extended_data = data[self.__Length.SDRAM:]
self.__program_flash(self.__Address.EXTENDED, extended_data)
self.__set_config(self.__CfgId.ROM_EXTENDED_ENABLE, extended_enabled)
self.__write_memory(self.__Address.SDRAM, data[:sdram_length])
def upload_ddipl(self, data: bytes) -> None: def upload_ddipl(self, data: bytes) -> None:
if (len(data) > self.__Length.DDIPL): if (len(data) > self.__Length.DDIPL):
@ -615,8 +635,8 @@ if __name__ == '__main__':
parser.add_argument('--tv', type=SC64.TVType, action=EnumAction, help='force TV type to set value') 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('--cic', type=SC64.CICSeed, action=EnumAction, help='force CIC seed to set value')
parser.add_argument('--rtc', action='store_true', help='update clock in SC64 to system time') parser.add_argument('--rtc', action='store_true', help='update clock in SC64 to system time')
parser.add_argument('--rom', help='upload ROM from specified file')
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)') 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)')
parser.add_argument('--rom', help='upload ROM from specified file')
parser.add_argument('--save-type', type=SC64.SaveType, action=EnumAction, help='set save type') parser.add_argument('--save-type', type=SC64.SaveType, action=EnumAction, help='set save type')
parser.add_argument('--save', help='upload save from specified file') parser.add_argument('--save', help='upload save from specified file')
parser.add_argument('--backup-save', help='download save and write it to specified file') parser.add_argument('--backup-save', help='download save and write it to specified file')
@ -624,6 +644,7 @@ if __name__ == '__main__':
parser.add_argument('--disk', action='append', help='path to 64DD disk (.ndd format), can be specified multiple times') parser.add_argument('--disk', 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', action='store_true', help='enable IS-Viewer64 support')
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', help='download whole memory space and write it to specified file')
if (len(sys.argv) <= 1): if (len(sys.argv) <= 1):
parser.print_help() parser.print_help()
@ -706,6 +727,12 @@ if __name__ == '__main__':
print('Downloading save... ', end='', flush=True) print('Downloading save... ', end='', flush=True)
f.write(sc64.download_save()) f.write(sc64.download_save())
print('done') print('done')
if (args.download_memory):
with open(args.download_memory, 'wb+') as f:
print('Downloading memory... ', end='', flush=True)
f.write(sc64.download_memory())
print('done')
except ValueError as e: except ValueError as e:
print(f'\nValue error: {e}') print(f'\nValue error: {e}')
except ConnectionException as e: except ConnectionException as e: