mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-25 07:06:52 +01:00
fsd write, rtc, isv and reset fixes
This commit is contained in:
parent
49251e50f2
commit
7f9989cab6
@ -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)
|
||||
);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
|
@ -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
23
sw/pc/helpers.py
Normal 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)
|
@ -1,2 +1,3 @@
|
||||
progressbar2==3.55.0
|
||||
pyft232==0.12
|
||||
pywin32==303; sys_platform == 'win32'
|
||||
|
@ -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,21 +138,26 @@ 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:
|
||||
self.__usb.cbus_setup(mask=1, init=0)
|
||||
time.sleep(0.1)
|
||||
self.__usb.cbus_setup(mask=0)
|
||||
def __reset_n64(self, type: str) -> None:
|
||||
if (self.__usb):
|
||||
if (type == "hold"):
|
||||
self.__usb.cbus_setup(mask=1, init=0)
|
||||
time.sleep(0.6)
|
||||
elif (type == "release"):
|
||||
self.__usb.cbus_setup(mask=0)
|
||||
|
||||
|
||||
def __find_sc64(self) -> None:
|
||||
@ -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,9 +575,10 @@ class SC64:
|
||||
offset = int.from_bytes(data[4:8], byteorder="little")
|
||||
|
||||
if (self.__fsd_file):
|
||||
self.__fsd_file.seek(sector * 512)
|
||||
self.__write_cmd("F", offset, 512)
|
||||
self.__fsd_file.write(self.__read(512))
|
||||
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))
|
||||
else:
|
||||
self.__write_cmd("F", offset, 0)
|
||||
|
||||
@ -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)
|
||||
@ -804,8 +834,6 @@ if __name__ == "__main__":
|
||||
sc64.download_save(save_file)
|
||||
else:
|
||||
sc64.upload_save(save_file)
|
||||
|
||||
sc64.reset_n64()
|
||||
|
||||
if (debug_server):
|
||||
sc64.debug_init(sd_file, disk_file, dd_turbo)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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':
|
||||
|
Loading…
Reference in New Issue
Block a user