import os
import sys
from enum import Enum
class SaveType(Enum):
EEPROM_512B = 0
EEPROM_8K = 1
FLASH_64K = 2
FLASH_128K = 3
SRAM = 4
SAVE_UNKNOWN = 5
def save_type_to_string(save_type):
return {
SaveType.EEPROM_512B: "EEPROM 4kbit",
SaveType.EEPROM_8K: "EEPROM 64kbit",
SaveType.FLASH_64K: "FLASH 512kbit",
SaveType.FLASH_128K: "FLASH 1MBit",
SaveType.SRAM: "SRAM",
SaveType.SAVE_UNKNOWN: "Unknown type"
}.get(save_type, "Unknown type")
def scan_section(data, size):
for i in range(size):
if data[i] != 0xff:
return True
return False
def detect_save_type(data, size):
if size == 512:
return SaveType.EEPROM_512B
if size == 0x2000:
return SaveType.EEPROM_8K
if size == 0x10000:
return SaveType.FLASH_64K
if size == 0x20000:
return SaveType.FLASH_128K
if size == 0x8000:
return SaveType.SRAM
if size == (0x20000 + 0x2000):
if scan_section(data[:0x8000], 0x8000) and not scan_section(data[0x8000:0x8000 + 0x1A000], 0x1A000):
return SaveType.SRAM
if scan_section(data[:0x10000], 0x10000) and not scan_section(data[0x10000:0x10000 + 0x10000], 0x10000):
return SaveType.FLASH_64K
if scan_section(data[:0x20000], 0x20000):
return SaveType.FLASH_128K
if scan_section(data[0x20000:0x20000 + 512], 512) and not scan_section(data[0x20000 + 512:0x20000 + 0x20000], 0x20000 - 512):
return SaveType.EEPROM_512B
if scan_section(data[0x20000:0x20000 + 0x2000], 0x2000):
return SaveType.EEPROM_8K
return SaveType.SAVE_UNKNOWN
def dump_srm(file, data, save_type):
buf = bytearray([0xff] * (0x20000 + 0x2000))
if save_type == SaveType.EEPROM_512B:
file.write(buf[:0x20000])
file.write(data[:512])
file.write(buf[:0x2000 - 512])
elif save_type == SaveType.EEPROM_8K:
file.write(buf[:0x20000])
file.write(data[:0x2000])
elif save_type == SaveType.FLASH_64K:
file.write(data[:0x10000])
file.write(buf[:0x20000 + 0x2000 - 0x10000])
elif save_type == SaveType.FLASH_128K:
file.write(data[:0x20000])
file.write(buf[:0x2000])
elif save_type == SaveType.SRAM:
file.write(data[:0x8000])
file.write(buf[:0x1A000])
def dump_sav(file, data, save_type):
if save_type == SaveType.EEPROM_512B:
file.write(data[0x20000:0x20000 + 512])
elif save_type == SaveType.EEPROM_8K:
file.write(data[0x20000:0x20000 + 0x2000])
elif save_type == SaveType.FLASH_64K:
file.write(data[:0x10000])
elif save_type == SaveType.FLASH_128K:
file.write(data[:0x20000])
elif save_type == SaveType.SRAM:
file.write(data[:0x8000])
def main():
if len(sys.argv) != 2:
print(f"Usage: {sys.argv[0]} <file>", file=sys.stderr)
sys.exit(1)
input_file = sys.argv[1]
try:
with open(input_file, 'rb') as f:
data = f.read()
except IOError:
print(f'Failed to open file "{input_file}"', file=sys.stderr)
sys.exit(1)
file_len = len(data)
out_path = os.path.splitext(input_file)[0]
ext = os.path.splitext(input_file)[1].lower()
if ext == '.srm':
out_path += '.sav'
elif len(ext) >= 3: # At least 3 characters (like .sav)
out_path += '.srm'
else:
print("Cannot detect extension!", file=sys.stderr)
sys.exit(1)
save_type = detect_save_type(data, file_len)
print(f"Detected save type: {save_type_to_string(save_type)}")
if save_type == SaveType.SAVE_UNKNOWN:
print("Cannot infer save type ...", file=sys.stderr)
sys.exit(1)
try:
with open(out_path, 'wb') as f:
if file_len == (0x20000 + 0x2000):
dump_sav(f, data, save_type)
else:
dump_srm(f, data, save_type)
except IOError:
print(f"Failed to write to output file {out_path}", file=sys.stderr)
sys.exit(1)
return 0
if __name__ == "__main__":
main()