fsd write, rtc, isv and reset fixes

This commit is contained in:
Polprzewodnikowy 2022-01-23 19:56:28 +01:00
parent 49251e50f2
commit 7f9989cab6
12 changed files with 235 additions and 74 deletions

View File

@ -46,5 +46,25 @@ DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) {
#endif
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void *buff) {
if (cmd == CTRL_SYNC) {
return RES_OK;
}
return RES_PARERR;
}
static uint8_t from_bcd (uint8_t bcd) {
return ((((bcd >> 4) & 0x0F) * 10) + (bcd & 0x0F));
}
DWORD get_fattime(void) {
rtc_time_t t;
sc64_get_time(&t);
return (
((from_bcd(t.year) + 20) << 25) |
(from_bcd(t.month) << 21) |
(from_bcd(t.day) << 16) |
(from_bcd(t.hour) << 11) |
(from_bcd(t.minute) << 5) |
(from_bcd(t.second) >> 1)
);
}

View File

@ -237,7 +237,7 @@
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
#define FF_FS_NORTC 1
#define FF_FS_NORTC 0
#define FF_NORTC_MON 1
#define FF_NORTC_MDAY 1
#define FF_NORTC_YEAR 2020

View File

@ -62,6 +62,26 @@ void sc64_init (void) {
sc64_change_config(CFG_ID_SDRAM_SWITCH, true);
}
void sc64_get_time (rtc_time_t *t) {
uint32_t result[2];
sc64_perform_cmd(SC64_CMD_GET_TIME, NULL, result);
t->second = (result[0] & 0xFF);
t->minute = ((result[0] >> 8) & 0xFF);
t->hour = ((result[0] >> 16) & 0xFF);
t->weekday = ((result[1] >> 24) & 0xFF);
t->day = (result[1] & 0xFF);
t->month = ((result[1] >> 8) & 0xFF);
t->year = ((result[1] >> 16) & 0xFF);
}
void sc64_set_time (rtc_time_t *t) {
uint32_t args[2] = {
((t->hour << 16) | (t->minute << 8) | t->second),
((t->weekday << 24) | (t->year << 16) | (t->month << 8) | t->day),
};
sc64_perform_cmd(SC64_CMD_SET_TIME, args, NULL);
}
static uint32_t sc64_wait_drive_ready (drive_id_t drive) {
uint32_t args[2] = { (drive & 0xFF), 0 };
uint32_t result[2];

View File

@ -9,10 +9,14 @@
#define SC64_CMD_QUERY ('Q')
#define SC64_CMD_CONFIG ('C')
#define SC64_CMD_GET_TIME (0xEE)
#define SC64_CMD_SET_TIME (0xEF)
#define SC64_CMD_DRIVE_INIT (0xF0)
#define SC64_CMD_DRIVE_BUSY (0xF1)
#define SC64_CMD_DRIVE_READ (0xF2)
#define SC64_CMD_DRIVE_WRITE (0xF3)
#define SC64_CMD_DRIVE_LOAD (0xF4)
#define SC64_CMD_DRIVE_STORE (0xF5)
#define SC64_CMD_UART_PUT (0xFF)
#define SC64_VERSION_2 (0x53437632)
@ -64,6 +68,16 @@ typedef struct {
tv_type_t tv_type;
} sc64_info_t;
typedef struct {
uint8_t second;
uint8_t minute;
uint8_t hour;
uint8_t weekday;
uint8_t day;
uint8_t month;
uint8_t year;
} rtc_time_t;
typedef enum {
DRIVE_SD = 0,
DRIVE_USB = 1,
@ -76,6 +90,8 @@ uint32_t sc64_query_config (cfg_id_t id);
void sc64_change_config (cfg_id_t id, uint32_t value);
void sc64_get_info (sc64_info_t *info);
void sc64_init (void);
void sc64_get_time (rtc_time_t *t);
void sc64_set_time (rtc_time_t *t);
bool sc64_storage_init (drive_id_t drive);
bool sc64_storage_read (drive_id_t drive, void *buffer, uint32_t sector, uint32_t count);
bool sc64_storage_write (drive_id_t drive, const void *buffer, uint32_t sector, uint32_t count);

View File

@ -70,6 +70,7 @@ void storage_run_menu (storage_backend_t storage_backend) {
FF_CHECK(f_read(&fil, menu, size, &br), "Couldn't read menu file");
FF_CHECK(br != size, "Read size is different than expected");
FF_CHECK(f_close(&fil), "Couldn't close menu file");
FF_CHECK(f_unmount(path), "Couldn't unmount drive");
deinit();

23
sw/pc/helpers.py Normal file
View File

@ -0,0 +1,23 @@
from io import TextIOWrapper
import contextlib
import os.path
import platform
@contextlib.contextmanager
def lock_volume(volume: TextIOWrapper):
if (os.path.ismount(volume.name)):
if (platform.system().startswith("Windows")):
import msvcrt
import win32file
import winioctlcon
handle = msvcrt.get_osfhandle(volume.fileno())
win32file.DeviceIoControl(handle, winioctlcon.FSCTL_LOCK_VOLUME, None, None)
try:
yield volume
finally:
try:
volume.flush()
finally:
win32file.DeviceIoControl(handle, winioctlcon.FSCTL_UNLOCK_VOLUME, None, None)

View File

@ -1,2 +1,3 @@
progressbar2==3.55.0
pyft232==0.12
pywin32==303; sys_platform == 'win32'

View File

@ -1,9 +1,12 @@
#!/usr/bin/env python3
from datetime import datetime
from ft232 import Ft232, Ft232Exception
from io import TextIOWrapper
from typing import Union
import argparse
import filecmp
import helpers
import os
import progressbar
import re
@ -73,6 +76,7 @@ class SC64:
def __del__(self) -> None:
if (self.__usb):
self.__reset_n64("release")
self.__usb.close()
if (self.__fsd_file):
self.__fsd_file.close()
@ -134,20 +138,25 @@ class SC64:
self.__write(value.to_bytes(4, byteorder="big"))
def __read_cmd_status(self, cmd: str) -> None:
if (self.__read(4) != f"CMP{cmd[0]}".encode(encoding="ascii")):
def __read_cmd_status(self, cmd: Union[str, int]) -> None:
token = b"CMP" + (cmd.encode() if isinstance(cmd, str) else int.to_bytes(cmd, 1, byteorder="big"))
if (self.__read(4) != token):
raise SC64Exception("Wrong command response")
def __write_cmd(self, cmd: str, arg1: int, arg2: int) -> None:
self.__write(f"CMD{cmd[0]}".encode())
def __write_cmd(self, cmd: Union[str, int], arg1: int, arg2: int) -> None:
token = b"CMD" + (cmd.encode() if isinstance(cmd, str) else int.to_bytes(cmd, 1, byteorder="big"))
self.__write(token)
self.__write_int(arg1)
self.__write_int(arg2)
def reset_n64(self) -> None:
def __reset_n64(self, type: str) -> None:
if (self.__usb):
if (type == "hold"):
self.__usb.cbus_setup(mask=1, init=0)
time.sleep(0.1)
time.sleep(0.6)
elif (type == "release"):
self.__usb.cbus_setup(mask=0)
@ -157,6 +166,7 @@ class SC64:
try:
self.__usb = Ft232(description="SummerCart64")
self.__reset_n64("hold")
self.__usb.flushOutput()
self.reset_link()
self.__probe_device()
@ -252,6 +262,16 @@ class SC64:
self.__find_sc64()
def set_rtc(self, t: datetime) -> None:
to_bcd = lambda v : ((int((v / 10) % 10) << 4) | int(int(v) % 10))
args = [
(to_bcd(t.weekday() + 1) << 24) | (to_bcd(t.hour) << 16) | (to_bcd(t.minute) << 8) | to_bcd(t.second),
(to_bcd(t.year) << 16) | (to_bcd(t.month) << 8) | to_bcd(t.day),
]
self.__write_cmd(0xEF, args[0], args[1])
self.__read_cmd_status(0xEF)
def set_boot_mode(self, mode: int) -> None:
if (mode >= 0 and mode <= 4):
self.__change_config(self.__CFG_ID_BOOT_MODE, mode)
@ -555,6 +575,7 @@ class SC64:
offset = int.from_bytes(data[4:8], byteorder="little")
if (self.__fsd_file):
with helpers.lock_volume(self.__fsd_file):
self.__fsd_file.seek(sector * 512)
self.__write_cmd("F", offset, 512)
self.__fsd_file.write(self.__read(512))
@ -609,6 +630,8 @@ class SC64:
start_indicator = bytearray()
dropped_bytes = 0
self.__reset_n64("release")
while (True):
while (start_indicator != b"DMA@"):
start_indicator.append(self.__read_long(1)[0])
@ -705,6 +728,7 @@ class SC64ProgressBar:
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="SummerCart64 one stop control center")
parser.add_argument("-rtc", default=False, action="store_true", required=False, help="update RTC to system time")
parser.add_argument("-b", metavar="boot_mode", default="2", required=False, help="set boot mode (0 - 4)")
parser.add_argument("-t", metavar="tv_type", default="3", required=False, help="set TV type (0 - 2)")
parser.add_argument("-c", metavar="cic_seed", default="0xFFFF", required=False, help="set CIC seed")
@ -731,6 +755,7 @@ if __name__ == "__main__":
try:
sc64 = SC64()
rtc = args.rtc
boot_mode = int(args.b)
save_type = int(args.s)
tv_type = int(args.t)
@ -751,6 +776,11 @@ if __name__ == "__main__":
firmware_backup_file = "sc64firmware.bin.bak"
with SC64ProgressBar(sc64):
if (rtc):
now = datetime.now()
print(f"Setting RTC to [{now}]")
sc64.set_rtc(now)
if (update_file):
if (is_read):
sc64.backup_firmware(update_file)
@ -805,8 +835,6 @@ if __name__ == "__main__":
else:
sc64.upload_save(save_file)
sc64.reset_n64()
if (debug_server):
sc64.debug_init(sd_file, disk_file, dd_turbo)
if (is_viewer_enabled):

View File

@ -3,8 +3,9 @@
#include "flash.h"
#include "isv.h"
#include "joybus.h"
#include "usb.h"
#include "rtc.h"
#include "uart.h"
#include "usb.h"
#define SAVE_SIZE_EEPROM_4K (512)
@ -132,6 +133,59 @@ uint32_t cfg_get_version (void) {
return CFG->VERSION;
}
void cfg_query (uint32_t *args) {
switch (args[0]) {
case CFG_ID_SCR:
args[1] = CFG->SCR;
break;
case CFG_ID_SDRAM_SWITCH:
args[1] = CFG->SCR & CFG_SCR_SDRAM_SWITCH;
break;
case CFG_ID_SDRAM_WRITABLE:
args[1] = CFG->SCR & CFG_SCR_SDRAM_WRITABLE;
break;
case CFG_ID_DD_ENABLE:
args[1] = CFG->SCR & CFG_SCR_DD_EN;
break;
case CFG_ID_SAVE_TYPE:
args[1] = (uint32_t) (p.save_type);
break;
case CFG_ID_CIC_SEED:
args[1] = (uint32_t) (p.cic_seed);
break;
case CFG_ID_TV_TYPE:
args[1] = (uint32_t) (p.tv_type);
break;
case CFG_ID_SAVE_OFFEST:
args[1] = CFG->SAVE_OFFSET;
break;
case CFG_ID_DDIPL_OFFEST:
args[1] = CFG->DDIPL_OFFSET;
break;
case CFG_ID_BOOT_MODE:
args[1] = p.boot_mode;
break;
case CFG_ID_FLASH_SIZE:
args[1] = flash_size();
break;
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;
}
}
void cfg_update (uint32_t *args) {
switch (args[0]) {
case CFG_ID_SCR:
@ -194,57 +248,22 @@ void cfg_update (uint32_t *args) {
}
}
void cfg_query (uint32_t *args) {
switch (args[0]) {
case CFG_ID_SCR:
args[1] = CFG->SCR;
break;
case CFG_ID_SDRAM_SWITCH:
args[1] = CFG->SCR & CFG_SCR_SDRAM_SWITCH;
break;
case CFG_ID_SDRAM_WRITABLE:
args[1] = CFG->SCR & CFG_SCR_SDRAM_WRITABLE;
break;
case CFG_ID_DD_ENABLE:
args[1] = CFG->SCR & CFG_SCR_DD_EN;
break;
case CFG_ID_SAVE_TYPE:
args[1] = (uint32_t) (p.save_type);
break;
case CFG_ID_CIC_SEED:
args[1] = (uint32_t) (p.cic_seed);
break;
case CFG_ID_TV_TYPE:
args[1] = (uint32_t) (p.tv_type);
break;
case CFG_ID_SAVE_OFFEST:
args[1] = CFG->SAVE_OFFSET;
break;
case CFG_ID_DDIPL_OFFEST:
args[1] = CFG->DDIPL_OFFSET;
break;
case CFG_ID_BOOT_MODE:
args[1] = p.boot_mode;
break;
case CFG_ID_FLASH_SIZE:
args[1] = flash_size();
break;
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;
}
void cfg_get_time (uint32_t *args) {
rtc_time_t *t = rtc_get_time();
args[0] = ((t->hour << 16) | (t->minute << 8) | t->second);
args[1] = ((t->weekday << 24) | (t->year << 16) | (t->month << 8) | t->day);
}
void cfg_set_time (uint32_t *args) {
rtc_time_t t;
t.second = (args[0] & 0xFF);
t.minute = ((args[0] >> 8) & 0xFF);
t.hour = ((args[0] >> 16) & 0xFF);
t.weekday = ((args[1] >> 24) & 0xFF);
t.day = (args[1] & 0xFF);
t.month = ((args[1] >> 8) & 0xFF);
t.year = ((args[1] >> 16) & 0xFF);
rtc_set_time(&t);
}
@ -271,14 +290,26 @@ void process_cfg (void) {
args[1] = CFG->DATA[1];
switch (CFG->CMD) {
case 'C':
cfg_update(args);
case 'V':
args[0] = cfg_get_version();
break;
case 'Q':
cfg_query(args);
break;
case 'C':
cfg_update(args);
break;
case 0xEE:
cfg_get_time(args);
break;
case 0xEF:
cfg_set_time(args);
break;
case 0xF0:
if (args[0] == 0) {
change_scr_bits(CFG_SCR_CMD_ERROR, true);

View File

@ -6,8 +6,10 @@
uint32_t cfg_get_version (void);
void cfg_update (uint32_t *args);
void cfg_query (uint32_t *args);
void cfg_update (uint32_t *args);
void cfg_get_time (uint32_t *args);
void cfg_set_time (uint32_t *args);
void cfg_init (void);
void process_cfg (void);

View File

@ -21,6 +21,7 @@ static void isv_set_ready (void) {
void isv_set_enabled (bool enabled) {
if (enabled) {
CFG->SCR |= CFG_SCR_ISV_EN;
CFG->ISV_CURRENT_RD_PTR = CFG->ISV_RD_PTR;
p.ready = true;
} else {
CFG->SCR &= ~(CFG_SCR_ISV_EN);

View File

@ -210,11 +210,6 @@ void process_usb (void) {
}
break;
case 'C':
cfg_update(p.args);
p.state = STATE_RESPONSE;
break;
case 'Q':
if (p.counter == 0) {
cfg_query(p.args);
@ -225,6 +220,29 @@ void process_usb (void) {
}
break;
case 'C':
cfg_update(p.args);
p.state = STATE_RESPONSE;
break;
case 0xEE:
if (p.counter == 0) {
cfg_get_time(p.args);
p.counter += 1;
}
if ((p.counter == 1) && tx_word(p.args[0])) {
p.counter += 1;
}
if ((p.counter == 2) && tx_word(p.args[1])) {
p.state = STATE_RESPONSE;
}
break;
case 0xEF:
cfg_set_time(p.args);
p.state = STATE_RESPONSE;
break;
case 'R':
case 'W':
case 'L':