Verify titles

Name archives properly using the database
Fix UI problems on macOS
This commit is contained in:
yeah-its-gloria 2024-10-21 14:03:07 +02:00
parent 0dbe28914d
commit 9c15eac1fd
No known key found for this signature in database
GPG Key ID: 3940AE4348411FD7
5 changed files with 151 additions and 71 deletions

110
NUSGet.py
View File

@ -231,21 +231,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.log_text = f"{tid} - {selected_title.name}\nVersion: {selected_title.version}\n\n{danger_text}\n"
self.ui.log_text_browser.setText(self.log_text)
def download_btn_pressed(self):
# Throw an error and make a message box appear if you haven't selected any options to output the title.
if (self.ui.pack_archive_chkbox.isChecked() is False and self.ui.keep_enc_chkbox.isChecked() is False and
self.ui.create_dec_chkbox.isChecked() is False):
msg_box = QMessageBox()
msg_box.setIcon(QMessageBox.Icon.Critical)
msg_box.setStandardButtons(QMessageBox.StandardButton.Ok)
msg_box.setDefaultButton(QMessageBox.StandardButton.Ok)
msg_box.setWindowTitle(app.translate("MainWindow", "No Output Selected"))
msg_box.setText(app.translate("MainWindow", "You have not selected any format to output the data in!"))
msg_box.setInformativeText(app.translate("MainWindow", "Please select at least one option for how you would "
"like the download to be saved."))
msg_box.exec()
return
def lock_ui_for_download(self):
# Lock the UI prior to the download beginning to avoid spawning multiple threads or changing info part way in.
# Also resets the log.
self.ui.tid_entry.setEnabled(False)
self.ui.version_entry.setEnabled(False)
self.ui.download_btn.setEnabled(False)
@ -260,6 +248,24 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.ui.console_select_dropdown.setEnabled(False)
self.log_text = ""
self.ui.log_text_browser.setText(self.log_text)
def download_btn_pressed(self):
# Throw an error and make a message box appear if you haven't selected any options to output the title.
if (self.ui.pack_archive_chkbox.isChecked() is False and self.ui.keep_enc_chkbox.isChecked() is False and
self.ui.create_dec_chkbox.isChecked() is False):
msg_box = QMessageBox()
msg_box.setIcon(QMessageBox.Icon.Critical)
msg_box.setStandardButtons(QMessageBox.StandardButton.Ok)
msg_box.setDefaultButton(QMessageBox.StandardButton.Ok)
msg_box.setWindowTitle(app.translate("MainWindow", "No Output Selected"))
msg_box.setText(app.translate("MainWindow", "You have not selected any format to output the data in!"))
msg_box.setInformativeText(app.translate("MainWindow", "Please select at least one option for how you would "
"like the download to be saved."))
msg_box.exec()
return
self.lock_ui_for_download()
# Create a new worker object to handle the download in a new thread.
if self.ui.console_select_dropdown.currentText() == "DSi":
worker = Worker(run_nus_download_dsi, out_folder, self.ui.tid_entry.text(),
@ -363,34 +369,72 @@ class MainWindow(QMainWindow, Ui_MainWindow):
content = file.readlines()
# Decoding NUS Scripts
# NUS Scripts are plaintext UTF-8 files that list a title per line, terminated with newlines.
# Every title is its u64 TID, a space and its u16 version, *both* written in hexadecimal.
# NUS itself expects versions as decimal notation, so they need to be decoded first, but TIDs are always written in hexadecimal notation.
titles = []
for title in content:
for index, title in enumerate(content):
decoded = title.replace("\n", "").split(" ", 1)
if len(decoded[0]) != 16 or len(decoded[1]) != 4:
QMessageBox.critical(self, app.translate("MainWindow", "Script Failure"), app.translate("MainWindow", "This script is invalid."), buttons=QMessageBox.StandardButton.Ok, defaultButton=QMessageBox.StandardButton.Ok)
if len(decoded[0]) != 16:
QMessageBox.critical(self, app.translate("MainWindow", "Script Failure"), app.translate("MainWindow", "The TID for title #%n is not valid.", "", index+1), buttons=QMessageBox.StandardButton.Ok, defaultButton=QMessageBox.StandardButton.Ok)
return
elif len(decoded[1]) != 4:
QMessageBox.critical(self, app.translate("MainWindow", "Script Failure"), app.translate("MainWindow", "The version for title #%n is not valid.", "", index+1), buttons=QMessageBox.StandardButton.Ok, defaultButton=QMessageBox.StandardButton.Ok)
return
tid = decoded[0]
try:
version = int(decoded[1], 16)
except:
QMessageBox.critical(self, app.translate("MainWindow", "Script Failure"), app.translate("MainWindow", "This script is invalid."), buttons=QMessageBox.StandardButton.Ok, defaultButton=QMessageBox.StandardButton.Ok)
QMessageBox.critical(self, app.translate("MainWindow", "Script Failure"), app.translate("MainWindow", "The version for title #%n is not valid.", "", index+1), buttons=QMessageBox.StandardButton.Ok, defaultButton=QMessageBox.StandardButton.Ok)
return
titles.append((decoded[0], str(version)))
title = None
for category in self.trees[self.ui.platform_tabs.currentIndex()][1]:
for title_ in self.trees[self.ui.platform_tabs.currentIndex()][1][category]:
# The last two digits are either identifying the title type (e.g IOS slot, BC type, etc) or a region code; in case of the latter, skip the region here to match it
if not ((title_["TID"][-2:] == "XX" and title_["TID"][:-2] == tid[:-2]) or title_["TID"] == tid):
continue
self.ui.tid_entry.setEnabled(False)
self.ui.version_entry.setEnabled(False)
self.ui.download_btn.setEnabled(False)
self.ui.script_btn.setEnabled(False)
self.ui.pack_archive_chkbox.setEnabled(False)
self.ui.keep_enc_chkbox.setEnabled(False)
self.ui.create_dec_chkbox.setEnabled(False)
self.ui.use_local_chkbox.setEnabled(False)
self.ui.use_wiiu_nus_chkbox.setEnabled(False)
self.ui.pack_vwii_mode_chkbox.setEnabled(False)
self.ui.archive_file_entry.setEnabled(False)
self.ui.console_select_dropdown.setEnabled(False)
self.log_text = ""
self.ui.log_text_browser.setText(self.log_text)
region = None
found_ver = False
if title_["TID"][-2:] == "XX":
global regions
for region_ in regions:
for code in regions[region_]:
if code == tid[:-2]:
region = region_
break
if region is None:
QMessageBox.critical(self, app.translate("MainWindow", "Script Failure"), app.translate("MainWindow", "Title #%n belongs to an unknown region.", "", index+1), buttons=QMessageBox.StandardButton.Ok, defaultButton=QMessageBox.StandardButton.Ok)
return
else:
region = "World"
for db_version in title_["Versions"][region]:
if db_version == version:
found_ver = True
break
if not found_ver:
QMessageBox.critical(self, app.translate("MainWindow", "Script Failure"), app.translate("MainWindow", "The version for title #%n could not be discovered in the database.", "", index+1), buttons=QMessageBox.StandardButton.Ok, defaultButton=QMessageBox.StandardButton.Ok)
return
title = title_
break
if title == None:
QMessageBox.critical(self, app.translate("MainWindow", "Script Failure"), app.translate("MainWindow", "Title #%n could not be discovered in the database.", "", index+1), buttons=QMessageBox.StandardButton.Ok, defaultButton=QMessageBox.StandardButton.Ok)
return
titles.append((title["TID"], str(version), title["Archive Name"]))
self.lock_ui_for_download()
self.update_log_text(f"Found {len(titles)} titles, starting batch download.")

View File

@ -134,10 +134,10 @@ def run_nus_download_dsi(out_folder: pathlib.Path, tid: str, version: str, pack_
return 1
return 0
def run_nus_download_dsi_batch(out_folder: pathlib.Path, titles: List[Tuple[str, str]], pack_tad_chkbox: bool, keep_enc_chkbox: bool,
def run_nus_download_dsi_batch(out_folder: pathlib.Path, titles: List[Tuple[str, str, str]], pack_tad_chkbox: bool, keep_enc_chkbox: bool,
decrypt_contents_chkbox: bool, use_local_chkbox: bool, progress_callback=None):
for title in titles:
result = run_nus_download_dsi(out_folder, title[0], title[1], pack_tad_chkbox, keep_enc_chkbox, decrypt_contents_chkbox, use_local_chkbox, None, progress_callback)
result = run_nus_download_dsi(out_folder, title[0], title[1], pack_tad_chkbox, keep_enc_chkbox, decrypt_contents_chkbox, use_local_chkbox, f"{title[2]}-{title[1]}.tad", progress_callback)
if result != 0:
return result

View File

@ -167,11 +167,11 @@ def run_nus_download_wii(out_folder: pathlib.Path, tid: str, version: str, pack_
return 1
return 0
def run_nus_download_wii_batch(out_folder: pathlib.Path, titles: List[Tuple[str, str]], pack_wad_chkbox: bool, keep_enc_chkbox: bool,
def run_nus_download_wii_batch(out_folder: pathlib.Path, titles: List[Tuple[str, str, str]], pack_wad_chkbox: bool, keep_enc_chkbox: bool,
decrypt_contents_chkbox: bool, wiiu_nus_chkbox: bool, use_local_chkbox: bool,
repack_vwii_chkbox: bool, patch_ios: bool, progress_callback=None):
for title in titles:
result = run_nus_download_wii(out_folder, title[0], title[1], pack_wad_chkbox, keep_enc_chkbox, decrypt_contents_chkbox, wiiu_nus_chkbox, use_local_chkbox, repack_vwii_chkbox, patch_ios, None, progress_callback)
result = run_nus_download_wii(out_folder, title[0], title[1], pack_wad_chkbox, keep_enc_chkbox, decrypt_contents_chkbox, wiiu_nus_chkbox, use_local_chkbox, repack_vwii_chkbox, patch_ios, f"{title[2]}-{title[1]}.wad", progress_callback)
if result != 0:
return result

View File

@ -111,7 +111,7 @@ class Ui_MainWindow(object):
self.vertical_layout_controls = QVBoxLayout()
self.vertical_layout_controls.setObjectName(u"vertical_layout_controls")
self.vertical_layout_controls.setSizeConstraint(QLayout.SetDefaultConstraint)
self.vertical_layout_controls.setSizeConstraint(QLayout.SizeConstraint.SetDefaultConstraint)
self.horizontal_layout_title_entry = QHBoxLayout()
self.horizontal_layout_title_entry.setObjectName(u"horizontal_layout_title_entry")
self.tid_entry = QLineEdit(self.centralwidget)
@ -149,11 +149,21 @@ class Ui_MainWindow(object):
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.download_btn = QPushButton(self.centralwidget)
self.download_btn.setObjectName(u"download_btn")
sizePolicy1 = QSizePolicy(QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.Fixed)
sizePolicy1.setHorizontalStretch(0)
sizePolicy1.setVerticalStretch(0)
sizePolicy1.setHeightForWidth(self.download_btn.sizePolicy().hasHeightForWidth())
self.download_btn.setSizePolicy(sizePolicy1)
self.horizontalLayout.addWidget(self.download_btn)
self.script_btn = QPushButton(self.centralwidget)
self.script_btn.setObjectName(u"script_btn")
sizePolicy2 = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed)
sizePolicy2.setHorizontalStretch(0)
sizePolicy2.setVerticalStretch(0)
sizePolicy2.setHeightForWidth(self.script_btn.sizePolicy().hasHeightForWidth())
self.script_btn.setSizePolicy(sizePolicy2)
self.horizontalLayout.addWidget(self.script_btn)
@ -163,7 +173,9 @@ class Ui_MainWindow(object):
self.horizontalLayout_5 = QHBoxLayout()
self.horizontalLayout_5.setObjectName(u"horizontalLayout_5")
self.verticalLayout_7 = QVBoxLayout()
self.verticalLayout_7.setSpacing(10)
self.verticalLayout_7.setObjectName(u"verticalLayout_7")
self.verticalLayout_7.setSizeConstraint(QLayout.SizeConstraint.SetNoConstraint)
self.label_3 = QLabel(self.centralwidget)
self.label_3.setObjectName(u"label_3")
self.label_3.setFont(font)
@ -174,11 +186,11 @@ class Ui_MainWindow(object):
self.pack_archive_row.setObjectName(u"pack_archive_row")
self.pack_archive_chkbox = QCheckBox(self.centralwidget)
self.pack_archive_chkbox.setObjectName(u"pack_archive_chkbox")
sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Fixed)
sizePolicy1.setHorizontalStretch(0)
sizePolicy1.setVerticalStretch(0)
sizePolicy1.setHeightForWidth(self.pack_archive_chkbox.sizePolicy().hasHeightForWidth())
self.pack_archive_chkbox.setSizePolicy(sizePolicy1)
sizePolicy3 = QSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Fixed)
sizePolicy3.setHorizontalStretch(0)
sizePolicy3.setVerticalStretch(0)
sizePolicy3.setHeightForWidth(self.pack_archive_chkbox.sizePolicy().hasHeightForWidth())
self.pack_archive_chkbox.setSizePolicy(sizePolicy3)
self.pack_archive_chkbox.setText(u"")
self.pack_archive_row.addWidget(self.pack_archive_chkbox)
@ -202,8 +214,8 @@ class Ui_MainWindow(object):
self.keep_enc_row.setObjectName(u"keep_enc_row")
self.keep_enc_chkbox = QCheckBox(self.centralwidget)
self.keep_enc_chkbox.setObjectName(u"keep_enc_chkbox")
sizePolicy1.setHeightForWidth(self.keep_enc_chkbox.sizePolicy().hasHeightForWidth())
self.keep_enc_chkbox.setSizePolicy(sizePolicy1)
sizePolicy3.setHeightForWidth(self.keep_enc_chkbox.sizePolicy().hasHeightForWidth())
self.keep_enc_chkbox.setSizePolicy(sizePolicy3)
self.keep_enc_chkbox.setText(u"")
self.keep_enc_chkbox.setChecked(True)
@ -222,8 +234,8 @@ class Ui_MainWindow(object):
self.create_dec_row.setObjectName(u"create_dec_row")
self.create_dec_chkbox = QCheckBox(self.centralwidget)
self.create_dec_chkbox.setObjectName(u"create_dec_chkbox")
sizePolicy1.setHeightForWidth(self.create_dec_chkbox.sizePolicy().hasHeightForWidth())
self.create_dec_chkbox.setSizePolicy(sizePolicy1)
sizePolicy3.setHeightForWidth(self.create_dec_chkbox.sizePolicy().hasHeightForWidth())
self.create_dec_chkbox.setSizePolicy(sizePolicy3)
self.create_dec_chkbox.setText(u"")
self.create_dec_row.addWidget(self.create_dec_chkbox)
@ -242,8 +254,8 @@ class Ui_MainWindow(object):
self.use_local_chkbox = QCheckBox(self.centralwidget)
self.use_local_chkbox.setObjectName(u"use_local_chkbox")
self.use_local_chkbox.setEnabled(True)
sizePolicy1.setHeightForWidth(self.use_local_chkbox.sizePolicy().hasHeightForWidth())
self.use_local_chkbox.setSizePolicy(sizePolicy1)
sizePolicy3.setHeightForWidth(self.use_local_chkbox.sizePolicy().hasHeightForWidth())
self.use_local_chkbox.setSizePolicy(sizePolicy3)
self.use_local_chkbox.setText(u"")
self.use_local_row.addWidget(self.use_local_chkbox)
@ -261,9 +273,12 @@ class Ui_MainWindow(object):
self.use_wiiu_nus_row.setObjectName(u"use_wiiu_nus_row")
self.use_wiiu_nus_chkbox = QCheckBox(self.centralwidget)
self.use_wiiu_nus_chkbox.setObjectName(u"use_wiiu_nus_chkbox")
sizePolicy1.setHeightForWidth(self.use_wiiu_nus_chkbox.sizePolicy().hasHeightForWidth())
self.use_wiiu_nus_chkbox.setSizePolicy(sizePolicy1)
self.use_wiiu_nus_chkbox.setLayoutDirection(Qt.LeftToRight)
sizePolicy4 = QSizePolicy(QSizePolicy.Policy.Maximum, QSizePolicy.Policy.Preferred)
sizePolicy4.setHorizontalStretch(0)
sizePolicy4.setVerticalStretch(0)
sizePolicy4.setHeightForWidth(self.use_wiiu_nus_chkbox.sizePolicy().hasHeightForWidth())
self.use_wiiu_nus_chkbox.setSizePolicy(sizePolicy4)
self.use_wiiu_nus_chkbox.setLayoutDirection(Qt.LayoutDirection.LeftToRight)
self.use_wiiu_nus_chkbox.setText(u"")
self.use_wiiu_nus_chkbox.setChecked(True)
@ -283,8 +298,8 @@ class Ui_MainWindow(object):
self.patch_ios_chkbox = QCheckBox(self.centralwidget)
self.patch_ios_chkbox.setObjectName(u"patch_ios_chkbox")
self.patch_ios_chkbox.setEnabled(False)
sizePolicy1.setHeightForWidth(self.patch_ios_chkbox.sizePolicy().hasHeightForWidth())
self.patch_ios_chkbox.setSizePolicy(sizePolicy1)
sizePolicy3.setHeightForWidth(self.patch_ios_chkbox.sizePolicy().hasHeightForWidth())
self.patch_ios_chkbox.setSizePolicy(sizePolicy3)
self.patch_ios_chkbox.setText(u"")
self.patch_ios_row.addWidget(self.patch_ios_chkbox)
@ -299,11 +314,11 @@ class Ui_MainWindow(object):
self.verticalLayout_7.addLayout(self.patch_ios_row)
self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Ignored)
self.verticalLayout_7.addItem(self.verticalSpacer_2)
self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Minimum)
self.verticalLayout_7.addItem(self.horizontalSpacer)
@ -323,8 +338,8 @@ class Ui_MainWindow(object):
self.pack_vwii_mode_chkbox = QCheckBox(self.centralwidget)
self.pack_vwii_mode_chkbox.setObjectName(u"pack_vwii_mode_chkbox")
self.pack_vwii_mode_chkbox.setEnabled(False)
sizePolicy1.setHeightForWidth(self.pack_vwii_mode_chkbox.sizePolicy().hasHeightForWidth())
self.pack_vwii_mode_chkbox.setSizePolicy(sizePolicy1)
sizePolicy3.setHeightForWidth(self.pack_vwii_mode_chkbox.sizePolicy().hasHeightForWidth())
self.pack_vwii_mode_chkbox.setSizePolicy(sizePolicy3)
self.pack_vwii_mode_chkbox.setText(u"")
self.pack_vwii_mode_row.addWidget(self.pack_vwii_mode_chkbox)
@ -343,7 +358,7 @@ class Ui_MainWindow(object):
self.verticalLayout_8.addItem(self.verticalSpacer)
self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Minimum)
self.verticalLayout_8.addItem(self.horizontalSpacer_2)

