573in1/tools/decodeDump.py
2024-07-12 01:17:50 +02:00

132 lines
3.6 KiB
Python
Executable File

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 573in1 - Copyright (C) 2022-2024 spicyjpeg
#
# 573in1 is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# 573in1 is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# 573in1. If not, see <https://www.gnu.org/licenses/>.
__version__ = "0.4.1"
__author__ = "spicyjpeg"
import sys
from argparse import ArgumentParser, FileType, Namespace
from typing import Mapping, TextIO
from common.cart import *
from common.util import serialNumberToString, hexdumpToFile
## Dump parser
_CHIP_NAMES: Mapping[ChipType, str] = {
ChipType.NONE: "None",
ChipType.X76F041: "Xicor X76F041",
ChipType.X76F100: "Xicor X76F100",
ChipType.ZS01: "Konami ZS01 (PIC16CE625)"
}
def printDumpInfo(dump: CartDump, output: TextIO):
if dump.flags & DumpFlag.DUMP_SYSTEM_ID_OK:
output.write("Digital I/O board:\n")
output.write(f" DS2401 ID: {dump.systemID.hex('-')}\n")
output.write(
f" Serial number: {serialNumberToString(dump.systemID)}\n\n"
)
output.write("Security cartridge:\n")
output.write(f" Chip type: {_CHIP_NAMES[dump.chipType]}\n")
if dump.flags & DumpFlag.DUMP_CART_ID_OK:
output.write(f" DS2401 ID: {dump.cartID.hex('-')}\n")
if dump.flags & DumpFlag.DUMP_ZS_ID_OK:
output.write(f" ZS01 ID: {dump.zsID.hex('-')}\n")
if dump.flags & DumpFlag.DUMP_CONFIG_OK:
output.write(f" Configuration: {dump.config.hex('-')}\n")
output.write("\nEEPROM dump:\n")
hexdumpToFile(dump.data, output)
output.write("\n")
## Main
def createParser() -> ArgumentParser:
parser = ArgumentParser(
description = \
"Decodes and displays or saves the contents of a QR code cartridge "
"dump generated by the tool.",
add_help = False
)
group = parser.add_argument_group("Tool options")
group.add_argument(
"-h", "--help",
action = "help",
help = "Show this help message and exit"
)
group = parser.add_argument_group("File paths")
group.add_argument(
"-i", "--input",
type = FileType("rb"),
help = "Read dump (.573 file) or QR string from specified path",
metavar = "file"
)
group.add_argument(
"-l", "--log",
type = FileType("at"),
default = sys.stdout,
help = "Log cartridge info to specified file (stdout by default)",
metavar = "file"
)
group.add_argument(
"-e", "--export",
type = FileType("wb"),
help = "Export binary dump (.573 file) to specified path",
metavar = "file"
)
group = parser.add_argument_group("Input data")
group.add_argument(
"data",
type = str,
nargs = "?",
help = "QR string to decode (if -i was not passed)"
)
return parser
def main():
parser: ArgumentParser = createParser()
args: Namespace = parser.parse_args()
if args.input:
with args.input as file:
data: bytes = file.read()
try:
dump: CartDump = parseCartDump(data)
except:
dump: CartDump = parseCartQRString(data.decode("ascii"))
elif args.data:
dump: CartDump = parseCartQRString(args.data)
else:
parser.error("a dump must be passed on the command line or using -i")
if args.log:
printDumpInfo(dump, args.log)
if args.export:
with args.export as file:
file.write(dump.serialize())
if __name__ == "__main__":
main()