1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-11-26 20:22:17 +00:00

readd changes, made one line work in py3.11, otherwise minor

This commit is contained in:
bilditup1 2023-12-04 23:46:41 -05:00
parent 62fd26b622
commit d8739fc514

View file

@ -55,7 +55,7 @@ from tkinter import filedialog, messagebox, font, scrolledtext
from tqdm import tqdm from tqdm import tqdm
from argparse import ArgumentParser, RawTextHelpFormatter, ArgumentDefaultsHelpFormatter from argparse import ArgumentParser, RawTextHelpFormatter
from io import BufferedWriter from io import BufferedWriter
from typing import Generator, Any, Callable from typing import Generator, Any, Callable
@ -320,6 +320,7 @@ g_terminalColors: bool = False
g_outputDir: str = '' g_outputDir: str = ''
g_logLevelIntVar: tk.IntVar | None = None g_logLevelIntVar: tk.IntVar | None = None
g_logToFileBoolVar: tk.BooleanVar | None = None g_logToFileBoolVar: tk.BooleanVar | None = None
g_logPath: str = '' g_logPath: str = ''
g_pathSep: str = '' g_pathSep: str = ''
@ -632,6 +633,9 @@ def utilsLogException(exception_str: str) -> None:
if (not g_cliMode) and (g_logger is not None): if (not g_cliMode) and (g_logger is not None):
g_logger.debug(exception_str) g_logger.debug(exception_str)
def utilsGetExt(path_arg: str) -> str:
return os.path.splitext(path_arg)[1][1:]
def utilsGetPath(path_arg: str, fallback_path: str, is_file: bool, create: bool = False) -> str: def utilsGetPath(path_arg: str, fallback_path: str, is_file: bool, create: bool = False) -> str:
path = os.path.abspath(os.path.expanduser(os.path.expandvars(path_arg if path_arg else fallback_path))) path = os.path.abspath(os.path.expanduser(os.path.expandvars(path_arg if path_arg else fallback_path)))
@ -773,7 +777,7 @@ def usbGetDeviceEndpoints() -> bool:
global g_usbEpIn, g_usbEpOut, g_usbEpMaxPacketSize, g_usbVer global g_usbEpIn, g_usbEpOut, g_usbEpMaxPacketSize, g_usbVer
assert g_logger is not None assert g_logger is not None
assert g_stopEvent is not None #assert g_stopEvent is not None
cur_dev: Generator[usb.core.Device, Any, None] | None = None cur_dev: Generator[usb.core.Device, Any, None] | None = None
prev_dev: usb.core.Device | None = None prev_dev: usb.core.Device | None = None
@ -944,7 +948,7 @@ def usbHandleSendFileProperties(cmd_block: bytes) -> int | None:
if not g_nspTransferMode and not g_extractedFsDumpMode: if not g_nspTransferMode and not g_extractedFsDumpMode:
fp = filename.split('/') # fp[0] is '/' character fp = filename.split('/') # fp[0] is '/' character
fp_len = len(fp) fp_len = len(fp)
ext = filename[-3:] ext = utilsGetExt(filename)
utilsInitTransferVars(file_size) utilsInitTransferVars(file_size)
g_logger.info("\nTransfer started!") g_logger.info("\nTransfer started!")
if (fp_len >= 2): # if file has parent directories if (fp_len >= 2): # if file has parent directories
@ -973,7 +977,7 @@ def usbHandleSendFileProperties(cmd_block: bytes) -> int | None:
g_logger.info(f'\t{fp[4][:fp[4].index(".")]}') g_logger.info(f'\t{fp[4][:fp[4].index(".")]}')
g_logger.info(f'Size:\t{g_formattedFileSize:.2f} {g_formattedFileUnit}\n') g_logger.info(f'Size:\t{g_formattedFileSize:.2f} {g_formattedFileUnit}\n')
case 'NCA' | 'HFS': case 'NCA' | 'HFS':
printable_ext = fp[fp_len-1][fp[fp_len-1].index(".")+1:] if fp[1] == 'HFS' else ext printable_ext = ext#fp[fp_len-1][fp[fp_len-1].index(".")+1:] if fp[1] == 'HFS' else ext
g_logger.info(f'\nType:\t{fp[1]} ({fp[2]}) [{printable_ext.upper()}]') g_logger.info(f'\nType:\t{fp[1]} ({fp[2]}) [{printable_ext.upper()}]')
g_logger.info(f'Src:\t{fp[3][:fp[3].index("[")]}') g_logger.info(f'Src:\t{fp[3][:fp[3].index("[")]}')
g_logger.info(f'\t{fp[3][fp[3].index("["):]}') g_logger.info(f'\t{fp[3][fp[3].index("["):]}')
@ -986,10 +990,10 @@ def usbHandleSendFileProperties(cmd_block: bytes) -> int | None:
g_logger.warning(f'\n\tNovel source!!! {fp[1]}???') g_logger.warning(f'\n\tNovel source!!! {fp[1]}???')
g_logger.info:(f'{filename}') g_logger.info:(f'{filename}')
g_logger.info(f'Size:\t{g_formattedFileSize:.2f} {g_formattedFileUnit}\n') g_logger.info(f'Size:\t{g_formattedFileSize:.2f} {g_formattedFileUnit}\n')
else: # if file is just a file with no parent dirs else: # If file is just a file with no parent dirs
if (ext == 'bin'): # Thusfar the only such case if (ext == 'bin'): # Thusfar the only such case
g_logger.info(f'\nType:\tConsole LAFW BLOB or similar (BIN)') g_logger.info(f'\nType:\tConsole LAFW BLOB or similar (BIN)')
g_logger.info(f'File:\t{filename.rsplit('/', 1)[-1]}') g_logger.info(f'File:\t'+filename.rsplit('/', 1)[-1])
g_logger.info(f'Size:\t{g_formattedFileSize:.2f} {g_formattedFileUnit}') g_logger.info(f'Size:\t{g_formattedFileSize:.2f} {g_formattedFileUnit}')
else: # If we ever get here it is time for more work else: # If we ever get here it is time for more work
g_logger.warning(f'\n\tNovel source!!!') g_logger.warning(f'\n\tNovel source!!!')
@ -1035,13 +1039,7 @@ def usbHandleSendFileProperties(cmd_block: bytes) -> int | None:
if (not g_nspTransferMode) or (g_nspFile is None): if (not g_nspTransferMode) or (g_nspFile is None):
# Generate full, absolute path to the destination file. # Generate full, absolute path to the destination file.
fullpath = os.path.abspath(g_outputDir + os.path.sep + filename) fullpath = os.path.abspath(g_outputDir + os.path.sep + filename)
printable_fullpath = (fullpath[4:] if g_isWindows else fullpath) printable_fullpath = utilsStripWinPrefix(fullpath)
printable_fullpath = (fullpath[4:] if g_isWindows else fullpath)
# Unconditionally enable long paths in Windows.
# if g_isWindows:
# fullpath = utilsGetWinFullPath(fullpath);
# Get parent directory path. # Get parent directory path.
dirpath = os.path.dirname(fullpath) dirpath = os.path.dirname(fullpath)
@ -1080,7 +1078,7 @@ def usbHandleSendFileProperties(cmd_block: bytes) -> int | None:
fullpath = g_nspFilePath fullpath = g_nspFilePath
dirpath = os.path.dirname(fullpath) dirpath = os.path.dirname(fullpath)
printable_fullpath = (fullpath[4:] if g_isWindows else fullpath) printable_fullpath = utilsStripWinPrefix(fullpath)
# Check if we're dealing with an empty file or with the first SendFileProperties command from a NSP. # Check if we're dealing with an empty file or with the first SendFileProperties command from a NSP.
if (not file_size) or (g_nspTransferMode and file_size == g_nspSize): if (not file_size) or (g_nspTransferMode and file_size == g_nspSize):
@ -1277,6 +1275,7 @@ def usbHandleEndSession(cmd_block: bytes) -> int:
def usbHandleStartExtractedFsDump(cmd_block: bytes) -> int: def usbHandleStartExtractedFsDump(cmd_block: bytes) -> int:
assert g_logger is not None assert g_logger is not None
global g_isWindows, g_outputDir, g_extractedFsDumpMode, g_extractedFsAbsRoot, g_formattedFileSize, g_formattedFileUnit, g_fileSizeMiB, g_startTime
g_logger.debug(f'Received StartExtractedFsDump ({USB_CMD_START_EXTRACTED_FS_DUMP:02X}) command.') g_logger.debug(f'Received StartExtractedFsDump ({USB_CMD_START_EXTRACTED_FS_DUMP:02X}) command.')
@ -1318,8 +1317,7 @@ def usbHandleStartExtractedFsDump(cmd_block: bytes) -> int:
else: else:
g_logger.debug(f'Starting extracted FS dump (size 0x{extracted_fs_size:X}, output relative path "{extracted_fs_root_path}").') g_logger.debug(f'Starting extracted FS dump (size 0x{extracted_fs_size:X}, output relative path "{extracted_fs_root_path}").')
g_extractedFsAbsRoot = os.path.abspath(g_outputDir + os.path.sep + extracted_fs_root_path) g_extractedFsAbsRoot = utilsStripWinPrefix(os.path.abspath(g_outputDir + os.path.sep + extracted_fs_root_path))
g_extractedFsAbsRoot = utilsStripWinPrefix(g_extractedFsAbsRoot) #if g_isWindows else g_extractedFsAbsRoot
g_extractedFsDumpMode = True g_extractedFsDumpMode = True
g_startTime = time.time() g_startTime = time.time()
@ -1328,8 +1326,9 @@ def usbHandleStartExtractedFsDump(cmd_block: bytes) -> int:
def usbHandleEndExtractedFsDump(cmd_block: bytes) -> int: def usbHandleEndExtractedFsDump(cmd_block: bytes) -> int:
assert g_logger is not None assert g_logger is not None
global g_extractedFsDumpMode, g_extractedFsAbsRoot
g_logger.debug(f'Received EndExtractedFsDump ({USB_CMD_END_EXTRACTED_FS_DUMP:02X}) command.') g_logger.debug(f'Received EndExtractedFsDump ({USB_CMD_END_EXTRACTED_FS_DUMP:02X}) command.')
g_logger.info(f'Finished extracted FS dump.') g_logger.debug(f'\nFinished extracted FS dump.')
if not g_logVerbose: if not g_logVerbose:
g_logger.info(f'\nExtracted FS dump complete!\n') g_logger.info(f'\nExtracted FS dump complete!\n')
utilsLogTransferStats(time.time() - g_startTime) utilsLogTransferStats(time.time() - g_startTime)
@ -1438,25 +1437,10 @@ def uiStopServer() -> None:
def uiStartServer() -> None: def uiStartServer() -> None:
assert g_tkDirText is not None uiUpdateOutputDir()
# Set new log path for this session if logging to file is turned on.
g_outputDir = g_tkDirText.get('1.0', tk.END).strip() if g_logToFile:
if not g_outputDir: utilsUpdateLogPath()
# We should never reach this, honestly.
messagebox.showerror('Error', 'You must provide an output directory!', parent=g_tkRoot)
return
# Unconditionally enable 32-bit paths on Windows.
if g_isWindows:
g_outputDir = '\\\\?\\' + g_outputDir
# Make sure the full directory tree exists.
try:
os.makedirs(g_outputDir, exist_ok=True)
except:
utilsLogException(traceback.format_exc())
messagebox.showerror('Error', 'Unable to create full output directory tree!', parent=g_tkRoot)
return
# Update UI. # Update UI.
uiToggleElements(False) uiToggleElements(False)
@ -1473,6 +1457,7 @@ def uiToggleElements(flag: bool) -> None:
assert g_tkChooseDirButton is not None assert g_tkChooseDirButton is not None
assert g_tkServerButton is not None assert g_tkServerButton is not None
assert g_tkCanvas is not None assert g_tkCanvas is not None
assert g_tkLogToFileCheckbox is not None
assert g_tkVerboseCheckbox is not None assert g_tkVerboseCheckbox is not None
if flag: if flag:
@ -1554,12 +1539,14 @@ def uiHandleLogToFileCheckbox() -> None:
assert g_logToFileBoolVar is not None assert g_logToFileBoolVar is not None
global g_logToFile global g_logToFile
g_logToFile = g_logToFileBoolVar.get() g_logToFile = g_logToFileBoolVar.get()
return
def uiHandleVerboseCheckbox() -> None: def uiHandleVerboseCheckbox() -> None:
assert g_logger is not None assert g_logger is not None
assert g_logLevelIntVar is not None assert g_logLevelIntVar is not None
g_logger.setLevel(g_logLevelIntVar.get()) global g_logVerbose
logLevel=g_logLevelIntVar.get()
g_logger.setLevel(logLevel)
g_logVerbose = True if(logLevel == logging.DEBUG) else False
def uiInitialize() -> None: def uiInitialize() -> None:
global SCALE, g_logLevelIntVar, g_logToFileBoolVar, g_logToFile, g_logVerbose global SCALE, g_logLevelIntVar, g_logToFileBoolVar, g_logToFile, g_logVerbose
@ -1703,11 +1690,10 @@ def uiInitialize() -> None:
def cliInitialize() -> None: def cliInitialize() -> None:
global g_progressBarWindow, g_outputDir, g_logToFile global g_progressBarWindow, g_outputDir, g_logToFile
assert g_logger is not None assert g_logger is not None
# Unconditionally enable long paths on Windows. # Unconditionally enable long paths on Windows.
g_outputDir = utilsGetWinFullPath(g_outputDir) #if g_isWindows else g_outputDir g_outputDir = utilsGetWinFullPath(g_outputDir)
# Determines whether to use colors in terminal and sets up accordingly. # Determines whether to use colors in terminal and sets up accordingly.
utilsSetupTerminal() utilsSetupTerminal()
@ -1723,13 +1709,8 @@ def cliInitialize() -> None:
bar_format = '{percentage:.2f}% |{bar}| {n:.2f}/{total:.2f} [{elapsed}<{remaining}, {rate_fmt}]' bar_format = '{percentage:.2f}% |{bar}| {n:.2f}/{total:.2f} [{elapsed}<{remaining}, {rate_fmt}]'
g_progressBarWindow = ProgressBarWindow(bar_format) g_progressBarWindow = ProgressBarWindow(bar_format)
# Print info. # Log basic info about the script and settings.
g_logger.info(f'\n{SCRIPT_TITLE}. {COPYRIGHT_TEXT}.') utilsLogBasicScriptInfo()
g_logger.info(f'Output directory: "{g_outputDir}".\n')
# Unconditionally enable 32-bit paths on Windows.
if g_isWindows:
g_outputDir = '\\\\?\\' + g_outputDir
# Start USB command handler directly. # Start USB command handler directly.
usbCommandHandler() usbCommandHandler()
@ -1740,10 +1721,10 @@ def main() -> int:
# Disable warnings. # Disable warnings.
warnings.filterwarnings("ignore") warnings.filterwarnings("ignore")
# Parse command line arguments. parser = ArgumentParser(formatter_class=RawTextHelpFormatter, description=SCRIPT_TITLE + '. ' + COPYRIGHT_TEXT + '.')
parser = ArgumentParser(description=SCRIPT_TITLE + '. ' + COPYRIGHT_TEXT + '.')
parser.add_argument('-c', '--cli', required=False, action='store_true', default=False, help='Start the script in CLI mode.') parser.add_argument('-c', '--cli', required=False, action='store_true', default=False, help='Start the script in CLI mode.')
parser.add_argument('-o', '--outdir', required=False, type=str, metavar='DIR', help=f'Path to output directory. Defaults to "{DEFAULT_DIR}".') parser.add_argument('-o', '--outdir', required=False, type=str, metavar='DIR', help='Path to output directory; will attempt to create if non-existent.\nDefaults to "' + DEFAULT_DIR + '".')
parser.add_argument('-l', '--log', required=False, action='store_true', default=False, help='Enables logging to file in output directory in CLI mode.')
parser.add_argument('-v', '--verbose', required=False, action='store_true', default=False, help='Enable verbose output.') parser.add_argument('-v', '--verbose', required=False, action='store_true', default=False, help='Enable verbose output.')
args = parser.parse_args() args = parser.parse_args()
@ -1797,7 +1778,8 @@ if __name__ == "__main__":
ret = main() ret = main()
except KeyboardInterrupt: except KeyboardInterrupt:
time.sleep(0.2) time.sleep(0.2)
print('\nScript interrupted.') g_logger.info("Host script exited!")
if g_isWindows10: print(COLOR_RESET)
except: except:
utilsLogException(traceback.format_exc()) utilsLogException(traceback.format_exc())