mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-22 05:59:15 +01:00
isv support + usb/dd improvements
This commit is contained in:
parent
92e5c5747b
commit
4b888d0f71
@ -9,6 +9,7 @@ interface if_n64_bus ();
|
||||
logic [31:0] address;
|
||||
logic [15:0] wdata;
|
||||
logic [15:0] rdata;
|
||||
logic n64_active;
|
||||
logic [31:0] real_address;
|
||||
logic read_op;
|
||||
logic write_op;
|
||||
@ -24,6 +25,10 @@ interface if_n64_bus ();
|
||||
ack = ack | device_ack[i];
|
||||
rdata = rdata | device_rdata[i];
|
||||
end
|
||||
|
||||
if (id >= NUM_DEVICES) begin
|
||||
ack = request;
|
||||
end
|
||||
end
|
||||
|
||||
modport n64 (
|
||||
@ -34,7 +39,7 @@ interface if_n64_bus ();
|
||||
output address,
|
||||
output wdata,
|
||||
input rdata,
|
||||
|
||||
output n64_active,
|
||||
output real_address,
|
||||
output read_op,
|
||||
output write_op
|
||||
@ -44,9 +49,11 @@ interface if_n64_bus ();
|
||||
generate
|
||||
for (n = 0; n < NUM_DEVICES; n++) begin : at
|
||||
logic device_request;
|
||||
logic device_n64_active;
|
||||
|
||||
always_comb begin
|
||||
device_request = request && id == sc64::e_n64_id'(n);
|
||||
device_n64_active = n64_active && id == sc64::e_n64_id'(n);
|
||||
end
|
||||
|
||||
modport device (
|
||||
@ -56,7 +63,7 @@ interface if_n64_bus ();
|
||||
input .address(address),
|
||||
input .wdata(wdata),
|
||||
output .rdata(device_rdata[n]),
|
||||
|
||||
input .n64_active(device_n64_active),
|
||||
input .real_address(real_address),
|
||||
input .read_op(read_op),
|
||||
input .write_op(write_op)
|
||||
|
@ -191,6 +191,7 @@ module n64_pi (
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
bus.n64_active = !pi_reset && pi_mode != PI_MODE_IDLE;
|
||||
bus.read_op = read_op;
|
||||
bus.write_op = write_op;
|
||||
end
|
||||
@ -218,6 +219,7 @@ module n64_pi (
|
||||
always_ff @(posedge sys.clk) begin
|
||||
if (aleh_op) begin
|
||||
n64_pi_address_valid <= 1'b0;
|
||||
next_id <= sc64::__ID_N64_END;
|
||||
next_offset <= 32'd0;
|
||||
sram_selected <= 1'b0;
|
||||
cfg_selected <= 1'b0;
|
||||
|
@ -41,15 +41,17 @@ module n64_sdram (
|
||||
end else begin
|
||||
case (state)
|
||||
S_IDLE: begin
|
||||
if (bus.request || sdram.request || dma.request) begin
|
||||
if (bus.request) begin
|
||||
state <= S_WAIT;
|
||||
mem_request <= 1'b1;
|
||||
if (bus.request) begin
|
||||
mem_write <= bus.write;
|
||||
mem_address <= bus.address;
|
||||
mem_wdata <= bus.wdata;
|
||||
source_request <= T_BUS;
|
||||
end else if (sdram.request) begin
|
||||
end else if ((!bus.n64_active) && (sdram.request || dma.request)) begin
|
||||
state <= S_WAIT;
|
||||
mem_request <= 1'b1;
|
||||
if (sdram.request) begin
|
||||
mem_write <= sdram.write;
|
||||
mem_address <= sdram.address;
|
||||
mem_wdata <= sdram.wdata;
|
||||
|
@ -65,6 +65,11 @@ void main (void) {
|
||||
}
|
||||
}
|
||||
|
||||
if (sc64_info.is_viewer_enabled) {
|
||||
LOG_I("Initializing IS-Viewer 64\r\n");
|
||||
sc64_init_is_viewer();
|
||||
}
|
||||
|
||||
LOG_I("Booting IPL3\033[0m\r\n\r\n");
|
||||
|
||||
boot(&boot_info);
|
||||
|
@ -69,6 +69,7 @@ void sc64_get_info (sc64_info_t *info) {
|
||||
}
|
||||
|
||||
info->dd_enabled = (bool) sc64_get_config(CFG_ID_DD_ENABLE);
|
||||
info->is_viewer_enabled = (bool) sc64_get_config(CFG_ID_IS_VIEWER_ENABLE);
|
||||
info->save_type = (save_type_t) sc64_get_config(CFG_ID_SAVE_TYPE);
|
||||
info->cic_seed = (uint16_t) sc64_get_config(CFG_ID_CIC_SEED);
|
||||
info->tv_type = (tv_type_t) sc64_get_config(CFG_ID_TV_TYPE);
|
||||
@ -196,6 +197,11 @@ void sc64_debug_fsd_write (const void *data, uint32_t sector, uint32_t count) {
|
||||
sc64_debug_write(SC64_DEBUG_ID_FSD_WRITE, data, count * 512);
|
||||
}
|
||||
|
||||
void sc64_init_is_viewer (void) {
|
||||
sc64_set_config(CFG_ID_SDRAM_WRITABLE, true);
|
||||
pi_io_write(&ISV->ID, 0);
|
||||
}
|
||||
|
||||
void sc64_init (void) {
|
||||
while (!sc64_check_presence());
|
||||
sc64_wait_cpu_ready();
|
||||
|
@ -67,6 +67,10 @@ typedef enum {
|
||||
CFG_ID_FLASH_READ,
|
||||
CFG_ID_FLASH_PROGRAM,
|
||||
CFG_ID_RECONFIGURE,
|
||||
CFG_ID_DD_DRIVE_ID,
|
||||
CFG_ID_DD_DISK_STATE,
|
||||
CFG_ID_DD_THB_TABLE_OFFSET,
|
||||
CFG_ID_IS_VIEWER_ENABLE,
|
||||
} cfg_id_t;
|
||||
|
||||
typedef enum {
|
||||
@ -95,6 +99,7 @@ typedef enum {
|
||||
|
||||
typedef struct {
|
||||
bool dd_enabled;
|
||||
bool is_viewer_enabled; // investigate why it breaks when put before bootloader_version
|
||||
save_type_t save_type;
|
||||
uint16_t cic_seed;
|
||||
tv_type_t tv_type;
|
||||
@ -120,6 +125,7 @@ void sc64_usb_tx_data (io32_t *address, uint32_t length);
|
||||
void sc64_debug_write (uint8_t type, const void *data, uint32_t len);
|
||||
void sc64_debug_fsd_read (const void *data, uint32_t sector, uint32_t count);
|
||||
void sc64_debug_fsd_write (const void *data, uint32_t sector, uint32_t count);
|
||||
void sc64_init_is_viewer (void);
|
||||
void sc64_init (void);
|
||||
|
||||
|
||||
|
@ -249,6 +249,18 @@ typedef struct {
|
||||
#define ROM_CART ((io32_t *) ROM_CART_BASE)
|
||||
|
||||
|
||||
typedef struct {
|
||||
io32_t ID;
|
||||
io32_t __padding_1[4];
|
||||
io32_t RD_PTR;
|
||||
io32_t __padding_2[2];
|
||||
io8_t BUFFER[(64 * 1024) - 0x20];
|
||||
} is_viewer_t;
|
||||
|
||||
#define ISV_BASE (0x13FF0000UL)
|
||||
#define ISV ((is_viewer_t *) ISV_BASE)
|
||||
|
||||
|
||||
#define PIFRAM_BASE (0x1FC007C0UL)
|
||||
#define PIFRAM ((io8_t *) PIFRAM_BASE)
|
||||
|
||||
|
105
sw/pc/sc64.py
105
sw/pc/sc64.py
@ -31,8 +31,10 @@ class SC64:
|
||||
__CFG_ID_FLASH_READ = 11
|
||||
__CFG_ID_FLASH_PROGRAM = 12
|
||||
__CFG_ID_RECONFIGURE = 13
|
||||
__CFG_ID_DD_SETTING = 14
|
||||
__CFG_ID_DD_THB_TABLE_OFFSET = 15
|
||||
__CFG_ID_DD_DRIVE_ID = 14
|
||||
__CFG_ID_DD_DISK_STATE = 15
|
||||
__CFG_ID_DD_THB_TABLE_OFFSET = 16
|
||||
__CFG_ID_IS_VIEWER_ENABLE = 17
|
||||
|
||||
__SC64_VERSION_V2 = 0x53437632
|
||||
|
||||
@ -47,14 +49,16 @@ class SC64:
|
||||
__DEBUG_ID_FSD_READ = 0xF1
|
||||
__DEBUG_ID_FSD_WRITE = 0xF2
|
||||
__DEBUG_ID_FSD_SECTOR = 0xF3
|
||||
__DEBUG_ID_DD_BLOCK = 0xF5
|
||||
__DEBUG_ID_INTERNAL = 0xFE
|
||||
__INTERNAL_ID_IS_VIEWER = 0
|
||||
__INTERNAL_ID_DD_BLOCK = 1
|
||||
|
||||
__DD_DRIVE_ID_RETAIL = 3
|
||||
__DD_DRIVE_ID_DEVELOPMENT = 4
|
||||
__DD_DISK_STATE_EJECTED = 0
|
||||
__DD_DISK_STATE_INSERTED = 1
|
||||
__DD_DISK_STATE_CHANGED = 2
|
||||
|
||||
__DD_SETTING_DISK_EJECTED = 0
|
||||
__DD_SETTING_DISK_INSERTED = 1
|
||||
__DD_SETTING_DISK_CHANGED = 2
|
||||
__DD_SETTING_DRIVE_RETAIL = 3
|
||||
__DD_SETTING_DRIVE_DEVELOPMENT = 4
|
||||
__DD_SETTING_SET_BLOCK_READY = 5
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.__serial = None
|
||||
@ -64,6 +68,7 @@ class SC64:
|
||||
self.__fsd_file = None
|
||||
self.__disk_file = None
|
||||
self.__disk_lba_table = []
|
||||
self.__isv_line_buffer = bytearray()
|
||||
self.__find_sc64()
|
||||
|
||||
|
||||
@ -370,13 +375,14 @@ class SC64:
|
||||
self.__write_file_to_sdram(file, dd_ipl_offset, min_length=self.__DDIPL_ROM_LENGTH)
|
||||
|
||||
|
||||
def set_dd_disk_state(self, state: int) -> None:
|
||||
if (state == "ejected"):
|
||||
self.__change_config(self.__CFG_ID_DD_SETTING, self.__DD_SETTING_DISK_EJECTED)
|
||||
elif (state == "inserted"):
|
||||
self.__change_config(self.__CFG_ID_DD_SETTING, self.__DD_SETTING_DISK_INSERTED)
|
||||
elif (state == "changed"):
|
||||
self.__change_config(self.__CFG_ID_DD_SETTING, self.__DD_SETTING_DISK_CHANGED)
|
||||
def set_dd_disk_state(self, state: str) -> None:
|
||||
state_mapping = {
|
||||
"ejected": self.__DD_DISK_STATE_EJECTED,
|
||||
"inserted": self.__DD_DISK_STATE_INSERTED,
|
||||
"changed": self.__DD_DISK_STATE_CHANGED,
|
||||
}
|
||||
if (state in state_mapping):
|
||||
self.__change_config(self.__CFG_ID_DD_DISK_STATE, state_mapping[state])
|
||||
else:
|
||||
raise SC64Exception("DD disk state outside of supported values")
|
||||
|
||||
@ -530,10 +536,14 @@ class SC64:
|
||||
self.__write_cmd("W", thb_table_offset, len(data))
|
||||
self.__write(data)
|
||||
self.__read_cmd_status("W")
|
||||
if (disk_drive_type == "retail"):
|
||||
self.__change_config(self.__CFG_ID_DD_SETTING, self.__DD_SETTING_DRIVE_RETAIL)
|
||||
elif (disk_drive_type == "development"):
|
||||
self.__change_config(self.__CFG_ID_DD_SETTING, self.__DD_SETTING_DRIVE_DEVELOPMENT)
|
||||
id_mapping = {
|
||||
"retail": self.__DD_DRIVE_ID_RETAIL,
|
||||
"development": self.__DD_DRIVE_ID_DEVELOPMENT,
|
||||
}
|
||||
if (disk_drive_type in id_mapping):
|
||||
self.__change_config(self.__CFG_ID_DD_DRIVE_ID, id_mapping[disk_drive_type])
|
||||
else:
|
||||
raise SC64Exception("DD drive type outside of supported values")
|
||||
else:
|
||||
raise SC64Exception("No DD disk file provided for disk info creation")
|
||||
|
||||
@ -557,6 +567,18 @@ class SC64:
|
||||
self.__fsd_file.write(data)
|
||||
|
||||
|
||||
def __debug_process_is_viewer(self, data: bytes) -> None:
|
||||
self.__isv_line_buffer.extend(data)
|
||||
try:
|
||||
while (len(self.__isv_line_buffer) > 0):
|
||||
line_end = self.__isv_line_buffer.index(b'\n')
|
||||
line = self.__isv_line_buffer[:line_end]
|
||||
self.__isv_line_buffer = self.__isv_line_buffer[line_end + 1:]
|
||||
print(line.decode("EUC-JP", errors="backslashreplace"))
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
|
||||
def __debug_process_dd_block(self, data: bytes) -> None:
|
||||
transfer_mode = int.from_bytes(data[0:4], byteorder='big')
|
||||
sdram_offset = int.from_bytes(data[4:8], byteorder='big')
|
||||
@ -568,26 +590,39 @@ class SC64:
|
||||
if (self.__disk_file):
|
||||
self.__disk_file.seek(disk_file_offset)
|
||||
if (transfer_mode):
|
||||
self.__write_cmd("W", sdram_offset, block_length)
|
||||
time.sleep(0.01) # Fixes weird bug in Mario Artist Paint Studio minigame
|
||||
self.__write_cmd("S", sdram_offset, block_length)
|
||||
self.__write(self.__disk_file.read(block_length))
|
||||
self.__read_cmd_status("W")
|
||||
else:
|
||||
self.__write_cmd("R", sdram_offset, block_length)
|
||||
self.__disk_file.write(self.__read_long(block_length))
|
||||
self.__read_cmd_status("R")
|
||||
|
||||
self.__change_config(self.__CFG_ID_DD_SETTING, self.__DD_SETTING_SET_BLOCK_READY)
|
||||
write_data = data[16:]
|
||||
self.__disk_file.write(write_data)
|
||||
|
||||
|
||||
def debug_loop(self, fsd_file: str = None, disk_file: str = None) -> None:
|
||||
print("\r\n\033[34m --- Debug server started --- \033[0m\r\n")
|
||||
def __debug_process_internal(self, internal_data: bytes) -> None:
|
||||
id = internal_data[0]
|
||||
start_alignmnet = internal_data[1]
|
||||
length = int.from_bytes(internal_data[2:4], byteorder="big")
|
||||
data = internal_data[(4 + start_alignmnet):][:length]
|
||||
|
||||
if (id == self.__INTERNAL_ID_IS_VIEWER):
|
||||
self.__debug_process_is_viewer(data)
|
||||
elif (id == self.__INTERNAL_ID_DD_BLOCK):
|
||||
self.__debug_process_dd_block(data)
|
||||
|
||||
|
||||
def debug_init(self, fsd_file: str = None, disk_file: str = None, is_viewer_enabled: bool = False) -> None:
|
||||
if (fsd_file):
|
||||
self.__fsd_file = open(fsd_file, "rb+")
|
||||
|
||||
if (disk_file):
|
||||
self.__disk_file = open(disk_file, "rb+")
|
||||
|
||||
self.__change_config(self.__CFG_ID_IS_VIEWER_ENABLE, is_viewer_enabled)
|
||||
|
||||
|
||||
def debug_loop(self) -> None:
|
||||
print("\r\n\033[34m --- Debug server started --- \033[0m\r\n")
|
||||
|
||||
start_indicator = bytearray()
|
||||
dropped_bytes = 0
|
||||
|
||||
@ -621,8 +656,8 @@ class SC64:
|
||||
self.__debug_process_fsd_write(data)
|
||||
elif (id == self.__DEBUG_ID_FSD_SECTOR):
|
||||
self.__debug_process_fsd_set_sector(data)
|
||||
elif (id == self.__DEBUG_ID_DD_BLOCK):
|
||||
self.__debug_process_dd_block(data)
|
||||
elif (id == self.__DEBUG_ID_INTERNAL):
|
||||
self.__debug_process_internal(data)
|
||||
else:
|
||||
print(f"\033[35mGot unknown id: {id}, length: {length}\033[0m", file=sys.stderr)
|
||||
|
||||
@ -698,6 +733,7 @@ if __name__ == "__main__":
|
||||
parser.add_argument("-e", metavar="save_path", default=None, required=False, help="path to save file")
|
||||
parser.add_argument("-i", metavar="ddipl_path", default=None, required=False, help="path to DDIPL file")
|
||||
parser.add_argument("-q", default=None, action="store_true", required=False, help="start debug server")
|
||||
parser.add_argument("-v", default=False, action="store_true", required=False, help="enable IS-Viewer64 support")
|
||||
parser.add_argument("-f", metavar="sd_path", default=None, required=False, help="path to disk or file for fake SD card emulation")
|
||||
parser.add_argument("-k", metavar="disk_path", default=None, required=False, help="path to 64DD disk file")
|
||||
parser.add_argument("rom", metavar="rom_path", default=None, help="path to ROM file", nargs="?")
|
||||
@ -723,6 +759,7 @@ if __name__ == "__main__":
|
||||
dd_ipl_file = args.i
|
||||
rom_file = args.rom
|
||||
debug_server = args.q
|
||||
is_viewer_enabled = args.v
|
||||
sd_file = args.f
|
||||
disk_file = args.k
|
||||
|
||||
@ -789,10 +826,12 @@ if __name__ == "__main__":
|
||||
if (disk_file):
|
||||
print(f"Using 64DD disk image file [{disk_file}]")
|
||||
sc64.set_dd_configuration_for_disk(disk_file)
|
||||
if (disk_file):
|
||||
print(f"Setting 64DD disk state to [Changed]")
|
||||
sc64.set_dd_disk_state("changed" if disk_file else "ejected")
|
||||
sc64.debug_loop(sd_file, disk_file)
|
||||
if (is_viewer_enabled):
|
||||
print(f"Setting IS-Viewer64 emulation to [Enabled]")
|
||||
sc64.debug_init(sd_file, disk_file, is_viewer_enabled)
|
||||
sc64.debug_loop(is_viewer_enabled)
|
||||
|
||||
except SC64Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
@ -12,7 +12,20 @@ LDFLAGS = -nostartfiles -Wl,--gc-sections
|
||||
SRC_DIR = src
|
||||
BUILD_DIR = build
|
||||
|
||||
SRC_FILES = startup.S process.c usb.c cfg.c dma.c joybus.c rtc.c i2c.c flashram.c uart.c flash.c dd.c
|
||||
SRC_FILES = \
|
||||
startup.S \
|
||||
process.c \
|
||||
usb.c \
|
||||
cfg.c \
|
||||
dma.c \
|
||||
joybus.c \
|
||||
rtc.c \
|
||||
i2c.c \
|
||||
flashram.c \
|
||||
uart.c \
|
||||
flash.c \
|
||||
dd.c \
|
||||
isv.c
|
||||
|
||||
SRCS = $(addprefix $(SRC_DIR)/, $(SRC_FILES))
|
||||
OBJS = $(addprefix $(BUILD_DIR)/, $(notdir $(patsubst %,%.o,$(SRCS))))
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "cfg.h"
|
||||
#include "dd.h"
|
||||
#include "flash.h"
|
||||
#include "isv.h"
|
||||
#include "joybus.h"
|
||||
#include "usb.h"
|
||||
|
||||
@ -32,8 +33,10 @@ enum cfg_id {
|
||||
CFG_ID_FLASH_READ,
|
||||
CFG_ID_FLASH_PROGRAM,
|
||||
CFG_ID_RECONFIGURE,
|
||||
CFG_ID_DD_SETTING,
|
||||
CFG_ID_DD_DRIVE_ID,
|
||||
CFG_ID_DD_DISK_STATE,
|
||||
CFG_ID_DD_THB_TABLE_OFFSET,
|
||||
CFG_ID_IS_VIEWER_ENABLE,
|
||||
};
|
||||
|
||||
enum save_type {
|
||||
@ -53,15 +56,6 @@ enum boot_mode {
|
||||
BOOT_MODE_DIRECT = 3,
|
||||
};
|
||||
|
||||
enum dd_setting {
|
||||
DD_SETTING_DISK_EJECTED = 0,
|
||||
DD_SETTING_DISK_INSERTED = 1,
|
||||
DD_SETTING_DISK_CHANGED = 2,
|
||||
DD_SETTING_DRIVE_RETAIL = 3,
|
||||
DD_SETTING_DRIVE_DEVELOPMENT = 4,
|
||||
DD_SETTING_SET_BLOCK_READY = 5,
|
||||
};
|
||||
|
||||
|
||||
struct process {
|
||||
enum save_type save_type;
|
||||
@ -124,29 +118,6 @@ static void set_save_type (enum save_type save_type) {
|
||||
CFG->SAVE_OFFSET = save_offset;
|
||||
}
|
||||
|
||||
static void set_dd_setting (enum dd_setting setting) {
|
||||
switch (setting) {
|
||||
case DD_SETTING_DISK_EJECTED:
|
||||
dd_set_disk_state(DD_DISK_EJECTED);
|
||||
break;
|
||||
case DD_SETTING_DISK_INSERTED:
|
||||
dd_set_disk_state(DD_DISK_INSERTED);
|
||||
break;
|
||||
case DD_SETTING_DISK_CHANGED:
|
||||
dd_set_disk_state(DD_DISK_CHANGED);
|
||||
break;
|
||||
case DD_SETTING_DRIVE_RETAIL:
|
||||
dd_set_drive_type_development(false);
|
||||
break;
|
||||
case DD_SETTING_DRIVE_DEVELOPMENT:
|
||||
dd_set_drive_type_development(true);
|
||||
break;
|
||||
case DD_SETTING_SET_BLOCK_READY:
|
||||
dd_set_block_ready(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t cfg_get_version (void) {
|
||||
return CFG->VERSION;
|
||||
@ -199,8 +170,17 @@ void cfg_update (uint32_t *args) {
|
||||
);
|
||||
}
|
||||
break;
|
||||
case CFG_ID_DD_SETTING:
|
||||
set_dd_setting(args[1]);
|
||||
case CFG_ID_DD_DISK_STATE:
|
||||
dd_set_disk_state(args[1]);
|
||||
break;
|
||||
case CFG_ID_DD_DRIVE_ID:
|
||||
dd_set_drive_id((uint16_t) (args[1]));
|
||||
break;
|
||||
case CFG_ID_DD_THB_TABLE_OFFSET:
|
||||
dd_set_thb_table_offset(args[1]);
|
||||
break;
|
||||
case CFG_ID_IS_VIEWER_ENABLE:
|
||||
isv_set_enabled(args[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -243,9 +223,18 @@ void cfg_query (uint32_t *args) {
|
||||
case CFG_ID_RECONFIGURE:
|
||||
args[1] = CFG->RECONFIGURE;
|
||||
break;
|
||||
case CFG_ID_DD_DISK_STATE:
|
||||
args[1] = dd_get_disk_state();
|
||||
break;
|
||||
case CFG_ID_DD_DRIVE_ID:
|
||||
args[1] = dd_get_drive_id();
|
||||
break;
|
||||
case CFG_ID_DD_THB_TABLE_OFFSET:
|
||||
args[1] = dd_get_thb_table_offset();
|
||||
break;
|
||||
case CFG_ID_IS_VIEWER_ENABLE:
|
||||
args[1] = isv_get_enabled();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
#define DD_BUFFERS_OFFSET (SDRAM_BASE + 0x03BD0000UL)
|
||||
#define DD_THB_TABLE_OFFSET (DD_BUFFERS_OFFSET + 0x0000)
|
||||
#define DD_USB_BUFFER_OFFSET (DD_BUFFERS_OFFSET + 0x5000)
|
||||
#define DD_BLOCK_BUFFER_OFFSET (DD_BUFFERS_OFFSET + 0x6000)
|
||||
#define DD_BLOCK_BUFFER_OFFSET (DD_USB_BUFFER_OFFSET + 0x10)
|
||||
|
||||
#define USB_DEBUG_ID_DD_BLOCK (0xF5)
|
||||
|
||||
@ -62,10 +62,8 @@ struct process {
|
||||
bool full_track_transfer;
|
||||
bool starting_block;
|
||||
uint8_t current_sector;
|
||||
bool is_dev_disk;
|
||||
rtc_time_t time;
|
||||
io32_t *thb_table;
|
||||
io32_t *usb_buffer;
|
||||
io32_t *block_buffer;
|
||||
bool block_ready;
|
||||
};
|
||||
@ -87,7 +85,7 @@ static bool dd_block_valid (void) {
|
||||
}
|
||||
|
||||
static bool dd_block_request (void) {
|
||||
if (!usb_debug_tx_ready()) {
|
||||
if (!usb_internal_debug_tx_ready()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -95,23 +93,22 @@ static bool dd_block_request (void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *dma = "DMA@";
|
||||
const char *cmp = "CMPH";
|
||||
|
||||
io32_t offset = p.thb_table[dd_track_head_block()];
|
||||
uint32_t length = ((DD->SECTOR_SIZE + 1) * DD_USER_SECTORS_PER_BLOCK);
|
||||
size_t transfer_length = 16;
|
||||
|
||||
io32_t *dst = p.usb_buffer;
|
||||
io32_t *dst = (io32_t *) (DD_USB_BUFFER_OFFSET);
|
||||
|
||||
*dst++ = *((uint32_t *) (dma));
|
||||
*dst++ = swap32((USB_DEBUG_ID_DD_BLOCK << 24) | 16);
|
||||
*dst++ = swap32(p.transfer_mode);
|
||||
*dst++ = swap32((uint32_t) (p.block_buffer));
|
||||
*dst++ = SWAP32(p.transfer_mode);
|
||||
*dst++ = SWAP32((uint32_t) (p.block_buffer));
|
||||
*dst++ = offset;
|
||||
*dst++ = swap32(length);
|
||||
*dst++ = *((uint32_t *) (cmp));
|
||||
*dst++ = SWAP32(length);
|
||||
|
||||
usb_debug_tx_data((uint32_t) (p.usb_buffer), 28);
|
||||
if (!p.transfer_mode) {
|
||||
transfer_length += length;
|
||||
}
|
||||
|
||||
usb_internal_debug_tx_data(INT_DBG_ID_DD_BLOCK, DD_USB_BUFFER_OFFSET, transfer_length);
|
||||
|
||||
p.block_ready = false;
|
||||
|
||||
@ -119,7 +116,15 @@ static bool dd_block_request (void) {
|
||||
}
|
||||
|
||||
static bool dd_block_ready (void) {
|
||||
return p.block_ready || (!(DD->SCR & DD_SCR_DISK_INSERTED));
|
||||
if (!(DD->SCR & DD_SCR_DISK_INSERTED)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (p.transfer_mode) {
|
||||
return p.block_ready;
|
||||
} else {
|
||||
return usb_internal_debug_tx_ready();
|
||||
}
|
||||
}
|
||||
|
||||
static void dd_sector_read (void) {
|
||||
@ -166,20 +171,34 @@ void dd_set_disk_state (disk_state_t disk_state) {
|
||||
DD->SCR = scr;
|
||||
}
|
||||
|
||||
void dd_set_drive_type_development (bool value) {
|
||||
if (value) {
|
||||
DD->DRIVE_ID = DD_DRIVE_ID_DEVELOPMENT;
|
||||
p.is_dev_disk = true;
|
||||
disk_state_t dd_get_disk_state (void) {
|
||||
uint32_t scr = (DD->SCR & (DD_SCR_DISK_CHANGED | DD_SCR_DISK_INSERTED));
|
||||
|
||||
if (scr == (DD_SCR_DISK_CHANGED | DD_SCR_DISK_INSERTED)) {
|
||||
return DD_DISK_CHANGED;
|
||||
} else if (scr == DD_SCR_DISK_INSERTED) {
|
||||
return DD_DISK_INSERTED;
|
||||
} else {
|
||||
DD->DRIVE_ID = DD_DRIVE_ID_RETAIL;
|
||||
p.is_dev_disk = false;
|
||||
return DD_DISK_EJECTED;
|
||||
}
|
||||
}
|
||||
|
||||
void dd_set_drive_id (uint16_t id) {
|
||||
DD->DRIVE_ID = id;
|
||||
}
|
||||
|
||||
uint16_t dd_get_drive_id (void) {
|
||||
return DD->DRIVE_ID;
|
||||
}
|
||||
|
||||
void dd_set_block_ready (bool value) {
|
||||
p.block_ready = value;
|
||||
}
|
||||
|
||||
void dd_set_thb_table_offset (uint32_t offset) {
|
||||
p.thb_table = (io32_t *) (SDRAM_BASE + offset);
|
||||
}
|
||||
|
||||
uint32_t dd_get_thb_table_offset (void) {
|
||||
return (((uint32_t) (p.thb_table)) & 0x0FFFFFFF);
|
||||
}
|
||||
@ -194,9 +213,7 @@ void dd_init (void) {
|
||||
p.power_up_delay = true;
|
||||
p.deffered_cmd_ready = false;
|
||||
p.bm_running = false;
|
||||
p.is_dev_disk = false;
|
||||
p.thb_table = (io32_t *) (DD_THB_TABLE_OFFSET);
|
||||
p.usb_buffer = (io32_t *) (DD_USB_BUFFER_OFFSET);
|
||||
p.block_buffer = (io32_t *) (DD_BLOCK_BUFFER_OFFSET);
|
||||
}
|
||||
|
||||
|
@ -13,9 +13,12 @@ typedef enum {
|
||||
|
||||
|
||||
void dd_set_disk_state (disk_state_t disk_state);
|
||||
void dd_set_drive_type_development (bool value);
|
||||
void dd_set_block_ready (bool value);
|
||||
disk_state_t dd_get_disk_state (void);
|
||||
void dd_set_drive_id (uint16_t id);
|
||||
uint16_t dd_get_drive_id (void);
|
||||
void dd_set_thb_table_offset (uint32_t offset);
|
||||
uint32_t dd_get_thb_table_offset (void);
|
||||
void dd_set_block_ready (bool value);
|
||||
void dd_init (void);
|
||||
void process_dd (void);
|
||||
|
||||
|
60
sw/riscv/src/isv.c
Normal file
60
sw/riscv/src/isv.c
Normal file
@ -0,0 +1,60 @@
|
||||
#include "isv.h"
|
||||
#include "usb.h"
|
||||
|
||||
|
||||
#define IS64_TOKEN (0x34365349)
|
||||
#define IS64_OFFSET (SDRAM_BASE + 0x03FF0000)
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t ID;
|
||||
uint32_t __padding_1[4];
|
||||
uint32_t RD_PTR;
|
||||
uint32_t __padding_2[2];
|
||||
uint8_t BUFFER[(64 * 1024) - 0x20];
|
||||
} is_viewer_t;
|
||||
|
||||
|
||||
struct process {
|
||||
bool enabled;
|
||||
uint32_t current_read_pointer;
|
||||
is_viewer_t *ISV;
|
||||
};
|
||||
|
||||
struct process p;
|
||||
|
||||
|
||||
void isv_set_enabled (bool enabled) {
|
||||
p.enabled = enabled;
|
||||
}
|
||||
|
||||
bool isv_get_enabled (void) {
|
||||
return p.enabled;
|
||||
}
|
||||
|
||||
|
||||
void isv_init (void) {
|
||||
p.enabled = false;
|
||||
p.current_read_pointer = 0;
|
||||
p.ISV = (is_viewer_t *) (IS64_OFFSET);
|
||||
}
|
||||
|
||||
void process_isv (void) {
|
||||
if (!p.enabled || (p.ISV->ID != IS64_TOKEN)) {
|
||||
p.current_read_pointer = 0;
|
||||
p.ISV->RD_PTR = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t read_pointer = SWAP32(p.ISV->RD_PTR);
|
||||
|
||||
if ((read_pointer != p.current_read_pointer) && usb_internal_debug_tx_ready()) {
|
||||
bool wrap = read_pointer < p.current_read_pointer;
|
||||
size_t length = ((wrap ? sizeof(p.ISV->BUFFER) : read_pointer) - p.current_read_pointer);
|
||||
uint32_t address = (uint32_t) (&p.ISV->BUFFER[p.current_read_pointer]);
|
||||
|
||||
if (usb_internal_debug_tx_data(INT_DBG_ID_IS_VIEWER, address, length)) {
|
||||
p.current_read_pointer = wrap ? 0 : read_pointer;
|
||||
}
|
||||
}
|
||||
}
|
14
sw/riscv/src/isv.h
Normal file
14
sw/riscv/src/isv.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef ISV_H__
|
||||
#define ISV_H__
|
||||
|
||||
|
||||
#include "sys.h"
|
||||
|
||||
|
||||
void isv_set_enabled (bool enabled);
|
||||
bool isv_get_enabled (void);
|
||||
void isv_init (void);
|
||||
void process_isv (void);
|
||||
|
||||
|
||||
#endif
|
@ -8,6 +8,7 @@
|
||||
#include "flashram.h"
|
||||
#include "dd.h"
|
||||
#include "uart.h"
|
||||
#include "isv.h"
|
||||
|
||||
|
||||
static const void (*process_table[])(void) = {
|
||||
@ -18,6 +19,7 @@ static const void (*process_table[])(void) = {
|
||||
process_flashram,
|
||||
process_dd,
|
||||
process_uart,
|
||||
process_isv,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@ -34,6 +36,7 @@ __attribute__((naked)) void process_loop (void) {
|
||||
flashram_init();
|
||||
dd_init();
|
||||
uart_init();
|
||||
isv_init();
|
||||
|
||||
while (1) {
|
||||
process_joybus();
|
||||
|
@ -8,11 +8,14 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
#define swap32(x) ((((x) & 0xFF000000UL) >> 24) | \
|
||||
#define SWAP32(x) ((((x) & 0xFF000000UL) >> 24) | \
|
||||
(((x) & 0x00FF0000UL) >> 8) | \
|
||||
(((x) & 0x0000FF00UL) << 8) | \
|
||||
(((x) & 0x000000FFUL) << 24))
|
||||
|
||||
#define ALIGN(value, align) (((value) + ((typeof(value))(align) - 1)) & ~((typeof(value))(align) - 1))
|
||||
|
||||
|
||||
typedef volatile uint8_t io8_t;
|
||||
typedef volatile uint16_t io16_t;
|
||||
typedef volatile uint32_t io32_t;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "usb.h"
|
||||
#include "dma.h"
|
||||
#include "cfg.h"
|
||||
#include "dd.h"
|
||||
|
||||
|
||||
static bool rx_byte (uint8_t *data) {
|
||||
@ -62,14 +63,20 @@ static bool tx_word (uint32_t data) {
|
||||
|
||||
#define USB_CMD_TOKEN (0x434D4400)
|
||||
#define USB_CMP_TOKEN (0x434D5000)
|
||||
#define USB_DMA_TOKEN (0x444D4100)
|
||||
#define USB_ERR_TOKEN (0x45525200)
|
||||
|
||||
#define DEBUG_ID_INTERNAL (0xFE)
|
||||
|
||||
enum state {
|
||||
STATE_IDLE,
|
||||
STATE_ARGS,
|
||||
STATE_DATA,
|
||||
STATE_RESPONSE,
|
||||
STATE_DEBUG_TX,
|
||||
STATE_INTERNAL_DEBUG_TX_START,
|
||||
STATE_INTERNAL_DEBUG_TX_DATA,
|
||||
STATE_INTERNAL_DEBUG_TX_END,
|
||||
};
|
||||
|
||||
struct process {
|
||||
@ -88,6 +95,13 @@ struct process {
|
||||
bool debug_tx_busy;
|
||||
uint32_t debug_tx_address;
|
||||
size_t debug_tx_length;
|
||||
|
||||
bool internal_debug_tx_busy;
|
||||
uint8_t internal_debug_tx_step;
|
||||
uint32_t internal_debug_tx_address;
|
||||
size_t internal_debug_tx_length;
|
||||
uint32_t internal_debug_tx_id_length;
|
||||
uint32_t internal_debug_tx_info;
|
||||
};
|
||||
|
||||
static struct process p;
|
||||
@ -154,6 +168,30 @@ void usb_debug_reset (void) {
|
||||
USB->SCR = USB_SCR_ENABLED | USB_SCR_FLUSH_TX | USB_SCR_FLUSH_RX;
|
||||
}
|
||||
|
||||
bool usb_internal_debug_tx_ready (void) {
|
||||
return !p.internal_debug_tx_busy;
|
||||
}
|
||||
|
||||
bool usb_internal_debug_tx_data (internal_debug_id_t id, uint32_t address, size_t length) {
|
||||
if (p.internal_debug_tx_busy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t start_address = address & 0xFFFFFFFC;
|
||||
uint32_t end_address = ALIGN((address + length), 4);
|
||||
size_t dma_length = end_address - start_address;
|
||||
uint8_t start_alignment = address & 0x03;
|
||||
|
||||
p.internal_debug_tx_busy = true;
|
||||
p.internal_debug_tx_address = start_address;
|
||||
p.internal_debug_tx_length = dma_length;
|
||||
p.internal_debug_tx_id_length = ((DEBUG_ID_INTERNAL << 24) | (dma_length + 4));
|
||||
p.internal_debug_tx_info = ((id << 24) | (start_alignment << 16) | (length & 0xFFFF));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t rx_cmd_current_byte = 0;
|
||||
static uint32_t rx_cmd_buffer = 0;
|
||||
|
||||
@ -201,6 +239,7 @@ void usb_init (void) {
|
||||
p.state = STATE_IDLE;
|
||||
p.debug_rx_busy = false;
|
||||
p.debug_tx_busy = false;
|
||||
p.internal_debug_tx_busy = false;
|
||||
|
||||
rx_word_current_byte = 0;
|
||||
rx_word_buffer = 0;
|
||||
@ -215,10 +254,7 @@ void process_usb (void) {
|
||||
|
||||
switch (p.state) {
|
||||
case STATE_IDLE:
|
||||
if (p.debug_tx_busy) {
|
||||
p.state = STATE_DEBUG_TX;
|
||||
p.dma_in_progress = false;
|
||||
} else if (rx_cmd(&p.args[0])) {
|
||||
if (rx_cmd(&p.args[0])) {
|
||||
if ((p.args[0] & 0xFFFFFF00) == USB_CMD_TOKEN) {
|
||||
p.cmd = p.args[0] & 0xFF;
|
||||
p.counter = 0;
|
||||
@ -231,6 +267,13 @@ void process_usb (void) {
|
||||
p.error = true;
|
||||
p.state = STATE_RESPONSE;
|
||||
}
|
||||
} else if (p.debug_tx_busy) {
|
||||
p.state = STATE_DEBUG_TX;
|
||||
p.dma_in_progress = false;
|
||||
} else if (p.internal_debug_tx_busy) {
|
||||
p.state = STATE_INTERNAL_DEBUG_TX_START;
|
||||
p.dma_in_progress = false;
|
||||
p.internal_debug_tx_step = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -268,15 +311,22 @@ void process_usb (void) {
|
||||
|
||||
case 'R':
|
||||
case 'W':
|
||||
case 'S':
|
||||
if (!dma_busy()) {
|
||||
if (!p.dma_in_progress) {
|
||||
enum dma_dir dir = p.cmd == 'W' ? DMA_DIR_TO_SDRAM : DMA_DIR_FROM_SDRAM;
|
||||
bool is_write = (p.cmd == 'W') || (p.cmd == 'S');
|
||||
enum dma_dir dir = is_write ? DMA_DIR_TO_SDRAM : DMA_DIR_FROM_SDRAM;
|
||||
dma_start(p.args[0], p.args[1], DMA_ID_USB, dir);
|
||||
p.dma_in_progress = true;
|
||||
} else {
|
||||
if (p.cmd == 'S') {
|
||||
dd_set_block_ready(true);
|
||||
p.state = STATE_IDLE;
|
||||
} else {
|
||||
p.state = STATE_RESPONSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
@ -319,5 +369,39 @@ void process_usb (void) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_INTERNAL_DEBUG_TX_START:
|
||||
uint32_t header_data[] = {
|
||||
(USB_DMA_TOKEN | '@'),
|
||||
p.internal_debug_tx_id_length,
|
||||
p.internal_debug_tx_info,
|
||||
};
|
||||
|
||||
if (tx_word(header_data[p.internal_debug_tx_step])) {
|
||||
p.internal_debug_tx_step += 1;
|
||||
if (p.internal_debug_tx_step >= 3) {
|
||||
p.state = STATE_INTERNAL_DEBUG_TX_DATA;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_INTERNAL_DEBUG_TX_DATA:
|
||||
if (!dma_busy()) {
|
||||
if (!p.dma_in_progress) {
|
||||
dma_start(p.internal_debug_tx_address, p.internal_debug_tx_length, DMA_ID_USB, DMA_DIR_FROM_SDRAM);
|
||||
p.dma_in_progress = true;
|
||||
} else {
|
||||
p.internal_debug_tx_busy = false;
|
||||
p.state = STATE_INTERNAL_DEBUG_TX_END;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_INTERNAL_DEBUG_TX_END:
|
||||
if (tx_word(USB_CMP_TOKEN | 'H')) {
|
||||
p.state = STATE_IDLE;
|
||||
}
|
||||
p.state = STATE_IDLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -5,12 +5,20 @@
|
||||
#include "sys.h"
|
||||
|
||||
|
||||
typedef enum {
|
||||
INT_DBG_ID_IS_VIEWER = 0,
|
||||
INT_DBG_ID_DD_BLOCK = 1,
|
||||
} internal_debug_id_t;
|
||||
|
||||
|
||||
bool usb_debug_rx_ready (uint32_t *type, size_t *length);
|
||||
bool usb_debug_rx_busy (void);
|
||||
bool usb_debug_rx_data (uint32_t address, size_t length);
|
||||
bool usb_debug_tx_ready (void);
|
||||
bool usb_debug_tx_data (uint32_t address, size_t length);
|
||||
void usb_debug_reset (void);
|
||||
bool usb_internal_debug_tx_ready (void);
|
||||
bool usb_internal_debug_tx_data (internal_debug_id_t id, uint32_t address, size_t length);
|
||||
void usb_init (void);
|
||||
void process_usb (void);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user