View File

@ -33,7 +33,6 @@
<widget class="QLabel" name="label_2">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
@ -159,7 +158,7 @@
<item>
<layout class="QVBoxLayout" name="vertical_layout_controls">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
</property>
<item>
<layout class="QHBoxLayout" name="horizontal_layout_title_entry">
@ -225,6 +224,12 @@
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="download_btn">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Start Download</string>
</property>
@ -232,6 +237,12 @@
</item>
<item>
<widget class="QPushButton" name="script_btn">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Run Script</string>
</property>
@ -243,11 +254,16 @@
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<layout class="QVBoxLayout" name="verticalLayout_7">
<property name="spacing">
<number>10</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SizeConstraint::SetNoConstraint</enum>
</property>
<item>
<widget class="QLabel" name="label_3">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
@ -385,13 +401,13 @@
<item>
<widget class="QCheckBox" name="use_wiiu_nus_chkbox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
<enum>Qt::LayoutDirection::LeftToRight</enum>
</property>
<property name="text">
<string notr="true"/>
@ -449,10 +465,10 @@
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
<enum>QSizePolicy::Policy::Ignored</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -465,7 +481,10 @@
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -483,7 +502,6 @@
<widget class="QLabel" name="label_4">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
@ -528,10 +546,10 @@
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
<enum>QSizePolicy::Policy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@ -544,7 +562,10 @@
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>