From ed21fc070484b5cc10eddeb05fc6b34001c95b85 Mon Sep 17 00:00:00 2001 From: NinjaCheetah <58050615+NinjaCheetah@users.noreply.github.com> Date: Wed, 28 Feb 2024 23:52:26 -0500 Subject: [PATCH 1/5] Updated pyproject.toml for first public release --- pyproject.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 856390a..b652676 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,9 @@ [project] name = "libWiiPy" -version = "0.0.1" +version = "0.1.0" authors = [ - { name="NinjaCheetah", email="ninjacheetah@ncxprogramming.com" }, + { name="NinjaCheetah", email="ninjacheetah@ncxprogramming.com" }, + { name="Lillian Skinner", email="lillian@randommeaninglesscharacters.com" } ] description = "A Wii-related library for Python" readme = "README.md" From c5025348dde9c4fd281646e4702f47d94429e655 Mon Sep 17 00:00:00 2001 From: rmc Date: Thu, 29 Feb 2024 22:12:26 -0500 Subject: [PATCH 2/5] Get WAD content records. --- .gitignore | 8 +++++++- src/libWiiPy/tmd.py | 15 ++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 62b9984..aef39b9 100644 --- a/.gitignore +++ b/.gitignore @@ -163,4 +163,10 @@ cython_debug/ # Allows me to keep TMD files in my repository folder for testing without accidentally publishing them *.tmd -*.wad \ No newline at end of file +*.wad +out_prod/ +remakewad.pl + +# Also awful macOS files +*._* +*.DS_Store diff --git a/src/libWiiPy/tmd.py b/src/libWiiPy/tmd.py index 31155b0..114ae47 100644 --- a/src/libWiiPy/tmd.py +++ b/src/libWiiPy/tmd.py @@ -5,6 +5,7 @@ import io import binascii +import struct from dataclasses import dataclass from typing import List @@ -41,7 +42,8 @@ class TMD: self.title_version: int self.num_contents: int self.boot_index: int - self.content_record: List[ContentRecord] + self.content_record: List[ContentRecord] = [] + self.content_record_hdr: List = [] # Load data from TMD file with io.BytesIO(tmd) as tmddata: # Signing certificate issuer @@ -101,6 +103,13 @@ class TMD: # Content index in content list that contains the boot file tmddata.seek(0x1E0) self.boot_index = tmddata.read(2) + # Got content records for the number of contents in num_contents. + i = 0 + while i < self.num_contents: + tmddata.seek(0x1E4 + (36 * i)) + self.content_record_hdr = struct.unpack(">LHH4x4s20s", tmddata.read(36)) + self.content_record.append(ContentRecord(self.content_record_hdr[0], self.content_record_hdr[1], self.content_record_hdr[2], self.content_record_hdr[3], self.content_record_hdr[4])) + i += 1 def get_title_id(self): """Returns the TID of the TMD's associated title.""" @@ -183,3 +192,7 @@ class TMD: def get_num_contents(self): """Returns the number of contents listed in the TMD.""" return self.num_contents + + def get_content_records(self, record): + """Returns all values for the specified content record.""" + return self.content_record[record].cid, self.content_record[record].index, self.content_record[record].content_type, self.content_record[record].content_size, self.content_record[record].content_hash From c9c4aa5b6225e4977c4305616b7467db7dd452ae Mon Sep 17 00:00:00 2001 From: rmc Date: Thu, 29 Feb 2024 22:58:51 -0500 Subject: [PATCH 3/5] Proper string formatting - NinjaCheetah, do the error returning please. --- src/libWiiPy/tmd.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libWiiPy/tmd.py b/src/libWiiPy/tmd.py index 114ae47..ff5faff 100644 --- a/src/libWiiPy/tmd.py +++ b/src/libWiiPy/tmd.py @@ -108,7 +108,7 @@ class TMD: while i < self.num_contents: tmddata.seek(0x1E4 + (36 * i)) self.content_record_hdr = struct.unpack(">LHH4x4s20s", tmddata.read(36)) - self.content_record.append(ContentRecord(self.content_record_hdr[0], self.content_record_hdr[1], self.content_record_hdr[2], self.content_record_hdr[3], self.content_record_hdr[4])) + self.content_record.append(ContentRecord(int(self.content_record_hdr[0]), int(self.content_record_hdr[1]), int(self.content_record_hdr[2]), int.from_bytes(self.content_record_hdr[3]), binascii.hexlify(self.content_record_hdr[4]).decode())) i += 1 def get_title_id(self): @@ -195,4 +195,7 @@ class TMD: def get_content_records(self, record): """Returns all values for the specified content record.""" - return self.content_record[record].cid, self.content_record[record].index, self.content_record[record].content_type, self.content_record[record].content_size, self.content_record[record].content_hash + if record <= self.num_contents: + return self.content_record[record].cid, self.content_record[record].index, self.content_record[record].content_type, self.content_record[record].content_size, self.content_record[record].content_hash + else: + return From b24112424030417ee4010c97d45923245a053f3d Mon Sep 17 00:00:00 2001 From: NinjaCheetah <58050615+NinjaCheetah@users.noreply.github.com> Date: Thu, 29 Feb 2024 23:40:33 -0500 Subject: [PATCH 4/5] Added error handling and made minor adjustments --- src/libWiiPy/tmd.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/libWiiPy/tmd.py b/src/libWiiPy/tmd.py index ff5faff..b210462 100644 --- a/src/libWiiPy/tmd.py +++ b/src/libWiiPy/tmd.py @@ -15,9 +15,9 @@ class ContentRecord: """Creates a content record object that contains the details of a content contained in a title.""" cid: int # Content ID index: int # Index in the list of contents - content_type: int # normal: 0x0001; dlc: 0x4001; shared: 0x8001 + content_type: int # Normal: 0x0001, DLC: 0x4001, Shared: 0x8001 content_size: int - content_hash: bytearray # SHA1 hash content + content_hash: bytes # SHA1 hash content class TMD: @@ -42,8 +42,7 @@ class TMD: self.title_version: int self.num_contents: int self.boot_index: int - self.content_record: List[ContentRecord] = [] - self.content_record_hdr: List = [] + self.content_records: List[ContentRecord] = [] # Load data from TMD file with io.BytesIO(tmd) as tmddata: # Signing certificate issuer @@ -103,13 +102,14 @@ class TMD: # Content index in content list that contains the boot file tmddata.seek(0x1E0) self.boot_index = tmddata.read(2) - # Got content records for the number of contents in num_contents. - i = 0 - while i < self.num_contents: - tmddata.seek(0x1E4 + (36 * i)) - self.content_record_hdr = struct.unpack(">LHH4x4s20s", tmddata.read(36)) - self.content_record.append(ContentRecord(int(self.content_record_hdr[0]), int(self.content_record_hdr[1]), int(self.content_record_hdr[2]), int.from_bytes(self.content_record_hdr[3]), binascii.hexlify(self.content_record_hdr[4]).decode())) - i += 1 + # Get content records for the number of contents in num_contents. + for content in range(0, self.num_contents): + tmddata.seek(0x1E4 + (36 * content)) + content_record_hdr = struct.unpack(">LHH4x4s20s", tmddata.read(36)) + self.content_records.append( + ContentRecord(int(content_record_hdr[0]), int(content_record_hdr[1]), + int(content_record_hdr[2]), int.from_bytes(content_record_hdr[3]), + binascii.hexlify(content_record_hdr[4]))) def get_title_id(self): """Returns the TID of the TMD's associated title.""" @@ -193,9 +193,10 @@ class TMD: """Returns the number of contents listed in the TMD.""" return self.num_contents - def get_content_records(self, record): - """Returns all values for the specified content record.""" - if record <= self.num_contents: - return self.content_record[record].cid, self.content_record[record].index, self.content_record[record].content_type, self.content_record[record].content_size, self.content_record[record].content_hash + def get_content_record(self, record): + """Returns the content record at the specified index.""" + if record < self.num_contents: + return self.content_records[record] else: - return + raise IndexError("Invalid content record! TMD lists '" + str(self.num_contents) + + "' contents but index was '" + str(record) + "'!") From f9b5e7aa16ee6715a720f6fa49ad535677cd15a1 Mon Sep 17 00:00:00 2001 From: rmc Date: Thu, 29 Feb 2024 23:52:49 -0500 Subject: [PATCH 5/5] Small edit to return error. --- src/libWiiPy/tmd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libWiiPy/tmd.py b/src/libWiiPy/tmd.py index b210462..b875698 100644 --- a/src/libWiiPy/tmd.py +++ b/src/libWiiPy/tmd.py @@ -198,5 +198,5 @@ class TMD: if record < self.num_contents: return self.content_records[record] else: - raise IndexError("Invalid content record! TMD lists '" + str(self.num_contents) + + raise IndexError("Invalid content record! TMD lists '" + str(self.num_contents - 1) + "' contents but index was '" + str(record) + "'!")