diff --git a/fw/SummerCart64.qsf b/fw/SummerCart64.qsf index 13d94dd..3ed036d 100644 --- a/fw/SummerCart64.qsf +++ b/fw/SummerCart64.qsf @@ -19,7 +19,7 @@ # # Quartus Prime # Version 20.1.1 Build 720 11/11/2020 SJ Lite Edition -# Date created = 17:57:25 August 28, 2021 +# Date created = 21:34:30 August 28, 2021 # # -------------------------------------------------------------------------- # # @@ -196,7 +196,6 @@ set_global_assignment -name FAMILY "MAX 10" set_global_assignment -name DEVICE_FILTER_PACKAGE EQFP set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144 set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8 -set_global_assignment -name TOP_LEVEL_ENTITY SummerCart64 set_global_assignment -name PROJECT_IP_REGENERATION_POLICY ALWAYS_REGENERATE_IP set_global_assignment -name VHDL_INPUT_VERSION VHDL_2008 set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF diff --git a/fw/cpu/controller/process.c b/fw/cpu/controller/process.c index 0a6e128..f9dc968 100644 --- a/fw/cpu/controller/process.c +++ b/fw/cpu/controller/process.c @@ -100,6 +100,28 @@ void process_usb (void) { } else if (cmd == 'C') { cfg_update_config(args); state = 3; + } else if (cmd == 'Q') { + if (USB->SCR & USB_SCR_TXE) { + switch (current_byte) { + case 0: USB->DR = cic_type >> 8; break; + case 1: USB->DR = cic_type; break; + case 2: USB->DR = ((tv_type & 0x3) << 4) | (save_type & 0x7); break; + case 3: USB->DR = CFG->SCR; break; + case 4: USB->DR = (CFG->SAVE_OFFSET >> 24); break; + case 5: USB->DR = (CFG->SAVE_OFFSET >> 16); break; + case 6: USB->DR = (CFG->SAVE_OFFSET >> 8); break; + case 7: USB->DR = (CFG->SAVE_OFFSET >> 0); break; + case 8: USB->DR = (CFG->DD_OFFSET >> 24); break; + case 9: USB->DR = (CFG->DD_OFFSET >> 16); break; + case 10: USB->DR = (CFG->DD_OFFSET >> 8); break; + case 11: USB->DR = (CFG->DD_OFFSET >> 0); break; + } + current_byte += 1; + if (current_byte == 12) { + state = 3; + current_byte = 0; + } + } } else { state = 3; is_error = 1; diff --git a/sw/dumpy/.gitignore b/sw/dumpy/.gitignore new file mode 100644 index 0000000..609531a --- /dev/null +++ b/sw/dumpy/.gitignore @@ -0,0 +1,7 @@ +*.dat +*.srm +*.eep +*.fla +*.n64 +*.z64 +*.v64 diff --git a/sw/dumpy/dum.py b/sw/dumpy/dum.py new file mode 100644 index 0000000..ab14921 --- /dev/null +++ b/sw/dumpy/dum.py @@ -0,0 +1,102 @@ +import os +import serial +import sys + + + +class SC64: + __SDRAM_SIZE = 64 * 1024 * 1024 + + def __init__(self, port): + self.__serial = serial.Serial(port) + self.__query_config() + + + def __query_config(self): + self.__serial.write(b'CMDQ') + self.__serial.write(bytes(8)) + config_raw = self.__serial.read(12) + if (self.__serial.read(4).decode() != 'CMPQ'): + raise Exception('Bad query response') + self.__save_type = config_raw[2] & 0x07 + self.__save_offset = int.from_bytes(config_raw[4:8], byteorder='big') + + + def __save_length(self): + return { + 0: 0, + 1: 512, + 2: 2048, + 3: (32 * 1024), + 4: (128 * 1024), + 5: (3 * 32 * 1024), + 6: (128 * 1024), + 7: 0 + }[self.__save_type] + + + def dump_save(self, file): + length = self.__save_length() + if (length == 0): + raise Exception('No save type is selected') + self.__serial.write(b'CMDR') + self.__serial.write(self.__save_offset.to_bytes(4, byteorder='big')) + self.__serial.write(length.to_bytes(4, byteorder='big')) + save = self.__serial.read(length) + response = self.__serial.read(4) + if (response.decode() == 'CMPR'): + with open(file, 'wb') as f: + f.write(save) + else: + raise Exception('There was a problem while dumping save data') + + + def redump_save(self, file): + length = self.__save_length() + if (not length): + raise Exception('No save type is selected') + if (os.path.getsize(file) != length): + raise Exception('Wrong save file size') + with open(file, 'rb') as f: + self.__serial.write(b'CMDW') + self.__serial.write(self.__save_offset.to_bytes(4, byteorder='big')) + self.__serial.write(length.to_bytes(4, byteorder='big')) + self.__serial.write(f.read()) + response = self.__serial.read(4) + if (response.decode() != 'CMPW'): + raise Exception('There was a problem while redumping save data') + + + def dump_all(self, file): + self.__serial.write(b'CMDR') + self.__serial.write((0).to_bytes(4, byteorder='big')) + self.__serial.write((self.__SDRAM_SIZE).to_bytes(4, byteorder='big')) + save = self.__serial.read(self.__SDRAM_SIZE) + response = self.__serial.read(4) + if (response.decode() == 'CMPR'): + with open(file, 'wb') as f: + f.write(save) + else: + raise Exception('There was a problem while dumping all data') + + + +mode = 'r' +file = 'save.dat' +port = 'COM5' + +if (len(sys.argv) >= 2): + mode = sys.argv[1] +if (len(sys.argv) >= 3): + file = sys.argv[2] +if (len(sys.argv) >= 4): + port = sys.argv[3] + +sc64 = SC64(port) + +if (mode == 'r'): + sc64.dump_save(file) +elif (mode == 'w'): + sc64.redump_save(file) +elif (mode == 'a'): + sc64.dump_all(file)