1
0
Fork 0

Light code refactoring

This commit is contained in:
JoshuaMK 2020-12-06 01:53:18 -06:00
parent 651448b6dd
commit 8e1bd5d38b
2 changed files with 231 additions and 168 deletions

View file

@ -1,4 +1,4 @@
#Written by JoshuaMK 2020 # Written by JoshuaMK 2020
import atexit import atexit
import logging import logging
@ -49,6 +49,7 @@ __version__ = "v7.1.0"
TMPDIR = Path(tempfile.mkdtemp(prefix="GeckoLoader-")) TMPDIR = Path(tempfile.mkdtemp(prefix="GeckoLoader-"))
@atexit.register @atexit.register
def clean_tmp_resources(): def clean_tmp_resources():
tmpfolder = TMPDIR.parent tmpfolder = TMPDIR.parent
@ -56,10 +57,12 @@ def clean_tmp_resources():
if entry.name.startswith("GeckoLoader-"): if entry.name.startswith("GeckoLoader-"):
shutil.rmtree(entry, ignore_errors=True) shutil.rmtree(entry, ignore_errors=True)
class GeckoLoaderCli(CommandLineParser): class GeckoLoaderCli(CommandLineParser):
def __init__(self, name, version=None, description=''): def __init__(self, name, version=None, description=''):
super().__init__(prog=(f"{name} {version}"), description=description, allow_abbrev=False) super().__init__(prog=(f"{name} {version}"),
description=description, allow_abbrev=False)
self.__version__ = version self.__version__ = version
self.__doc__ = description self.__doc__ = description
@ -67,7 +70,7 @@ class GeckoLoaderCli(CommandLineParser):
self.add_argument('codelist', help='Folder or Gecko GCT|TXT file') self.add_argument('codelist', help='Folder or Gecko GCT|TXT file')
self.add_argument('-a', '--alloc', self.add_argument('-a', '--alloc',
help='Define the size of the code allocation in hex, only applies when using the ARENA space', help='Define the size of the code allocation in hex, only applies when using the ARENA space',
metavar ='SIZE') metavar='SIZE')
self.add_argument('-i', '--init', self.add_argument('-i', '--init',
help='Define where GeckoLoader is initialized in hex', help='Define where GeckoLoader is initialized in hex',
metavar='ADDRESS') metavar='ADDRESS')
@ -130,7 +133,8 @@ class GeckoLoaderCli(CommandLineParser):
return self.__doc__ return self.__doc__
def print_splash(self): def print_splash(self):
helpMessage = 'Try option -h for more info on this program'.center(64, ' ') helpMessage = 'Try option -h for more info on this program'.center(
64, ' ')
version = self.__version__.rjust(9, ' ') version = self.__version__.rjust(9, ' ')
logo = [' ', logo = [' ',
@ -159,7 +163,8 @@ class GeckoLoaderCli(CommandLineParser):
' '] ' ']
for line in logo: for line in logo:
print(color_text(line, [('', TREDLIT), ('╔╚╝╗═', TRED)], TGREENLIT)) print(color_text(
line, [('', TREDLIT), ('╔╚╝╗═', TRED)], TGREENLIT))
def check_updates(self): def check_updates(self):
repoChecker = Updater('JoshuaMKW', 'GeckoLoader') repoChecker = Updater('JoshuaMKW', 'GeckoLoader')
@ -167,82 +172,30 @@ class GeckoLoaderCli(CommandLineParser):
tag, status = repoChecker.get_newest_version() tag, status = repoChecker.get_newest_version()
if status is False: if status is False:
self.error(color_text(tag + '\n', defaultColor=TREDLIT), print_usage=False) self.error(color_text(tag + '\n', defaultColor=TREDLIT),
print_usage=False)
print('') print('')
if LooseVersion(tag) > LooseVersion(self.__version__): if LooseVersion(tag) > LooseVersion(self.__version__):
print(color_text(f' :: A new update is live at {repoChecker.gitReleases.format(repoChecker.owner, repoChecker.repo)}', defaultColor=TYELLOWLIT)) print(color_text(
print(color_text(f' :: Current version is "{self.__version__}", Most recent version is "{tag}"', defaultColor=TYELLOWLIT)) f' :: A new update is live at {repoChecker.gitReleases.format(repoChecker.owner, repoChecker.repo)}', defaultColor=TYELLOWLIT))
print(color_text(
f' :: Current version is "{self.__version__}", Most recent version is "{tag}"', defaultColor=TYELLOWLIT))
elif LooseVersion(tag) < LooseVersion(self.__version__): elif LooseVersion(tag) < LooseVersion(self.__version__):
print(color_text(' :: No update available', defaultColor=TGREENLIT)) print(color_text(' :: No update available', defaultColor=TGREENLIT))
print(color_text(f' :: Current version is "{self.__version__}(dev)", Most recent version is "{tag}(release)"', defaultColor=TGREENLIT)) print(color_text(
f' :: Current version is "{self.__version__}(dev)", Most recent version is "{tag}(release)"', defaultColor=TGREENLIT))
else: else:
print(color_text(' :: No update available', defaultColor=TGREENLIT)) print(color_text(' :: No update available', defaultColor=TGREENLIT))
print(color_text(f' :: Current version is "{self.__version__}(release)", Most recent version is "{tag}(release)"', defaultColor=TGREENLIT)) print(color_text(
f' :: Current version is "{self.__version__}(release)", Most recent version is "{tag}(release)"', defaultColor=TGREENLIT))
print('') print('')
def _validate_args(self, args) -> tuple: def _validate_args(self, args) -> dict:
if args.alloc: dolFile = Path(args.dolfile).resolve()
try: codeList = Path(args.codelist).resolve()
_allocation = int(args.alloc, 16)
except ValueError:
self.error(color_text('The allocation was invalid\n', defaultColor=TREDLIT))
else:
_allocation = None
if args.hookaddress:
if 0x80000000 > int(args.hookaddress, 16) >= 0x81800000:
self.error(color_text('The codehandler hook address was beyond bounds\n', defaultColor=TREDLIT))
else:
try:
_codehook = int(args.hookaddress, 16)
except ValueError:
self.error(color_text('The codehandler hook address was invalid\n', defaultColor=TREDLIT))
else:
_codehook = None
if args.handler == CodeHandler.Types.MINI:
codeHandlerFile = Path('bin/codehandler-mini.bin')
elif args.handler == CodeHandler.Types.FULL:
codeHandlerFile = Path('bin/codehandler.bin')
else:
self.error(color_text(f'Codehandler type {args.handler} is invalid\n', defaultColor=TREDLIT))
if not os.path.isfile(args.dolfile):
self.error(color_text(f'File "{args.dolfile}" does not exist\n', defaultColor=TREDLIT))
if not os.path.exists(args.codelist):
self.error(color_text(f'File/folder "{args.codelist}" does not exist\n', defaultColor=TREDLIT))
return _allocation, _codehook, codeHandlerFile
def _exec(self, args, tmpdir):
_allocation, _codehook, codeHandlerFile = self._validate_args(args)
try:
with open(args.dolfile, "rb") as dol:
dolFile = DolFile(dol)
with resource_path(str(codeHandlerFile)).open("rb") as handler:
codeHandler = CodeHandler(handler)
codeHandler.allocation = _allocation
codeHandler.hookAddress = _codehook
codeHandler.hookType = args.hooktype
codeHandler.includeAll = args.txtcodes.lower() == 'all'
codeHandler.optimizeList = args.optimize
with resource_path("bin/geckoloader.bin").open("rb") as kernelfile:
geckoKernel = KernelLoader(kernelfile, cli)
if args.init is not None:
geckoKernel.initAddress = int(args.init, 16)
geckoKernel.verbosity = args.verbose
geckoKernel.quiet = args.quiet
geckoKernel.encrypt = args.encrypt
geckoKernel.protect = args.protect
if args.dest: if args.dest:
dest = Path(args.dest).resolve() dest = Path(args.dest).resolve()
@ -251,14 +204,92 @@ class GeckoLoaderCli(CommandLineParser):
else: else:
dest = Path.cwd() / "geckoloader-build" / args.dolfile.name dest = Path.cwd() / "geckoloader-build" / args.dolfile.name
if not dest.parent.exists(): if args.alloc:
dest.parent.mkdir(parents=True, exist_ok=True) try:
_allocation = int(args.alloc, 16)
except ValueError:
self.error(color_text(
'The allocation was invalid\n', defaultColor=TREDLIT))
else:
_allocation = None
geckoKernel.build(Path(args.codelist), dolFile, codeHandler, TMPDIR, dest) if args.hookaddress:
if 0x80000000 > int(args.hookaddress, 16) >= 0x81800000:
self.error(color_text(
'The codehandler hook address was beyond bounds\n', defaultColor=TREDLIT))
else:
try:
_codehook = int(args.hookaddress, 16)
except ValueError:
self.error(color_text(
'The codehandler hook address was invalid\n', defaultColor=TREDLIT))
else:
_codehook = None
if args.handler == CodeHandler.Types.MINI:
codeHandlerFile = Path('bin/codehandler-mini.bin')
elif args.handler == CodeHandler.Types.FULL:
codeHandlerFile = Path('bin/codehandler.bin')
else:
self.error(color_text(
f'Codehandler type {args.handler} is invalid\n', defaultColor=TREDLIT))
if not dolFile.is_file():
self.error(color_text(
f'File "{dolFile}" does not exist\n', defaultColor=TREDLIT))
if not codeList.exists():
self.error(color_text(
f'File/folder "{codeList}" does not exist\n', defaultColor=TREDLIT))
return {"dol": dolFile,
"codepath": codeList,
"codehandler": codeHandlerFile,
"destination": dest,
"allocation": _allocation,
"hookaddress": _codehook,
"hooktype": args.hooktype,
"initaddress": None if args.init is None else int(args.init, 16),
"includeall": args.txtcodes.lower() == "all",
"optimize": args.optimize,
"protect": args.protect,
"encrypt": args.encrypt,
"verbosity": args.verbose,
"quiet": args.quiet}
def _exec(self, args, tmpdir):
context = self._validate_args(args)
try:
with context["dol"].open("rb") as dol:
dolFile = DolFile(dol)
with resource_path(context["codehandler"]).open("rb") as handler:
codeHandler = CodeHandler(handler)
codeHandler.allocation = context["allocation"]
codeHandler.hookAddress = context["hookaddress"]
codeHandler.hookType = context["hooktype"]
codeHandler.includeAll = context["includeall"]
codeHandler.optimizeList = context["optimize"]
with resource_path("bin/geckoloader.bin").open("rb") as kernelfile:
geckoKernel = KernelLoader(kernelfile, cli)
geckoKernel.initAddress = context["initaddress"]
geckoKernel.verbosity = context["verbosity"]
geckoKernel.quiet = context["quiet"]
geckoKernel.encrypt = context["encrypt"]
geckoKernel.protect = context["protect"]
if not context["destination"].parent.exists():
context["destination"].parent.mkdir(parents=True, exist_ok=True)
geckoKernel.build(context["codepath"], dolFile,
codeHandler, TMPDIR, context["destination"])
except FileNotFoundError as e: except FileNotFoundError as e:
self.error(color_text(e, defaultColor=TREDLIT)) self.error(color_text(e, defaultColor=TREDLIT))
class GUI(object): class GUI(object):
class Dialogs: class Dialogs:
@ -289,8 +320,10 @@ class GUI(object):
if not get_program_folder("GeckoLoader").exists(): if not get_program_folder("GeckoLoader").exists():
get_program_folder("GeckoLoader").mkdir() get_program_folder("GeckoLoader").mkdir()
hdlr = logging.FileHandler(get_program_folder("GeckoLoader") / "error.log") hdlr = logging.FileHandler(
formatter = logging.Formatter("\n%(levelname)s (%(asctime)s): %(message)s") get_program_folder("GeckoLoader") / "error.log")
formatter = logging.Formatter(
"\n%(levelname)s (%(asctime)s): %(message)s")
hdlr.setFormatter(formatter) hdlr.setFormatter(formatter)
self.log.addHandler(hdlr) self.log.addHandler(hdlr)
@ -298,7 +331,7 @@ class GUI(object):
if dialog_type == "aboutqt": if dialog_type == "aboutqt":
QtWidgets.QMessageBox.aboutQt(self.app.activeWindow()) QtWidgets.QMessageBox.aboutQt(self.app.activeWindow())
elif dialog_type == "aboutGeckoLoader": elif dialog_type == "aboutGeckoLoader":
desc = "".join([ "GeckoLoader is a cross platform tool designed to give ", desc = "".join(["GeckoLoader is a cross platform tool designed to give ",
"the user the most efficient codespace usage possible.\n\n ", "the user the most efficient codespace usage possible.\n\n ",
"This application supports various features, such as ", "This application supports various features, such as ",
"pre-patching codes, dynamic codehandler hooks, codespace ", "pre-patching codes, dynamic codehandler hooks, codespace ",
@ -307,9 +340,10 @@ class GUI(object):
f"Current running version: {self.version}\n\n" f"Current running version: {self.version}\n\n"
"Copyright (c) 2020\n\n", "Copyright (c) 2020\n\n",
"JoshuaMK <joshuamkw2002@gmail.com> \n\n", "JoshuaMK <joshuamkw2002@gmail.com> \n\n",
"All rights reserved." ]) "All rights reserved."])
QtWidgets.QMessageBox.about(self.app.activeWindow(), "About GeckoLoader", desc) QtWidgets.QMessageBox.about(
self.app.activeWindow(), "About GeckoLoader", desc)
elif dialog_type == "Preferences": elif dialog_type == "Preferences":
self.uiprefs.show() self.uiprefs.show()
else: else:
@ -338,7 +372,7 @@ class GUI(object):
else: else:
return False, "The file does not exist!" return False, "The file does not exist!"
def _load_codes(self, isFolder: bool=False) -> tuple: def _load_codes(self, isFolder: bool = False) -> tuple:
if not isFolder: if not isFolder:
if self.codePath[0] is None: # Just start in the home directory if self.codePath[0] is None: # Just start in the home directory
fname = str(QtWidgets.QFileDialog.getOpenFileName(self.ui, "Open Codelist", str(Path.home()), fname = str(QtWidgets.QFileDialog.getOpenFileName(self.ui, "Open Codelist", str(Path.home()),
@ -422,7 +456,8 @@ class GUI(object):
self.uiexSettings.encryptCodes.setChecked(p["encrypt"]) self.uiexSettings.encryptCodes.setChecked(p["encrypt"])
self.uiexSettings.codehookLineEdit.setText(p["hookAddress"]) self.uiexSettings.codehookLineEdit.setText(p["hookAddress"])
self.uiexSettings.kernelHookLineEdit.setText(p["initAddress"]) self.uiexSettings.kernelHookLineEdit.setText(p["initAddress"])
self.uiexSettings.verbositySelect.setCurrentIndex(p["verbosity"]) self.uiexSettings.verbositySelect.setCurrentIndex(
p["verbosity"])
return True, None return True, None
@ -549,7 +584,8 @@ class GUI(object):
self.prefs.get("qtstyle"), self.prefs.get("qtstyle"),
flags=QtCore.Qt.MatchFixedString)) flags=QtCore.Qt.MatchFixedString))
self.uiprefs.qtdarkButton.setChecked(self.prefs.get("darktheme")) self.uiprefs.qtdarkButton.setChecked(
self.prefs.get("darktheme"))
self.update_theme() self.update_theme()
except FileNotFoundError: except FileNotFoundError:
@ -568,7 +604,8 @@ class GUI(object):
self.log.exception(e) self.log.exception(e)
def load_qtstyle(self, style, first_style_load=False): def load_qtstyle(self, style, first_style_load=False):
self.style_log.append([self.app.style, self.uiprefs.qtstyleSelect.currentText()]) self.style_log.append(
[self.app.style, self.uiprefs.qtstyleSelect.currentText()])
if len(self.style_log) > 2: if len(self.style_log) > 2:
self.style_log.pop(0) self.style_log.pop(0)
@ -606,14 +643,16 @@ class GUI(object):
_status = True _status = True
icon = QtGui.QIcon() icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(str(resource_path(Path("bin/icon.ico")))), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon.addPixmap(QtGui.QPixmap(
str(resource_path(Path("bin/icon.ico")))), QtGui.QIcon.Normal, QtGui.QIcon.Off)
if _status is False: if _status is False:
reply = QtWidgets.QErrorMessage() reply = QtWidgets.QErrorMessage()
reply.setWindowIcon(icon) reply.setWindowIcon(icon)
reply.setWindowTitle("Response Error") reply.setWindowTitle("Response Error")
reply.setText(self._remove_ansi(_errpipe.getvalue())) reply.setText(self._remove_ansi(_errpipe.getvalue()))
reply.setInformativeText("Make sure you have an internet connection") reply.setInformativeText(
"Make sure you have an internet connection")
reply.setIcon(QtWidgets.QMessageBox.Warning) reply.setIcon(QtWidgets.QMessageBox.Warning)
reply.setStandardButtons(QtWidgets.QMessageBox.Ok) reply.setStandardButtons(QtWidgets.QMessageBox.Ok)
reply.exec_() reply.exec_()
@ -621,7 +660,8 @@ class GUI(object):
reply = QtWidgets.QMessageBox() reply = QtWidgets.QMessageBox()
reply.setWindowIcon(icon) reply.setWindowIcon(icon)
reply.setWindowTitle("Update Info") reply.setWindowTitle("Update Info")
reply.setText(self._remove_ansi(_outpipe.getvalue()).strip("\n") + "\n\nYou can find all GeckoLoader releases at:\nhttps://github.com/JoshuaMKW/GeckoLoader/releases") reply.setText(self._remove_ansi(_outpipe.getvalue()).strip(
"\n") + "\n\nYou can find all GeckoLoader releases at:\nhttps://github.com/JoshuaMKW/GeckoLoader/releases")
reply.setIcon(QtWidgets.QMessageBox.Information) reply.setIcon(QtWidgets.QMessageBox.Information)
reply.setStandardButtons(QtWidgets.QMessageBox.Ok) reply.setStandardButtons(QtWidgets.QMessageBox.Ok)
reply.exec_() reply.exec_()
@ -631,9 +671,11 @@ class GUI(object):
textbox.setText(textbox.text().strip()) textbox.setText(textbox.text().strip())
if len(textbox.text()) > 0: if len(textbox.text()) > 0:
_depth = len(hex(mask)[2:]) _depth = len(hex(mask)[2:])
_address = int(textbox.text(), 16) << ((_depth - len(textbox.text())) << 2) _address = int(textbox.text(), 16) << (
(_depth - len(textbox.text())) << 2)
aligned = hex(((_address & mask) | _or) >> ((_depth - len(textbox.text())) << 2))[2:].upper() aligned = hex(((_address & mask) | _or) >> (
(_depth - len(textbox.text())) << 2))[2:].upper()
textbox.setText(aligned) textbox.setText(aligned)
@staticmethod @staticmethod
@ -642,50 +684,73 @@ class GUI(object):
return ansi_escape.sub('', msg) return ansi_escape.sub('', msg)
def connect_signals(self): def connect_signals(self):
self.ui.actionPreferences.triggered.connect(lambda: self.show_dialog("Preferences")) self.ui.actionPreferences.triggered.connect(
self.ui.actionAbout_Qt.triggered.connect(lambda: self.show_dialog("aboutqt")) lambda: self.show_dialog("Preferences"))
self.ui.actionAbout_GeckoLoader.triggered.connect(lambda: self.show_dialog("aboutGeckoLoader")) self.ui.actionAbout_Qt.triggered.connect(
self.ui.actionCheck_Update.triggered.connect(lambda: self.display_update()) lambda: self.show_dialog("aboutqt"))
self.ui.actionAbout_GeckoLoader.triggered.connect(
lambda: self.show_dialog("aboutGeckoLoader"))
self.ui.actionCheck_Update.triggered.connect(
lambda: self.display_update())
self.ui.actionOpen.triggered.connect(lambda: self.file_dialog_exec(GUI.Dialogs.LOAD_SESSION)) self.ui.actionOpen.triggered.connect(
lambda: self.file_dialog_exec(GUI.Dialogs.LOAD_SESSION))
self.ui.actionClose.triggered.connect(lambda: self.close_session()) self.ui.actionClose.triggered.connect(lambda: self.close_session())
self.ui.actionSave_As.triggered.connect(lambda: self.file_dialog_exec(GUI.Dialogs.SAVE_SESSION_AS)) self.ui.actionSave_As.triggered.connect(
self.ui.actionSave.triggered.connect(lambda: self.file_dialog_exec(GUI.Dialogs.SAVE_SESSION)) lambda: self.file_dialog_exec(GUI.Dialogs.SAVE_SESSION_AS))
self.ui.actionSave.triggered.connect(
lambda: self.file_dialog_exec(GUI.Dialogs.SAVE_SESSION))
self.ui.dolButton.clicked.connect(lambda: self.file_dialog_exec(GUI.Dialogs.LOAD_DOL)) self.ui.dolButton.clicked.connect(
self.ui.gctFileButton.clicked.connect(lambda: self.file_dialog_exec(GUI.Dialogs.LOAD_GCT)) lambda: self.file_dialog_exec(GUI.Dialogs.LOAD_DOL))
self.ui.gctFolderButton.clicked.connect(lambda: self.file_dialog_exec(GUI.Dialogs.LOAD_FOLDER)) self.ui.gctFileButton.clicked.connect(
self.ui.destButton.clicked.connect(lambda: self.file_dialog_exec(GUI.Dialogs.LOAD_DEST)) lambda: self.file_dialog_exec(GUI.Dialogs.LOAD_GCT))
self.ui.gctFolderButton.clicked.connect(
lambda: self.file_dialog_exec(GUI.Dialogs.LOAD_FOLDER))
self.ui.destButton.clicked.connect(
lambda: self.file_dialog_exec(GUI.Dialogs.LOAD_DEST))
self.ui.dolTextBox.textChanged.connect(lambda: self.ui.set_edit_fields()) self.ui.dolTextBox.textChanged.connect(
self.ui.gctFolderTextBox.textChanged.connect(lambda: self.ui.set_edit_fields()) lambda: self.ui.set_edit_fields())
self.ui.gctFileTextBox.textChanged.connect(lambda: self.ui.set_edit_fields()) self.ui.gctFolderTextBox.textChanged.connect(
self.ui.destTextBox.textChanged.connect(lambda: self.ui.set_edit_fields()) lambda: self.ui.set_edit_fields())
self.ui.gctFileTextBox.textChanged.connect(
lambda: self.ui.set_edit_fields())
self.ui.destTextBox.textChanged.connect(
lambda: self.ui.set_edit_fields())
self.ui.allocLineEdit.textChanged.connect(lambda: self._enforce_mask(self.ui.allocLineEdit, 0xFFFFFC)) self.ui.allocLineEdit.textChanged.connect(
lambda: self._enforce_mask(self.ui.allocLineEdit, 0xFFFFFC))
self.ui.exOptionsButton.clicked.connect(lambda: self.show_dialog("Advanced Settings")) self.ui.exOptionsButton.clicked.connect(
lambda: self.show_dialog("Advanced Settings"))
self.ui.compileButton.clicked.connect(lambda: self._exec_api()) self.ui.compileButton.clicked.connect(lambda: self._exec_api())
self.uiprefs.buttonBox.accepted.connect(self.save_prefs) self.uiprefs.buttonBox.accepted.connect(self.save_prefs)
self.uiprefs.qtstyleSelect.currentIndexChanged.connect(lambda: self.load_qtstyle(self.uiprefs.qtstyleSelect.currentText())) self.uiprefs.qtstyleSelect.currentIndexChanged.connect(
lambda: self.load_qtstyle(self.uiprefs.qtstyleSelect.currentText()))
self.uiprefs.qtdarkButton.clicked.connect(lambda: self.update_theme()) self.uiprefs.qtdarkButton.clicked.connect(lambda: self.update_theme())
self.uiexSettings.codehookLineEdit.textChanged.connect(lambda: self._enforce_mask(self.uiexSettings.codehookLineEdit, 0x817FFFFC, 0x80000000)) self.uiexSettings.codehookLineEdit.textChanged.connect(lambda: self._enforce_mask(
self.uiexSettings.kernelHookLineEdit.textChanged.connect(lambda: self._enforce_mask(self.uiexSettings.kernelHookLineEdit, 0x817FFFFC, 0x80000000)) self.uiexSettings.codehookLineEdit, 0x817FFFFC, 0x80000000))
self.uiexSettings.kernelHookLineEdit.textChanged.connect(lambda: self._enforce_mask(
self.uiexSettings.kernelHookLineEdit, 0x817FFFFC, 0x80000000))
def _exec_api(self): def _exec_api(self):
if sys.platform == "win32": if sys.platform == "win32":
self.ui.responses.appendPlainText(f"| Session {self.compileCount} |".center(84, "=") + "\n") self.ui.responses.appendPlainText(
f"| Session {self.compileCount} |".center(84, "=") + "\n")
else: else:
self.ui.responses.appendPlainText(f"| Session {self.compileCount} |".center(76, "=") + "\n") self.ui.responses.appendPlainText(
f"| Session {self.compileCount} |".center(76, "=") + "\n")
self.compileCount += 1 self.compileCount += 1
if self.ui.dolTextBox.isEnabled and self.ui.dolTextBox.text().strip() != "": if self.ui.dolTextBox.isEnabled and self.ui.dolTextBox.text().strip() != "":
dol = self.ui.dolTextBox.text().strip() dol = self.ui.dolTextBox.text().strip()
else: else:
self.ui.responses.appendPlainText("DOL is missing, please add the path to your codes in the respective textbox" + "\n\n") self.ui.responses.appendPlainText(
"DOL is missing, please add the path to your codes in the respective textbox" + "\n\n")
return return
if self.ui.gctFileTextBox.isEnabled and self.ui.gctFileTextBox.text().strip() != "": if self.ui.gctFileTextBox.isEnabled and self.ui.gctFileTextBox.text().strip() != "":
@ -693,7 +758,8 @@ class GUI(object):
elif self.ui.gctFolderTextBox.isEnabled and self.ui.gctFolderTextBox.text().strip() != "": elif self.ui.gctFolderTextBox.isEnabled and self.ui.gctFolderTextBox.text().strip() != "":
gct = self.ui.gctFolderTextBox.text().strip() gct = self.ui.gctFolderTextBox.text().strip()
else: else:
self.ui.responses.appendPlainText("GCT is missing, please add the path to your codes in the respective textbox" + "\n\n") self.ui.responses.appendPlainText(
"GCT is missing, please add the path to your codes in the respective textbox" + "\n\n")
return return
alloc = self.ui.allocLineEdit.text().strip() alloc = self.ui.allocLineEdit.text().strip()
@ -705,10 +771,12 @@ class GUI(object):
optimize = self.uiexSettings.optimizeCodes.isChecked() optimize = self.uiexSettings.optimizeCodes.isChecked()
protect = self.uiexSettings.protectCodes.isChecked() protect = self.uiexSettings.protectCodes.isChecked()
encrypt = self.uiexSettings.encryptCodes.isChecked() encrypt = self.uiexSettings.encryptCodes.isChecked()
verbosity = int(self.uiexSettings.verbositySelect.currentText().strip()) verbosity = int(
self.uiexSettings.verbositySelect.currentText().strip())
dest = self.ui.destTextBox.text().strip() dest = self.ui.destTextBox.text().strip()
argslist = [ dol, gct, "-t", txtInclude, "--handler", codeHandlerType, "--hooktype", hookType ] argslist = [dol, gct, "-t", txtInclude, "--handler",
codeHandlerType, "--hooktype", hookType]
if alloc != "": if alloc != "":
argslist.append("-a") argslist.append("-a")
@ -716,7 +784,8 @@ class GUI(object):
if hookAddress != "": if hookAddress != "":
if int(hookAddress, 16) < 0x80000000: if int(hookAddress, 16) < 0x80000000:
self.ui.responses.appendPlainText("The specified code hook is invalid" + "\n") self.ui.responses.appendPlainText(
"The specified code hook is invalid" + "\n")
return return
argslist.append("--hookaddress") argslist.append("--hookaddress")
@ -724,7 +793,8 @@ class GUI(object):
if initAddress != "": if initAddress != "":
if int(initAddress, 16) < 0x80000000: if int(initAddress, 16) < 0x80000000:
self.ui.responses.appendPlainText("The specified initialization address is invalid" + "\n") self.ui.responses.appendPlainText(
"The specified initialization address is invalid" + "\n")
return return
argslist.append("-i") argslist.append("-i")
@ -735,7 +805,8 @@ class GUI(object):
argslist.append("--dest") argslist.append("--dest")
argslist.append(dest) argslist.append(dest)
else: else:
self.ui.responses.appendPlainText("The destination file path is not a valid DOL file\n") self.ui.responses.appendPlainText(
"The destination file path is not a valid DOL file\n")
return return
if optimize: if optimize:
@ -769,7 +840,7 @@ class GUI(object):
if _status is False: if _status is False:
_msg = f"Arguments failed! GeckoLoader couldn't execute the job\n\nArgs: {args.__repr__()}\n\nstderr: {self._remove_ansi(_errpipe.getvalue())}" _msg = f"Arguments failed! GeckoLoader couldn't execute the job\n\nArgs: {args.__repr__()}\n\nstderr: {self._remove_ansi(_errpipe.getvalue())}"
self.ui.responses.appendPlainText(_outpipe.getvalue() + "\n\n" + _msg.strip() + "\n") self.ui.responses.appendPlainText(_msg.strip() + "\n")
else: else:
for line in self._remove_ansi(_outpipe.getvalue()).split("\n"): for line in self._remove_ansi(_outpipe.getvalue()).split("\n"):
_msg += line.lstrip() + "\n" _msg += line.lstrip() + "\n"
@ -808,8 +879,10 @@ class GUI(object):
self.ui.show() self.ui.show()
sys.exit(self.app.exec_()) sys.exit(self.app.exec_())
if __name__ == "__main__": if __name__ == "__main__":
cli = GeckoLoaderCli('GeckoLoader', __version__, description='Dol editing tool for allocating extended codespace') cli = GeckoLoaderCli('GeckoLoader', __version__,
description='Dol editing tool for allocating extended codespace')
if len(sys.argv) == 1: if len(sys.argv) == 1:
cli.print_splash() cli.print_splash()

View file

@ -1,17 +1,7 @@
import logging
import os
import pickle as cPickle
import re
import signal
import subprocess
import sys
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5 import QtCore, QtGui, QtWidgets
from children_ui import PrefWindow from children_ui import PrefWindow
from dolreader import DolFile
from fileutils import resource_path from fileutils import resource_path
from kernel import CodeHandler, KernelLoader
class MainWindow(QtWidgets.QMainWindow): class MainWindow(QtWidgets.QMainWindow):
def __init__(self, version: str): def __init__(self, version: str):
@ -66,7 +56,7 @@ class MainWindow(QtWidgets.QMainWindow):
font.setWeight(42) font.setWeight(42)
self.setFont(font) self.setFont(font)
icon = QtGui.QIcon() icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(str(resource_path(os.path.join("bin", "icon.ico")))), QtGui.QIcon.Normal, QtGui.QIcon.Off) icon.addPixmap(QtGui.QPixmap(str(resource_path("bin/icon.ico"))), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.setWindowIcon(icon) self.setWindowIcon(icon)
#Top level widget #Top level widget