mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-22 05:59:15 +01:00
[SC64][SW] Fixed setting CIC parameters, added GDB socket support in sc64.py
This commit is contained in:
parent
982db95fa2
commit
39dccd5e00
@ -4,6 +4,7 @@ import argparse
|
|||||||
import os
|
import os
|
||||||
import queue
|
import queue
|
||||||
import serial
|
import serial
|
||||||
|
import socket
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@ -313,9 +314,11 @@ class SC64:
|
|||||||
RAWBINARY = 2
|
RAWBINARY = 2
|
||||||
HEADER = 3
|
HEADER = 3
|
||||||
SCREENSHOT = 4
|
SCREENSHOT = 4
|
||||||
|
GDB = 0xDB
|
||||||
|
|
||||||
__isv_line_buffer: bytes = b''
|
__isv_line_buffer: bytes = b''
|
||||||
__debug_header: Optional[bytes] = None
|
__debug_header: Optional[bytes] = None
|
||||||
|
__gdb_client: Optional[socket.socket] = None
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.__link = SC64Serial()
|
self.__link = SC64Serial()
|
||||||
@ -496,16 +499,18 @@ class SC64:
|
|||||||
def set_save_type(self, type: SaveType) -> None:
|
def set_save_type(self, type: SaveType) -> None:
|
||||||
self.__set_config(self.__CfgId.SAVE_TYPE, type)
|
self.__set_config(self.__CfgId.SAVE_TYPE, type)
|
||||||
|
|
||||||
def set_cic_parameters(self, disabled=False, dd_mode: bool=False, seed: int=0x3F, checksum: bytes=bytes([0xA5, 0x36, 0xC0, 0xF1, 0xD8, 0x59])) -> None:
|
def set_cic_parameters(self, disabled=False, dd_mode: bool=False, seed: Optional[int]=None, checksum: Optional[int]=None) -> None:
|
||||||
|
# TODO: guess seed and calculate checksum if not provided
|
||||||
|
seed = seed if seed else 0x3F
|
||||||
|
checksum = checksum if checksum else 0xA536C0F1D859
|
||||||
if (seed < 0 or seed > 0xFF):
|
if (seed < 0 or seed > 0xFF):
|
||||||
raise ValueError('CIC seed outside of allowed values')
|
raise ValueError('CIC seed outside of allowed values')
|
||||||
if (len(checksum) != 6):
|
|
||||||
raise ValueError('CIC checksum length outside of allowed values')
|
|
||||||
mode = (1 << 1) if disabled else 0
|
mode = (1 << 1) if disabled else 0
|
||||||
mode |= (1 << 0) if dd_mode else 0
|
mode |= (1 << 0) if dd_mode else 0
|
||||||
data = bytes([mode, seed])
|
data = bytes([mode, seed])
|
||||||
data = [*data, *checksum]
|
data = [*data, *checksum.to_bytes(6, byteorder='big')]
|
||||||
self.__link.execute_cmd(cmd=b'B', args=[self.__get_int(data[0:4]), self.__get_int(data[4:8])])
|
self.__link.execute_cmd(cmd=b'B', args=[self.__get_int(data[0:4]), self.__get_int(data[4:8])])
|
||||||
|
return (seed, checksum)
|
||||||
|
|
||||||
def update_firmware(self, data: bytes, status_callback: Optional[Callable[[str], None]]=None) -> None:
|
def update_firmware(self, data: bytes, status_callback: Optional[Callable[[str], None]]=None) -> None:
|
||||||
address = self.__Address.FIRMWARE
|
address = self.__Address.FIRMWARE
|
||||||
@ -607,6 +612,35 @@ class SC64:
|
|||||||
print('Screenshot header data is invalid')
|
print('Screenshot header data is invalid')
|
||||||
else:
|
else:
|
||||||
print('Got screenshot packet without header data')
|
print('Got screenshot packet without header data')
|
||||||
|
elif (datatype == self.__DebugDatatype.GDB):
|
||||||
|
self.__handle_gdb_datatype(packet)
|
||||||
|
|
||||||
|
def __handle_gdb_socket(self, gdb_port: int) -> None:
|
||||||
|
MAX_PACKET_SIZE = 65536
|
||||||
|
gdb_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
gdb_socket.bind(('localhost', gdb_port))
|
||||||
|
gdb_socket.listen()
|
||||||
|
while (True):
|
||||||
|
(self.__gdb_client, address) = gdb_socket.accept()
|
||||||
|
client_address = f'{address[0]}:{address[1]}'
|
||||||
|
print(f'[GDB]: New connection ({client_address})')
|
||||||
|
while (True):
|
||||||
|
try:
|
||||||
|
data = self.__gdb_client.recv(MAX_PACKET_SIZE)
|
||||||
|
if (len(data) == 0):
|
||||||
|
break
|
||||||
|
self.debug_send(self.__DebugDatatype.GDB, data)
|
||||||
|
except:
|
||||||
|
self.__gdb_client.close()
|
||||||
|
break
|
||||||
|
print(f'[GDB]: Connection closed ({client_address})')
|
||||||
|
|
||||||
|
def __handle_gdb_datatype(self, data: bytes) -> None:
|
||||||
|
if (self.__gdb_client):
|
||||||
|
try:
|
||||||
|
self.__gdb_client.sendall(data)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
def __handle_debug_input(self) -> None:
|
def __handle_debug_input(self) -> None:
|
||||||
running = True
|
running = True
|
||||||
@ -641,7 +675,7 @@ class SC64:
|
|||||||
except EOFError:
|
except EOFError:
|
||||||
running = False
|
running = False
|
||||||
|
|
||||||
def debug_loop(self, isv: int=0, disks: Optional[list[str]]=None) -> None:
|
def debug_loop(self, isv: int=0, disks: Optional[list[str]]=None, gdb_port: Optional[int]=None) -> None:
|
||||||
dd = None
|
dd = None
|
||||||
current_image = 0
|
current_image = 0
|
||||||
next_image = 0
|
next_image = 0
|
||||||
@ -651,7 +685,7 @@ class SC64:
|
|||||||
if (isv != 0):
|
if (isv != 0):
|
||||||
print(f'IS-Viewer64 support set to [ENABLED] at ROM offset [0x{(isv):08X}]')
|
print(f'IS-Viewer64 support set to [ENABLED] at ROM offset [0x{(isv):08X}]')
|
||||||
if (self.__get_config(self.__CfgId.ROM_SHADOW_ENABLE)):
|
if (self.__get_config(self.__CfgId.ROM_SHADOW_ENABLE)):
|
||||||
print('ROM shadow enabled - IS-Viewer64 will NOT work (use --no-shadow option to disable it)')
|
print('ROM shadow enabled - IS-Viewer64 will NOT work (use --no-shadow option while uploading ROM to disable it)')
|
||||||
|
|
||||||
if (disks):
|
if (disks):
|
||||||
dd = DD64Image()
|
dd = DD64Image()
|
||||||
@ -682,6 +716,11 @@ class SC64:
|
|||||||
print(f' - {os.path.basename(disk)}')
|
print(f' - {os.path.basename(disk)}')
|
||||||
print('Press button on SC64 device to cycle through provided disks')
|
print('Press button on SC64 device to cycle through provided disks')
|
||||||
|
|
||||||
|
if (gdb_port):
|
||||||
|
gdb_thread = Thread(target=lambda: self.__handle_gdb_socket(gdb_port), daemon=True)
|
||||||
|
gdb_thread.start()
|
||||||
|
print(f'GDB server started and listening on port [{gdb_port}]')
|
||||||
|
|
||||||
print('\nDebug loop started, press Ctrl-C to exit\n')
|
print('\nDebug loop started, press Ctrl-C to exit\n')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -741,6 +780,14 @@ class EnumAction(argparse.Action):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
def cic_params_type(argument: str):
|
||||||
|
params = argument.split(',')
|
||||||
|
disabled = bool(int(params[0]))
|
||||||
|
dd_mode = bool(int(params[1])) if len(params) >= 2 else None
|
||||||
|
seed = int(params[2], 0) if len(params) >= 3 else None
|
||||||
|
checksum = int(params[3], 0) if len(params) >= 4 else None
|
||||||
|
return (disabled, dd_mode, seed, checksum)
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='SC64 control software')
|
parser = argparse.ArgumentParser(description='SC64 control software')
|
||||||
parser.add_argument('--backup-firmware', metavar='file', help='backup SC64 firmware and write it to specified file')
|
parser.add_argument('--backup-firmware', metavar='file', help='backup SC64 firmware and write it to specified file')
|
||||||
parser.add_argument('--update-firmware', metavar='file', help='update SC64 firmware from specified file')
|
parser.add_argument('--update-firmware', metavar='file', help='update SC64 firmware from specified file')
|
||||||
@ -750,7 +797,7 @@ if __name__ == '__main__':
|
|||||||
parser.add_argument('--boot', type=SC64.BootMode, action=EnumAction, help='set boot mode')
|
parser.add_argument('--boot', type=SC64.BootMode, action=EnumAction, help='set boot mode')
|
||||||
parser.add_argument('--tv', type=SC64.TVType, action=EnumAction, help='force TV type to set value')
|
parser.add_argument('--tv', type=SC64.TVType, action=EnumAction, help='force TV type to set value')
|
||||||
parser.add_argument('--cic', type=SC64.CICSeed, action=EnumAction, help='force CIC seed to set value')
|
parser.add_argument('--cic', type=SC64.CICSeed, action=EnumAction, help='force CIC seed to set value')
|
||||||
parser.add_argument('--cic-params', metavar='disabled,dd_mode,seed,checksum', help='set CIC emulation parameters')
|
parser.add_argument('--cic-params', metavar='disabled,[dd_mode,[seed,[checksum]]]', type=cic_params_type, help='set CIC emulation parameters')
|
||||||
parser.add_argument('--rtc', action='store_true', help='update clock in SC64 to system time')
|
parser.add_argument('--rtc', action='store_true', help='update clock in SC64 to system time')
|
||||||
parser.add_argument('--no-shadow', action='store_false', help='do not put last 128 kB of ROM inside flash memory (can corrupt non EEPROM saves)')
|
parser.add_argument('--no-shadow', action='store_false', help='do not put last 128 kB of ROM inside flash memory (can corrupt non EEPROM saves)')
|
||||||
parser.add_argument('--rom', metavar='file', help='upload ROM from specified file')
|
parser.add_argument('--rom', metavar='file', help='upload ROM from specified file')
|
||||||
@ -760,7 +807,8 @@ if __name__ == '__main__':
|
|||||||
parser.add_argument('--ddipl', metavar='file', help='upload 64DD IPL from specified file')
|
parser.add_argument('--ddipl', metavar='file', help='upload 64DD IPL from specified file')
|
||||||
parser.add_argument('--disk', metavar='file', action='append', help='path to 64DD disk (.ndd format), can be specified multiple times')
|
parser.add_argument('--disk', metavar='file', action='append', help='path to 64DD disk (.ndd format), can be specified multiple times')
|
||||||
parser.add_argument('--isv', type=lambda x: int(x, 0), default=0, help='enable IS-Viewer64 support at provided ROM offset')
|
parser.add_argument('--isv', type=lambda x: int(x, 0), default=0, help='enable IS-Viewer64 support at provided ROM offset')
|
||||||
parser.add_argument('--debug', action='store_true', help='run debug loop (required for 64DD and IS-Viewer64)')
|
parser.add_argument('--gdb', metavar='port', type=int, help='expose socket port for GDB debugging')
|
||||||
|
parser.add_argument('--debug', action='store_true', help='run debug loop (required for 64DD, IS-Viewer64 and GDB)')
|
||||||
parser.add_argument('--download-memory', metavar='file', help='download whole memory space and write it to specified file')
|
parser.add_argument('--download-memory', metavar='file', help='download whole memory space and write it to specified file')
|
||||||
|
|
||||||
if (len(sys.argv) <= 1):
|
if (len(sys.argv) <= 1):
|
||||||
@ -843,19 +891,16 @@ if __name__ == '__main__':
|
|||||||
print('done')
|
print('done')
|
||||||
|
|
||||||
if (args.cic_params != None):
|
if (args.cic_params != None):
|
||||||
# TODO: calculate checksum in script
|
(disabled, dd_mode, seed, checksum) = args.cic_params
|
||||||
params = args.cic_params.split(',')
|
(seed, checksum) = sc64.set_cic_parameters(disabled, dd_mode, seed, checksum)
|
||||||
if (len(params) != 4):
|
print('CIC parameters set to [', end='')
|
||||||
raise ValueError('Incorrect number of CIC parameters')
|
print(f'{"DISABLED" if disabled else "ENABLED"}, ', end='')
|
||||||
disabled = (params[0] != '0')
|
print(f'{"DDIPL" if dd_mode else "ROM"}, ', end='')
|
||||||
dd_mode = (params[1] != '0')
|
print(f'seed: 0x{seed:02X}, checksum: 0x{checksum:12X}', end='')
|
||||||
seed = int(params[2])
|
print(']')
|
||||||
checksum = int(params[3]).to_bytes(6, byteorder='big', signed=False)
|
|
||||||
sc64.set_cic_parameters(disabled, dd_mode, seed, checksum)
|
|
||||||
print(f'CIC parameters set to [{"DISABLED, " if disabled else ""}{"DDIPL" if dd_mode else "ROM"}, seed: 0x{seed:02X}, checksum: 0x{int(params[3]):12X}]')
|
|
||||||
|
|
||||||
if (args.debug):
|
if (args.debug):
|
||||||
sc64.debug_loop(isv=args.isv, disks=args.disk)
|
sc64.debug_loop(isv=args.isv, disks=args.disk, gdb_port=args.gdb)
|
||||||
|
|
||||||
if (args.backup_save):
|
if (args.backup_save):
|
||||||
with open(args.backup_save, 'wb') as f:
|
with open(args.backup_save, 'wb') as f:
|
||||||
|
Loading…
Reference in New Issue
Block a user