forked from NinjaCheetah/NUSGet
Allow for using the Wii U NUS for faster downloads (libWiiPy v0.2.3 beta)
This commit is contained in:
parent
466f914ad9
commit
625131873b
51
NUSGet.py
51
NUSGet.py
@ -5,6 +5,7 @@ import sys
|
||||
import os
|
||||
import json
|
||||
import pathlib
|
||||
from importlib.metadata import version
|
||||
|
||||
import libWiiPy
|
||||
|
||||
@ -58,12 +59,13 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
# noinspection PyUnresolvedReferences
|
||||
self.ui.title_tree.header().setSectionResizeMode(QHeaderView.ResizeToContents)
|
||||
# Basic intro text set to automatically show when the app loads. This may be changed in the future.
|
||||
self.ui.log_text_browser.setText("NUSGet v1.0\nDeveloped by NinjaCheetah\nPowered by libWiiPy\n\n"
|
||||
"Select a title from the list on the left, or enter a Title ID to begin.\n\n"
|
||||
"Titles marked with a checkmark are free and have a ticket available, and can"
|
||||
" be decrypted and packed into a WAD. Titles with an X do not have a ticket,"
|
||||
" and only their encrypted contents can be saved.")
|
||||
# Tree building code.
|
||||
libwiipy_version = "v" + version("libWiiPy")
|
||||
self.ui.log_text_browser.setText(f"NUSGet v1.0\nDeveloped by NinjaCheetah\nPowered by libWiiPy "
|
||||
f"{libwiipy_version}\n\nSelect a title from the list on the left, or enter a "
|
||||
f"Title ID to begin.\n\nTitles marked with a checkmark are free and have a "
|
||||
f"ticket available, and can be decrypted and packed into a WAD. Titles with an"
|
||||
f" X do not have a ticket, and only their encrypted contents can be saved.")
|
||||
# Title tree building code.
|
||||
tree = self.ui.title_tree
|
||||
self.tree_categories = []
|
||||
global regions
|
||||
@ -79,9 +81,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
for region in title["Versions"]:
|
||||
new_region = QTreeWidgetItem()
|
||||
new_region.setText(0, region)
|
||||
for version in title["Versions"][region]:
|
||||
for title_version in title["Versions"][region]:
|
||||
new_version = QTreeWidgetItem()
|
||||
new_version.setText(0, "v" + str(version))
|
||||
new_version.setText(0, "v" + str(title_version))
|
||||
new_region.addChild(new_version)
|
||||
new_title.addChild(new_region)
|
||||
# Set an indicator icon to show if a ticket is offered for this title or not.
|
||||
@ -177,6 +179,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
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.wad_file_entry.setEnabled(False)
|
||||
self.log_text = ""
|
||||
self.ui.log_text_browser.setText(self.log_text)
|
||||
@ -230,6 +233,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
self.ui.keep_enc_chkbox.setEnabled(True)
|
||||
self.ui.create_dec_chkbox.setEnabled(True)
|
||||
self.ui.use_local_chkbox.setEnabled(True)
|
||||
self.ui.use_wiiu_nus_chkbox.setEnabled(True)
|
||||
if self.ui.pack_wad_chkbox.isChecked() is True:
|
||||
self.ui.wad_file_entry.setEnabled(True)
|
||||
|
||||
@ -242,12 +246,14 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
# An error here is acceptable, because it may just mean the box is empty. Or the version string is nonsense.
|
||||
# Either way, just fall back on downloading the latest version of the title.
|
||||
try:
|
||||
version = int(self.ui.version_entry.text())
|
||||
title_version = int(self.ui.version_entry.text())
|
||||
except ValueError:
|
||||
version = None
|
||||
title_version = None
|
||||
# Set variables for these two options so that their state can be compared against the user's choices later.
|
||||
pack_wad_enabled = self.ui.pack_wad_chkbox.isChecked()
|
||||
decrypt_contents_enabled = self.ui.create_dec_chkbox.isChecked()
|
||||
# Check whether we're going to be using the "fallback" (but faster) Wii U NUS or not.
|
||||
fallback_enabled = self.ui.use_wiiu_nus_chkbox.isChecked()
|
||||
# Create a new libWiiPy Title.
|
||||
title = libWiiPy.Title()
|
||||
# Make a directory for this title if it doesn't exist.
|
||||
@ -255,27 +261,27 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
if not title_dir.is_dir():
|
||||
title_dir.mkdir()
|
||||
# Announce the title being downloaded, and the version if applicable.
|
||||
if version is not None:
|
||||
progress_callback.emit("Downloading title " + tid + " v" + str(version) + ", please wait...")
|
||||
if title_version is not None:
|
||||
progress_callback.emit("Downloading title " + tid + " v" + str(title_version) + ", please wait...")
|
||||
else:
|
||||
progress_callback.emit("Downloading title " + tid + " vLatest, please wait...")
|
||||
progress_callback.emit(" - Downloading and parsing TMD...")
|
||||
# Download a specific TMD version if a version was specified, otherwise just download the latest TMD.
|
||||
try:
|
||||
if version is not None:
|
||||
title.load_tmd(libWiiPy.download_tmd(tid, version))
|
||||
if title_version is not None:
|
||||
title.load_tmd(libWiiPy.download_tmd(tid, title_version, fallback_endpoint=fallback_enabled))
|
||||
else:
|
||||
title.load_tmd(libWiiPy.download_tmd(tid))
|
||||
version = title.tmd.title_version
|
||||
title.load_tmd(libWiiPy.download_tmd(tid, fallback_endpoint=fallback_enabled))
|
||||
title_version = title.tmd.title_version
|
||||
# If libWiiPy returns an error, that means that either the TID or version doesn't exist, so return code -2.
|
||||
except ValueError:
|
||||
return -2
|
||||
# Make a directory for this version if it doesn't exist.
|
||||
version_dir = pathlib.Path(os.path.join(title_dir, str(version)))
|
||||
version_dir = pathlib.Path(os.path.join(title_dir, str(title_version)))
|
||||
if not version_dir.is_dir():
|
||||
version_dir.mkdir()
|
||||
# Write out the TMD to a file.
|
||||
tmd_out = open(os.path.join(version_dir, "tmd." + str(version)), "wb")
|
||||
tmd_out = open(os.path.join(version_dir, "tmd." + str(title_version)), "wb")
|
||||
tmd_out.write(title.tmd.dump())
|
||||
tmd_out.close()
|
||||
# Use a local ticket, if one exists and "use local files" is enabled.
|
||||
@ -286,7 +292,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
else:
|
||||
progress_callback.emit(" - Downloading and parsing Ticket...")
|
||||
try:
|
||||
title.load_ticket(libWiiPy.download_ticket(tid))
|
||||
title.load_ticket(libWiiPy.download_ticket(tid, fallback_endpoint=fallback_enabled))
|
||||
ticket_out = open(os.path.join(version_dir, "tik"), "wb")
|
||||
ticket_out.write(title.ticket.dump())
|
||||
ticket_out.close()
|
||||
@ -316,7 +322,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
progress_callback.emit(" - Downloading content " + str(content + 1) + " of " +
|
||||
str(len(title.tmd.content_records)) + " (" +
|
||||
str(title.tmd.content_records[content].content_size) + " bytes)...")
|
||||
content_list.append(libWiiPy.download_content(tid, title.tmd.content_records[content].content_id))
|
||||
content_list.append(libWiiPy.download_content(tid, title.tmd.content_records[content].content_id,
|
||||
fallback_endpoint=fallback_enabled))
|
||||
progress_callback.emit(" - Done!")
|
||||
# If keep encrypted contents is on, write out each content after its downloaded.
|
||||
if self.ui.keep_enc_chkbox.isChecked() is True:
|
||||
@ -346,7 +353,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
if pack_wad_enabled is True:
|
||||
# Get the WAD certificate chain, courtesy of libWiiPy.
|
||||
progress_callback.emit(" - Building certificate...")
|
||||
title.wad.set_cert_data(libWiiPy.download_cert())
|
||||
title.wad.set_cert_data(libWiiPy.download_cert(fallback_endpoint=fallback_enabled))
|
||||
# Use a typed WAD name if there is one, and auto generate one based on the TID and version if there isn't.
|
||||
progress_callback.emit("Packing WAD...")
|
||||
if self.ui.wad_file_entry.text() != "":
|
||||
@ -354,7 +361,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
if wad_file_name[-4:] != ".wad":
|
||||
wad_file_name = wad_file_name + ".wad"
|
||||
else:
|
||||
wad_file_name = tid + "-v" + str(version) + ".wad"
|
||||
wad_file_name = tid + "-v" + str(title_version) + ".wad"
|
||||
# Have libWiiPy dump the WAD, and write that data out.
|
||||
file = open(os.path.join(version_dir, wad_file_name), "wb")
|
||||
file.write(title.dump_wad())
|
||||
|
@ -24,9 +24,9 @@ class Ui_MainWindow(object):
|
||||
def setupUi(self, MainWindow):
|
||||
if not MainWindow.objectName():
|
||||
MainWindow.setObjectName(u"MainWindow")
|
||||
MainWindow.resize(610, 605)
|
||||
MainWindow.setMinimumSize(QSize(610, 605))
|
||||
MainWindow.setMaximumSize(QSize(610, 605))
|
||||
MainWindow.resize(610, 625)
|
||||
MainWindow.setMinimumSize(QSize(610, 625))
|
||||
MainWindow.setMaximumSize(QSize(610, 625))
|
||||
self.centralwidget = QWidget(MainWindow)
|
||||
self.centralwidget.setObjectName(u"centralwidget")
|
||||
self.horizontalLayout_3 = QHBoxLayout(self.centralwidget)
|
||||
@ -123,6 +123,12 @@ class Ui_MainWindow(object):
|
||||
|
||||
self.verticalLayout_3.addWidget(self.use_local_chkbox)
|
||||
|
||||
self.use_wiiu_nus_chkbox = QCheckBox(self.centralwidget)
|
||||
self.use_wiiu_nus_chkbox.setObjectName(u"use_wiiu_nus_chkbox")
|
||||
self.use_wiiu_nus_chkbox.setChecked(True)
|
||||
|
||||
self.verticalLayout_3.addWidget(self.use_wiiu_nus_chkbox)
|
||||
|
||||
|
||||
self.horizontalLayout_3.addLayout(self.verticalLayout_3)
|
||||
|
||||
@ -156,5 +162,6 @@ class Ui_MainWindow(object):
|
||||
self.keep_enc_chkbox.setText(QCoreApplication.translate("MainWindow", u"Keep encrypted contents", None))
|
||||
self.create_dec_chkbox.setText(QCoreApplication.translate("MainWindow", u"Create decrypted contents (*.app)", None))
|
||||
self.use_local_chkbox.setText(QCoreApplication.translate("MainWindow", u"Use local files, if they exist", None))
|
||||
self.use_wiiu_nus_chkbox.setText(QCoreApplication.translate("MainWindow", u"Use the Wii U NUS (faster, NOT vWii titles)", None))
|
||||
# retranslateUi
|
||||
|
||||
|
@ -7,19 +7,19 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>610</width>
|
||||
<height>605</height>
|
||||
<height>625</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>610</width>
|
||||
<height>605</height>
|
||||
<height>625</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>610</width>
|
||||
<height>605</height>
|
||||
<height>625</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -173,6 +173,16 @@ p, li { white-space: pre-wrap; }
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="use_wiiu_nus_chkbox">
|
||||
<property name="text">
|
||||
<string>Use the Wii U NUS (faster, NOT vWii titles)</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
|
@ -1,4 +1,4 @@
|
||||
pyside6
|
||||
nuitka
|
||||
libWiiPy
|
||||
git+https://github.com/NinjaCheetah/libWiipy
|
||||
zstandard
|
Loading…
x
Reference in New Issue
Block a user