diff --git a/sw/n64/src/main.c b/sw/n64/src/main.c index 520572f..cc429a9 100644 --- a/sw/n64/src/main.c +++ b/sw/n64/src/main.c @@ -65,7 +65,7 @@ void main (void) { } } - LOG_I("Booting IPL3\r\n\r\n"); + LOG_I("Booting IPL3\033[0m\r\n\r\n"); boot(&boot_info); } diff --git a/sw/pc/sc64.py b/sw/pc/sc64.py index 08a4b28..ad84222 100644 --- a/sw/pc/sc64.py +++ b/sw/pc/sc64.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 +from io import TextIOWrapper from serial import Serial, SerialException from serial.tools import list_ports import argparse @@ -7,6 +8,7 @@ import filecmp import os import progressbar import re +import struct import sys import time @@ -18,9 +20,6 @@ class SC64Exception(Exception): class SC64: - __CFG_ID_SCR = 0 - __CFG_ID_SDRAM_SWITCH = 1 - __CFG_ID_SDRAM_WRITABLE = 2 __CFG_ID_DD_ENABLE = 3 __CFG_ID_SAVE_TYPE = 4 __CFG_ID_CIC_SEED = 5 @@ -33,6 +32,7 @@ class SC64: __CFG_ID_FLASH_PROGRAM = 12 __CFG_ID_RECONFIGURE = 13 __CFG_ID_DD_SETTING = 14 + __CFG_ID_DD_THB_TABLE_OFFSET = 15 __SC64_VERSION_V2 = 0x53437632 @@ -49,13 +49,12 @@ class SC64: __DEBUG_ID_FSD_SECTOR = 0xF3 __DEBUG_ID_DD_BLOCK = 0xF5 - __DD_USER_SECTORS_IN_BLOCK = 85 - __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 @@ -97,8 +96,11 @@ class SC64: return re.sub(b"\x1B", b"\x1B\x1B", data) - def __reset_link(self) -> None: + def reset_link(self) -> None: self.__serial.write(b"\x1BR") + while (self.__serial.in_waiting): + self.__serial.read_all() + time.sleep(0.1) def __read(self, bytes: int) -> bytes: @@ -151,10 +153,7 @@ class SC64: try: self.__serial = Serial(p.device, timeout=1.0, write_timeout=1.0) self.__serial.flushOutput() - self.__reset_link() - while (self.__serial.in_waiting): - self.__serial.read_all() - time.sleep(0.1) + self.reset_link() self.__probe_device() except (SerialException, SC64Exception): if (self.__serial): @@ -390,6 +389,153 @@ class SC64: raise SC64Exception("DD drive type outside of supported values") + def __dd_process_disk(self, handle: TextIOWrapper) -> tuple[str, bytes]: + DISK_TRACKS = 1175 + DISK_HEADS = 2 + DISK_BLOCKS_PER_TRACK = 2 + DISK_SECTORS_PER_BLOCK = 85 + DISK_SYSTEM_SECTOR_SIZE = 232 + + DISK_PZONES = [ + (0, 0, 158, 232, 0, 0), + (1, 0, 158, 216, 158, 1), + (2, 0, 149, 208, 316, 2), + (3, 0, 149, 192, 465, 3), + (4, 0, 149, 176, 614, 4), + (5, 0, 149, 160, 763, 5), + (6, 0, 149, 144, 912, 6), + (7, 0, 114, 128, 1061, 7), + (1, 1, 158, 216, 157, 8), + (2, 1, 158, 208, 315, 9), + (3, 1, 149, 192, 464, 10), + (4, 1, 149, 176, 613, 11), + (5, 1, 149, 160, 762, 12), + (6, 1, 149, 144, 911, 13), + (7, 1, 149, 128, 1060, 14), + (8, 1, 114, 112, 1174, 15), + ] + + DISK_VZONE_TO_PZONE = [ + [0, 1, 2, 9, 8, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10], + [0, 1, 2, 3, 10, 9, 8, 4, 5, 6, 7, 15, 14, 13, 12, 11], + [0, 1, 2, 3, 4, 11, 10, 9, 8, 5, 6, 7, 15, 14, 13, 12], + [0, 1, 2, 3, 4, 5, 12, 11, 10, 9, 8, 6, 7, 15, 14, 13], + [0, 1, 2, 3, 4, 5, 6, 13, 12, 11, 10, 9, 8, 7, 15, 14], + [0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8, 15], + [0, 1, 2, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10, 9, 8], + ] + + DRIVE_TYPES = [{ + "drive_type": "development", + "system_lbas": [11, 10, 3, 2], + "sector_size": 192, + }, { + "drive_type": "retail", + "system_lbas": [9, 8, 1, 0], + "sector_size": 232, + }] + + block_valid = False + system_data = None + disk_type = None + drive_type = None + + for drive in DRIVE_TYPES: + if (block_valid): + break + + for system_lba in drive["system_lbas"]: + block_valid = True + sector_size = drive["sector_size"] + + handle.seek(system_lba * DISK_SYSTEM_SECTOR_SIZE * DISK_SECTORS_PER_BLOCK) + block_data = handle.read(sector_size * DISK_SECTORS_PER_BLOCK) + + system_data = block_data[:sector_size] + + for sector in range(1, DISK_SECTORS_PER_BLOCK): + sector_data = block_data[(sector * sector_size):][:sector_size] + if (system_data != sector_data): + block_valid = False + + if (system_data[4] != 0x10): + block_valid = False + + if ((system_data[5] & 0xF0) != 0x10): + block_valid = False + + if (block_valid): + disk_type = system_data[5] & 0x0F + drive_type = drive["drive_type"] + + if (not block_valid): + raise SC64Exception("Provided 64DD disk file is not valid") + + disk_zone_bad_tracks = [] + + for pzone in range(16): + tracks = [] + start = 0 if pzone == 0 else system_data[0x07 + pzone] + stop = system_data[0x07 + pzone + 1] + for offset in range(start, stop): + tracks.append(system_data[0x20 + offset]) + if (drive_type == "development"): + tracks.append(DISK_PZONES[pzone][2] - 2) + tracks.append(DISK_PZONES[pzone][2] - 1) + disk_zone_bad_tracks.append(tracks) + + zones = [] + + for vzone in range(16): + zones.append(DISK_PZONES[DISK_VZONE_TO_PZONE[disk_type][vzone]]) + + thb_table = [0xFFFFFFFF] * (DISK_TRACKS * DISK_HEADS * DISK_BLOCKS_PER_TRACK) + + starting_block = 0 + disk_file_offset = 0 + lba = 0 + + for (vzone, head, tracks, sector_size, track, pzone) in zones: + processed_tracks = 0 + for zone_track in range(tracks): + current_zone_track = ((tracks - 1) - zone_track) if head else zone_track + if (current_zone_track in disk_zone_bad_tracks[pzone]): + track += (-1) if head else 1 + continue + + if (processed_tracks >= (tracks - 12)): + break + + for block in range(2): + if (not (drive_type == "retail" and lba == 12)): + thb_table_entry = (track << 2) | (head << 1) | (starting_block ^ block) + thb_table[thb_table_entry] = disk_file_offset + disk_file_offset += sector_size * 85 + lba += 1 + + track += (-1) if head else 1 + starting_block ^= 1 + processed_tracks += 1 + + return (drive_type, thb_table) + + + def set_dd_disk_info(self, file: str = None): + if (file): + with open(file, "rb+") as handle: + (drive_type, thb_table) = self.__dd_process_disk(handle) + thb_table_offset = self.__query_config(self.__CFG_ID_DD_THB_TABLE_OFFSET) + data = bytearray() + for value in thb_table: + data += struct.pack(">I", value) + self.__write_cmd("W", thb_table_offset, len(data)) + self.__write(data) + self.__read_cmd_status("W") + self.set_dd_drive_type(drive_type) + else: + raise SC64Exception("No DD disk file provided for disk info creation") + + def __debug_process_fsd_set_sector(self, data: bytes) -> None: sector = int.from_bytes(data[0:4], byteorder='big') if (self.__fsd_file): @@ -409,112 +555,31 @@ class SC64: self.__fsd_file.write(data) - def __dd_calculate_file_offset(self, head_track: int, starting_block: int) -> int: - # shamelessly stolen from MAME implementation, to be rewritten - head = (head_track & 0x1000) >> 9 - track = head_track & 0xFFF - dd_zone = 0 - tr_off = 0 - - if (track >= 0x425): - dd_zone = 7 + head - tr_off = track - 0x425 - elif (track >= 0x390): - dd_zone = 6 + head - tr_off = track - 0x390 - elif (track >= 0x2FB): - dd_zone = 5 + head - tr_off = track - 0x2FB - elif (track >= 0x266): - dd_zone = 4 + head - tr_off = track - 0x266 - elif (track >= 0x1D1): - dd_zone = 3 + head - tr_off = track - 0x1D1 - elif (track >= 0x13C): - dd_zone = 2 + head - tr_off = track - 0x13C - elif (track >= 0x9E): - dd_zone = 1 + head - tr_off = track - 0x9E - else: - dd_zone = 0 + head - tr_off = track - - ddStartOffset = [ - 0x0000000, - 0x05F15E0, - 0x0B79D00, - 0x10801A0, - 0x1523720, - 0x1963D80, - 0x1D414C0, - 0x20BBCE0, - 0x23196E0, - 0x28A1E00, - 0x2DF5DC0, - 0x3299340, - 0x36D99A0, - 0x3AB70E0, - 0x3E31900, - 0x4149200 - ] - - ddZoneSecSize = [ - 232, - 216, - 208, - 192, - 176, - 160, - 144, - 128, - 216, - 208, - 192, - 176, - 160, - 144, - 128, - 112 - ] - - offset = ddStartOffset[dd_zone] + tr_off * ddZoneSecSize[dd_zone] * self.__DD_USER_SECTORS_IN_BLOCK * 2 - offset += starting_block * self.__DD_USER_SECTORS_IN_BLOCK * ddZoneSecSize[dd_zone] - return offset - - def __debug_process_dd_block(self, data: bytes) -> None: - transfer_mode = int.from_bytes(data[0:4], byteorder='little') - head_track = int.from_bytes(data[4:6], byteorder='little') - starting_block = int.from_bytes(data[6:7], byteorder='little') - sector_size = int.from_bytes(data[7:8], byteorder='little') - - block_data = None + transfer_mode = int.from_bytes(data[0:4], byteorder='big') + sdram_offset = int.from_bytes(data[4:8], byteorder='big') + disk_file_offset = int.from_bytes(data[8:12], byteorder='big') + block_length = int.from_bytes(data[12:16], byteorder='big') if (self.__disk_file): - file_offset = self.__dd_calculate_file_offset(head_track, starting_block) - self.__disk_file.seek(file_offset) + self.__disk_file.seek(disk_file_offset) if (transfer_mode): - block_data = self.__disk_file.read(sector_size * self.__DD_USER_SECTORS_IN_BLOCK) - self.__debug_write(self.__DEBUG_ID_DD_BLOCK, block_data) + self.__write_cmd("W", sdram_offset, block_length) + self.__write(self.__disk_file.read(block_length)) + self.__read_cmd_status("W") else: - block_data = self.__read_long(sector_size * self.__DD_USER_SECTORS_IN_BLOCK) - self.__disk_file.write(block_data) - print(f"{'R'if transfer_mode else 'W'} - H: {1 if (head_track & 0x2000) else 0} | T: {head_track & 0x1FFF} | S: {starting_block} = [{hex(int.from_bytes(block_data[0:4], byteorder='big'))}]") - else: - if (transfer_mode): - self.__debug_write(self.__DEBUG_ID_DD_BLOCK, bytes(4)) + 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) - def debug_loop(self, file: str = None, disk_file: str = None) -> None: + 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") - self.__serial.timeout = 0.01 - self.__serial.write_timeout = 1 - - if (file): - self.__fsd_file = open(file, "rb+") + if (fsd_file): + self.__fsd_file = open(fsd_file, "rb+") if (disk_file): self.__disk_file = open(disk_file, "rb+") @@ -537,10 +602,13 @@ class SC64: header = self.__read_long(4) id = int(header[0]) length = int.from_bytes(header[1:4], byteorder="big") + data = self.__read_long(length) + self.__read_long(self.__align(length, 4) - length) + end_indicator = self.__read_long(4) - if (length > 0): - data = self.__read_long(length) - + if (end_indicator != b"CMPH"): + print(f"\033[35mGot unknown end indicator: {end_indicator.decode(encoding='ascii', errors='backslashreplace')}\033[0m", file=sys.stderr) + else: if (id == self.__DEBUG_ID_TEXT): print(data.decode(encoding="ascii", errors="backslashreplace"), end="") elif (id == self.__DEBUG_ID_FSD_READ): @@ -554,11 +622,6 @@ class SC64: else: print(f"\033[35mGot unknown id: {id}, length: {length}\033[0m", file=sys.stderr) - self.__read_long(self.__align(length, 4) - length) - end_indicator = self.__read_long(4) - if (end_indicator != b"CMPH"): - print(f"\033[35mGot unknown end indicator: {end_indicator.decode(encoding='ascii', errors='backslashreplace')}\033[0m", file=sys.stderr) - class SC64ProgressBar: @@ -633,7 +696,6 @@ if __name__ == "__main__": parser.add_argument("-q", default=None, action="store_true", required=False, help="start debug server") 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("-x", default=False, action="store_true", required=False, help="set 64DD drive type to development") parser.add_argument("rom", metavar="rom_path", default=None, help="path to ROM file", nargs="?") if (len(sys.argv) <= 1): @@ -659,7 +721,6 @@ if __name__ == "__main__": debug_server = args.q sd_file = args.f disk_file = args.k - development_64dd = args.x firmware_backup_file = "sc64firmware.bin.bak" @@ -697,14 +758,6 @@ if __name__ == "__main__": print(f"Setting 64DD emulation to [{'Enabled' if dd_enable else 'Disabled'}]") sc64.set_dd_enable(dd_enable) - if (development_64dd): - print(f"Setting 64DD drive type to [Development]") - sc64.set_dd_drive_type("development" if development_64dd else "retail") - - if (disk_file): - print(f"Setting 64DD disk state to [Inserted]") - sc64.set_dd_disk_state("inserted" if disk_file else "ejected") - if (rom_file): if (is_read): if (rom_length > 0): @@ -727,13 +780,24 @@ if __name__ == "__main__": sc64.upload_save(save_file) if (debug_server): + if (sd_file): + print(f"Using fake SD emulation file [{sd_file}]") + if (disk_file): + print(f"Using 64DD disk image file [{disk_file}]") + sc64.set_dd_disk_info(disk_file) + if (disk_file): + print(f"Setting 64DD disk state to [Inserted]") + sc64.set_dd_disk_state("changed" if disk_file else "ejected") sc64.debug_loop(sd_file, disk_file) except SC64Exception as e: print(f"Error: {e}") parser.exit(1) except KeyboardInterrupt: - if (disk_file): - sc64.set_dd_disk_state("ejected") + pass finally: + sc64.reset_link() + if (disk_file): + print(f"Setting 64DD disk state to [Ejected]") + sc64.set_dd_disk_state("ejected") sys.stdout.write("\033[0m") diff --git a/sw/riscv/src/cfg.c b/sw/riscv/src/cfg.c index 649631d..1232c05 100644 --- a/sw/riscv/src/cfg.c +++ b/sw/riscv/src/cfg.c @@ -33,6 +33,7 @@ enum cfg_id { CFG_ID_FLASH_PROGRAM, CFG_ID_RECONFIGURE, CFG_ID_DD_SETTING, + CFG_ID_DD_THB_TABLE_OFFSET, }; enum save_type { @@ -53,11 +54,12 @@ enum boot_mode { }; enum dd_setting { - DD_SETTING_DISK_EJECTED, - DD_SETTING_DISK_INSERTED, - DD_SETTING_DISK_CHANGED, - DD_SETTING_DRIVE_RETAIL, - DD_SETTING_DRIVE_DEVELOPMENT, + 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, }; @@ -139,6 +141,9 @@ static void set_dd_setting (enum dd_setting setting) { case DD_SETTING_DRIVE_DEVELOPMENT: dd_set_drive_type_development(true); break; + case DD_SETTING_SET_BLOCK_READY: + dd_set_block_ready(true); + break; } } @@ -238,6 +243,9 @@ void cfg_query (uint32_t *args) { case CFG_ID_RECONFIGURE: args[1] = CFG->RECONFIGURE; break; + case CFG_ID_DD_THB_TABLE_OFFSET: + args[1] = dd_get_thb_table_offset(); + break; } } diff --git a/sw/riscv/src/dd.c b/sw/riscv/src/dd.c index 84131a2..a891042 100644 --- a/sw/riscv/src/dd.c +++ b/sw/riscv/src/dd.c @@ -3,13 +3,22 @@ #include "usb.h" +#define DD_USER_SECTORS_PER_BLOCK (85) + +#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 USB_DEBUG_ID_DD_BLOCK (0xF5) + #define DD_DRIVE_ID_RETAIL (0x0003) #define DD_DRIVE_ID_DEVELOPMENT (0x0004) #define DD_VERSION_RETAIL (0x0114) -#define DD_POWER_UP_DELAY_TICKS (320000000UL) // 3.2 s + +#define DD_POWER_UP_DELAY_TICKS (200000000UL) // 2 s #define DD_TRACK_SEEK_TIME_TICKS (10000) // 0.1 ms -#define DEFAULT_DD_BUFFER_OFFSET (0x03BD8000UL) -#define USB_DEBUG_ID_DD_BLOCK (0xF5) + typedef enum { DD_CMD_SEEK_READ = 0x01, @@ -55,57 +64,66 @@ struct process { uint8_t current_sector; bool is_dev_disk; rtc_time_t time; - io32_t *buffer; + io32_t *thb_table; + io32_t *usb_buffer; + io32_t *block_buffer; + bool block_ready; }; static struct process p; -enum { - READ_PHASE_IDLE, - READ_PHASE_STARTED, - READ_PHASE_WAIT, -} read_phase = READ_PHASE_IDLE; -static void dd_block_read (void) { - read_phase = READ_PHASE_STARTED; +static uint16_t dd_track_head_block (void) { + uint32_t head_track = DD->HEAD_TRACK; + uint16_t track = ((head_track & DD_TRACK_MASK) << 2); + uint16_t head = (((head_track & DD_HEAD_MASK) ? 1 : 0) << 1); + uint16_t block = (p.starting_block ? 1 : 0); - io32_t *dst = p.buffer; + return (track | head | block); +} + +static bool dd_block_valid (void) { + return (p.thb_table[dd_track_head_block()] != 0xFFFFFFFF); +} + +static bool dd_block_request (void) { + if (!usb_debug_tx_ready()) { + return false; + } + + if (!(DD->SCR & DD_SCR_DISK_INSERTED)) { + 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); + + io32_t *dst = p.usb_buffer; + *dst++ = *((uint32_t *) (dma)); - *dst++ = (((2 * 4) << 24) | USB_DEBUG_ID_DD_BLOCK); - *dst++ = p.transfer_mode; - *dst++ = (((DD->SECTOR_SIZE + 1) << 24) | (p.starting_block << 16) | DD->HEAD_TRACK); + *dst++ = swap32((USB_DEBUG_ID_DD_BLOCK << 24) | 16); + *dst++ = swap32(p.transfer_mode); + *dst++ = swap32((uint32_t) (p.block_buffer)); + *dst++ = (offset); + *dst++ = swap32(length); *dst++ = *((uint32_t *) (cmp)); - usb_debug_tx_data((uint32_t) (p.buffer), (5 * 4)); -} + usb_debug_tx_data((uint32_t) (p.usb_buffer), 28); -static bool dd_block_read_done (void) { - uint32_t type; - size_t length; - - if (read_phase == READ_PHASE_STARTED) { - if (usb_debug_rx_ready(&type, &length)) { - usb_debug_rx_data((uint32_t) (p.buffer), length); - read_phase = READ_PHASE_WAIT; - } - return false; - } else if (read_phase == READ_PHASE_WAIT) { - if (!usb_debug_rx_busy()) { - read_phase = READ_PHASE_IDLE; - return true; - } - return false; - } + p.block_ready = false; return true; } +static bool dd_block_ready (void) { + return p.block_ready || (!(DD->SCR & DD_SCR_DISK_INSERTED)); +} + static void dd_sector_read (void) { - io32_t *src = p.buffer; + io32_t *src = p.block_buffer; io32_t *dst = DD->SECTOR_BUFFER; uint8_t sector_size = ((DD->SECTOR_SIZE + 1) / sizeof(io32_t)); @@ -119,7 +137,7 @@ static void dd_sector_read (void) { static void dd_sector_write (void) { io32_t *src = DD->SECTOR_BUFFER; - io32_t *dst = p.buffer + 4; + io32_t *dst = p.block_buffer; uint8_t sector_size = ((DD->SECTOR_SIZE + 1) / sizeof(io32_t)); @@ -130,27 +148,6 @@ static void dd_sector_write (void) { } } -static void dd_block_write (void) { - io32_t *dst = p.buffer; - - const char *dma = "DMA@"; - const char *cmp = "CMPH"; - - uint32_t block_length = ((DD->SECTOR_SIZE + 1) * 85); - - *dst++ = *((uint32_t *) (dma)); - *dst++ = (((2 * 4) << 24) | USB_DEBUG_ID_DD_BLOCK); - *dst++ = p.transfer_mode; - *dst++ = (((DD->SECTOR_SIZE + 1) << 24) | (p.starting_block << 16) | DD->HEAD_TRACK); - dst += block_length / 4; - *dst++ = *((uint32_t *) (cmp)); - usb_debug_tx_data((uint32_t) (p.buffer), ((5 * 4) + block_length)); -} - -static bool dd_block_write_done (void) { - return usb_debug_tx_ready(); -} - void dd_set_disk_state (disk_state_t disk_state) { uint32_t scr = (DD->SCR & (~(DD_SCR_DISK_CHANGED | DD_SCR_DISK_INSERTED))); @@ -179,6 +176,14 @@ void dd_set_drive_type_development (bool value) { } } +void dd_set_block_ready (bool value) { + p.block_ready = value; +} + +uint32_t dd_get_thb_table_offset (void) { + return (((uint32_t) (p.thb_table)) & 0x0FFFFFFF); +} + void dd_init (void) { DD->SCR = 0; @@ -190,7 +195,9 @@ void dd_init (void) { p.deffered_cmd_ready = false; p.bm_running = false; p.is_dev_disk = false; - p.buffer = (io32_t *) (SDRAM_BASE + DEFAULT_DD_BUFFER_OFFSET); + 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); } @@ -268,16 +275,16 @@ void process_dd (void) { break; case DD_CMD_GET_RTC_YEAR_MONTH: - DD->DATA = (p.time.year << 8) | p.time.month; + DD->DATA = ((p.time.year << 8) | p.time.month); break; case DD_CMD_GET_RTC_DAY_HOUR: - DD->DATA = (p.time.day << 8) | p.time.hour; + DD->DATA = ((p.time.day << 8) | p.time.hour); break; case DD_CMD_GET_RTC_MINUTE_SECOND: p.time = *rtc_get_time(); - DD->DATA = (p.time.minute << 8) | p.time.second; + DD->DATA = ((p.time.minute << 8) | p.time.second); break; case DD_CMD_READ_PROGRAM_VERSION: @@ -349,28 +356,31 @@ void process_dd (void) { p.bm_running = true; p.current_sector = 0; if (p.transfer_mode) { - if (!p.is_dev_disk && ((DD->HEAD_TRACK & DD_HEAD_TRACK_MASK) == 6) && !p.starting_block) { - p.state = STATE_SECTOR_READ; - DD->SCR |= DD_SCR_BM_MICRO_ERROR; - } else { + if (dd_block_valid()) { p.state = STATE_BLOCK_READ; DD->SCR |= DD_SCR_BM_TRANSFER_DATA; + } else { + p.state = STATE_SECTOR_READ; + DD->SCR |= DD_SCR_BM_MICRO_ERROR; } } else { p.state = STATE_IDLE; - DD->SCR |= DD_SCR_BM_TRANSFER_DATA | DD_SCR_BM_READY; + if (dd_block_valid()) { + DD->SCR |= DD_SCR_BM_TRANSFER_DATA | DD_SCR_BM_READY; + } else { + DD->SCR |= DD_SCR_BM_MICRO_ERROR | DD_SCR_BM_READY; + } } break; case STATE_BLOCK_READ: - if (dd_block_read_done()) { - dd_block_read(); + if (dd_block_request()) { p.state = STATE_BLOCK_READ_WAIT; } break; case STATE_BLOCK_READ_WAIT: - if (dd_block_read_done()) { + if (dd_block_ready()) { p.state = STATE_SECTOR_READ; } break; @@ -394,14 +404,13 @@ void process_dd (void) { break; case STATE_BLOCK_WRITE: - if (dd_block_write_done()) { - dd_block_write(); + if (dd_block_request()) { p.state = STATE_BLOCK_WRITE_WAIT; } break; case STATE_BLOCK_WRITE_WAIT: - if (dd_block_write_done()) { + if (dd_block_ready()) { p.state = STATE_NEXT_BLOCK; } break; @@ -417,7 +426,7 @@ void process_dd (void) { p.state = STATE_STOP; } else { p.state = STATE_IDLE; - DD->SCR &= ~(DD_SCR_BM_TRANSFER_DATA); + DD->SCR &= ~(DD_SCR_BM_TRANSFER_C2 | DD_SCR_BM_TRANSFER_DATA); DD->SCR |= DD_SCR_BM_READY; } } diff --git a/sw/riscv/src/dd.h b/sw/riscv/src/dd.h index 6f57abf..18a79c0 100644 --- a/sw/riscv/src/dd.h +++ b/sw/riscv/src/dd.h @@ -14,6 +14,8 @@ 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); +uint32_t dd_get_thb_table_offset (void); void dd_init (void); void process_dd (void); diff --git a/sw/riscv/src/sys.h b/sw/riscv/src/sys.h index d0e23b2..f0ed845 100644 --- a/sw/riscv/src/sys.h +++ b/sw/riscv/src/sys.h @@ -8,6 +8,11 @@ #include +#define swap32(x) ((((x) & 0xFF000000UL) >> 24) | \ + (((x) & 0x00FF0000UL) >> 8) | \ + (((x) & 0x0000FF00UL) << 8) | \ + (((x) & 0x000000FFUL) << 24)) + typedef volatile uint8_t io8_t; typedef volatile uint16_t io16_t; typedef volatile uint32_t io32_t; @@ -235,7 +240,8 @@ typedef volatile struct dd_regs { #define DD_SCR_SEEK_TIMER_RESET (1 << 20) #define DD_TRACK_MASK (0x0FFF) -#define DD_HEAD_TRACK_MASK (0x1FFF) +#define DD_HEAD_MASK (0x1000) +#define DD_HEAD_TRACK_MASK (DD_HEAD_MASK | DD_TRACK_MASK) #define DD_HEAD_TRACK_INDEX_LOCK (1 << 13)