mirror of
https://github.com/NinjaCheetah/libWiiPy.git
synced 2025-04-26 13:21:01 -04:00
Added methods to wad.py to allow changing a WAD's data
Also added methods to title.py to allow dumping a full WAD. Some attributes were also removed from wad.py, because the offsets would become poisoned if any changes were made to the content sizes, and they therefore should not be read.
This commit is contained in:
parent
8026fc4fa3
commit
142a121fa9
@ -45,7 +45,7 @@ class Title:
|
|||||||
"invalid.")
|
"invalid.")
|
||||||
|
|
||||||
def dump(self) -> bytes:
|
def dump(self) -> bytes:
|
||||||
"""Dumps all title components (TMD, ticket, and content) back into the WAD object, and then dumps the WAD back
|
"""Dumps all title components (TMD, Ticket, and contents) back into the WAD object, and then dumps the WAD back
|
||||||
into raw data and returns it.
|
into raw data and returns it.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
@ -53,7 +53,15 @@ class Title:
|
|||||||
wad_data : bytes
|
wad_data : bytes
|
||||||
The raw data of the WAD.
|
The raw data of the WAD.
|
||||||
"""
|
"""
|
||||||
# Dump the TMD.
|
# Dump the TMD and set it in the WAD.
|
||||||
|
self.wad.set_tmd_data(self.tmd.dump())
|
||||||
|
# Dump the Ticket and set it in the WAD.
|
||||||
|
self.wad.set_ticket_data(self.ticket.dump())
|
||||||
|
# Dump the ContentRegion and set it in the WAD.
|
||||||
|
self.wad.set_content_data(self.content.dump())
|
||||||
|
# Dump the WAD with the new regions back into raw data and return it.
|
||||||
|
wad_data = self.wad.dump()
|
||||||
|
return wad_data
|
||||||
|
|
||||||
def set_title_id(self, title_id: str) -> None:
|
def set_title_id(self, title_id: str) -> None:
|
||||||
"""Sets the Title ID of the title in both the TMD and Ticket.
|
"""Sets the Title ID of the title in both the TMD and Ticket.
|
||||||
@ -68,6 +76,44 @@ class Title:
|
|||||||
self.tmd.set_title_id(title_id)
|
self.tmd.set_title_id(title_id)
|
||||||
self.ticket.set_title_id(title_id)
|
self.ticket.set_title_id(title_id)
|
||||||
|
|
||||||
|
def get_content_by_index(self, index: id) -> bytes:
|
||||||
|
"""Gets an individual content from the content region based on the provided index, in decrypted form.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
index : int
|
||||||
|
The index of the content you want to get.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
bytes
|
||||||
|
The decrypted content listed in the content record.
|
||||||
|
"""
|
||||||
|
# Load the Title Key from the Ticket.
|
||||||
|
title_key = self.ticket.get_title_key()
|
||||||
|
# Get the decrypted content and return it.
|
||||||
|
dec_content = self.content.get_content_by_index(index, title_key)
|
||||||
|
return dec_content
|
||||||
|
|
||||||
|
def get_content_by_cid(self, cid: int) -> bytes:
|
||||||
|
"""Gets an individual content from the content region based on the provided Content ID, in decrypted form.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
cid : int
|
||||||
|
The Content ID of the content you want to get. Expected to be in decimal form.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
bytes
|
||||||
|
The decrypted content listed in the content record.
|
||||||
|
"""
|
||||||
|
# Load the Title Key from the Ticket.
|
||||||
|
title_key = self.ticket.get_title_key()
|
||||||
|
# Get the decrypted content and return it.
|
||||||
|
dec_content = self.content.get_content_by_cid(cid, title_key)
|
||||||
|
return dec_content
|
||||||
|
|
||||||
def set_enc_content(self, enc_content: bytes, cid: int, index: int, content_type: int, content_size: int,
|
def set_enc_content(self, enc_content: bytes, cid: int, index: int, content_type: int, content_size: int,
|
||||||
content_hash: bytes) -> None:
|
content_hash: bytes) -> None:
|
||||||
"""Sets the provided index to a new content with the provided Content ID. Hashes and size of the content are
|
"""Sets the provided index to a new content with the provided Content ID. Hashes and size of the content are
|
||||||
|
@ -30,13 +30,13 @@ class WAD:
|
|||||||
# This is the size of the content region, which contains all app files combined.
|
# This is the size of the content region, which contains all app files combined.
|
||||||
self.wad_content_size: int = 0
|
self.wad_content_size: int = 0
|
||||||
self.wad_meta_size: int = 0
|
self.wad_meta_size: int = 0
|
||||||
# === Offsets ===
|
# === Data ===
|
||||||
self.wad_cert_offset: int = 0
|
self.wad_cert_data: bytes = b''
|
||||||
self.wad_crl_offset: int = 0
|
self.wad_crl_data: bytes = b''
|
||||||
self.wad_tik_offset: int = 0
|
self.wad_tik_data: bytes = b''
|
||||||
self.wad_tmd_offset: int = 0
|
self.wad_tmd_data: bytes = b''
|
||||||
self.wad_content_offset: int = 0
|
self.wad_content_data: bytes = b''
|
||||||
self.wad_meta_offset: int = 0
|
self.wad_meta_data: bytes = b''
|
||||||
# Call load() to set all of the attributes from the raw WAD data provided.
|
# Call load() to set all of the attributes from the raw WAD data provided.
|
||||||
self.load()
|
self.load()
|
||||||
|
|
||||||
@ -89,14 +89,35 @@ class WAD:
|
|||||||
# ====================================================================================
|
# ====================================================================================
|
||||||
# Calculate file offsets from sizes. Every section of the WAD is padded out to a multiple of 0x40.
|
# Calculate file offsets from sizes. Every section of the WAD is padded out to a multiple of 0x40.
|
||||||
# ====================================================================================
|
# ====================================================================================
|
||||||
self.wad_cert_offset = self.wad_hdr_size
|
wad_cert_offset = self.wad_hdr_size
|
||||||
# crl isn't ever used, however an entry for its size exists in the header, so its calculated just in case.
|
# crl isn't ever used, however an entry for its size exists in the header, so its calculated just in case.
|
||||||
self.wad_crl_offset = align_value(self.wad_cert_offset + self.wad_cert_size)
|
wad_crl_offset = align_value(wad_cert_offset + self.wad_cert_size)
|
||||||
self.wad_tik_offset = align_value(self.wad_crl_offset + self.wad_crl_size)
|
wad_tik_offset = align_value(wad_crl_offset + self.wad_crl_size)
|
||||||
self.wad_tmd_offset = align_value(self.wad_tik_offset + self.wad_tik_size)
|
wad_tmd_offset = align_value(wad_tik_offset + self.wad_tik_size)
|
||||||
# meta isn't guaranteed to be used, but some older SDK titles use it, and not reading it breaks things.
|
# meta isn't guaranteed to be used, but some older SDK titles use it, and not reading it breaks things.
|
||||||
self.wad_meta_offset = align_value(self.wad_tmd_offset + self.wad_tmd_size)
|
wad_meta_offset = align_value(wad_tmd_offset + self.wad_tmd_size)
|
||||||
self.wad_content_offset = align_value(self.wad_meta_offset + self.wad_meta_size)
|
wad_content_offset = align_value(wad_meta_offset + self.wad_meta_size)
|
||||||
|
# ====================================================================================
|
||||||
|
# Load data for each WAD section based on the previously calculated offsets.
|
||||||
|
# ====================================================================================
|
||||||
|
# Cert data.
|
||||||
|
wad_data.seek(wad_cert_offset)
|
||||||
|
self.wad_cert_data = wad_data.read(self.wad_cert_size)
|
||||||
|
# Crl data.
|
||||||
|
wad_data.seek(wad_crl_offset)
|
||||||
|
self.wad_crl_data = wad_data.read(self.wad_crl_size)
|
||||||
|
# Ticket data.
|
||||||
|
wad_data.seek(wad_tik_offset)
|
||||||
|
self.wad_tik_data = wad_data.read(self.wad_tik_size)
|
||||||
|
# TMD data.
|
||||||
|
wad_data.seek(wad_tmd_offset)
|
||||||
|
self.wad_tmd_data = wad_data.read(self.wad_tmd_size)
|
||||||
|
# Content data.
|
||||||
|
wad_data.seek(wad_content_offset)
|
||||||
|
self.wad_content_data = wad_data.read(self.wad_content_size)
|
||||||
|
# Meta data.
|
||||||
|
wad_data.seek(wad_meta_offset)
|
||||||
|
self.wad_meta_data = wad_data.read(self.wad_meta_size)
|
||||||
|
|
||||||
def dump(self) -> bytes:
|
def dump(self) -> bytes:
|
||||||
"""Dumps the WAD object back into bytes. This also sets the raw WAD attribute of WAD object to the dumped data,
|
"""Dumps the WAD object back into bytes. This also sets the raw WAD attribute of WAD object to the dumped data,
|
||||||
@ -153,78 +174,6 @@ class WAD:
|
|||||||
self.load()
|
self.load()
|
||||||
return self.wad
|
return self.wad
|
||||||
|
|
||||||
def get_cert_region(self):
|
|
||||||
"""Gets the offset and size of the certificate data.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
int
|
|
||||||
The offset of the certificate data in the WAD.
|
|
||||||
int
|
|
||||||
The size of the certificate data in the WAD.
|
|
||||||
"""
|
|
||||||
return self.wad_cert_offset, self.wad_cert_size
|
|
||||||
|
|
||||||
def get_crl_region(self):
|
|
||||||
"""Gets the offset and size of the crl data.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
int
|
|
||||||
The offset of the crl data in the WAD.
|
|
||||||
int
|
|
||||||
The size of the crl data in the WAD.
|
|
||||||
"""
|
|
||||||
return self.wad_crl_offset, self.wad_crl_size
|
|
||||||
|
|
||||||
def get_ticket_region(self):
|
|
||||||
"""Gets the offset and size of the ticket data.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
int
|
|
||||||
The offset of the ticket data in the WAD.
|
|
||||||
int
|
|
||||||
The size of the ticket data in the WAD.
|
|
||||||
"""
|
|
||||||
return self.wad_tik_offset, self.wad_tik_size
|
|
||||||
|
|
||||||
def get_tmd_region(self):
|
|
||||||
"""Gets the offset and size of the TMD data.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
int
|
|
||||||
The offset of the TMD data in the WAD.
|
|
||||||
int
|
|
||||||
The size of the TMD data in the WAD.
|
|
||||||
"""
|
|
||||||
return self.wad_tmd_offset, self.wad_tmd_size
|
|
||||||
|
|
||||||
def get_content_region(self):
|
|
||||||
"""Gets the offset and size of the content of the WAD.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
int
|
|
||||||
The offset of the content data in the WAD.
|
|
||||||
int
|
|
||||||
The size of the content data in the WAD.
|
|
||||||
"""
|
|
||||||
return self.wad_content_offset, self.wad_content_size
|
|
||||||
|
|
||||||
def get_meta_region(self):
|
|
||||||
"""Gets the offset and size of the meta region of the WAD, which is typically unused.
|
|
||||||
|
|
||||||
Returns
|
|
||||||
-------
|
|
||||||
int
|
|
||||||
The offset of the meta region in the WAD.
|
|
||||||
int
|
|
||||||
The size of the meta region in the WAD.
|
|
||||||
"""
|
|
||||||
return self.wad_meta_offset, self.wad_meta_size
|
|
||||||
|
|
||||||
def get_wad_type(self):
|
def get_wad_type(self):
|
||||||
"""Gets the type of the WAD.
|
"""Gets the type of the WAD.
|
||||||
|
|
||||||
@ -235,7 +184,7 @@ class WAD:
|
|||||||
"""
|
"""
|
||||||
return self.wad_type
|
return self.wad_type
|
||||||
|
|
||||||
def get_cert_data(self):
|
def get_cert_data(self) -> bytes:
|
||||||
"""Gets the certificate data from the WAD.
|
"""Gets the certificate data from the WAD.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
@ -243,12 +192,9 @@ class WAD:
|
|||||||
bytes
|
bytes
|
||||||
The certificate data.
|
The certificate data.
|
||||||
"""
|
"""
|
||||||
wad_data = io.BytesIO(self.wad)
|
return self.wad_cert_data
|
||||||
wad_data.seek(self.wad_cert_offset)
|
|
||||||
cert_data = wad_data.read(self.wad_cert_size)
|
|
||||||
return cert_data
|
|
||||||
|
|
||||||
def get_crl_data(self):
|
def get_crl_data(self) -> bytes:
|
||||||
"""Gets the crl data from the WAD, if it exists.
|
"""Gets the crl data from the WAD, if it exists.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
@ -256,12 +202,9 @@ class WAD:
|
|||||||
bytes
|
bytes
|
||||||
The crl data.
|
The crl data.
|
||||||
"""
|
"""
|
||||||
wad_data = io.BytesIO(self.wad)
|
return self.wad_crl_data
|
||||||
wad_data.seek(self.wad_crl_offset)
|
|
||||||
crl_data = wad_data.read(self.wad_crl_size)
|
|
||||||
return crl_data
|
|
||||||
|
|
||||||
def get_ticket_data(self):
|
def get_ticket_data(self) -> bytes:
|
||||||
"""Gets the ticket data from the WAD.
|
"""Gets the ticket data from the WAD.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
@ -269,12 +212,9 @@ class WAD:
|
|||||||
bytes
|
bytes
|
||||||
The ticket data.
|
The ticket data.
|
||||||
"""
|
"""
|
||||||
wad_data = io.BytesIO(self.wad)
|
return self.wad_tik_data
|
||||||
wad_data.seek(self.wad_tik_offset)
|
|
||||||
ticket_data = wad_data.read(self.wad_tik_size)
|
|
||||||
return ticket_data
|
|
||||||
|
|
||||||
def get_tmd_data(self):
|
def get_tmd_data(self) -> bytes:
|
||||||
"""Returns the TMD data from the WAD.
|
"""Returns the TMD data from the WAD.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
@ -282,12 +222,9 @@ class WAD:
|
|||||||
bytes
|
bytes
|
||||||
The TMD data.
|
The TMD data.
|
||||||
"""
|
"""
|
||||||
wad_data = io.BytesIO(self.wad)
|
return self.wad_tmd_data
|
||||||
wad_data.seek(self.wad_tmd_offset)
|
|
||||||
tmd_data = wad_data.read(self.wad_tmd_size)
|
|
||||||
return tmd_data
|
|
||||||
|
|
||||||
def get_content_data(self):
|
def get_content_data(self) -> bytes:
|
||||||
"""Gets the content of the WAD.
|
"""Gets the content of the WAD.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
@ -295,12 +232,9 @@ class WAD:
|
|||||||
bytes
|
bytes
|
||||||
The content data.
|
The content data.
|
||||||
"""
|
"""
|
||||||
wad_data = io.BytesIO(self.wad)
|
return self.wad_content_data
|
||||||
wad_data.seek(self.wad_content_offset)
|
|
||||||
content_data = wad_data.read(self.wad_content_size)
|
|
||||||
return content_data
|
|
||||||
|
|
||||||
def get_meta_data(self):
|
def get_meta_data(self) -> bytes:
|
||||||
"""Gets the meta region of the WAD, which is typically unused.
|
"""Gets the meta region of the WAD, which is typically unused.
|
||||||
|
|
||||||
Returns
|
Returns
|
||||||
@ -308,7 +242,76 @@ class WAD:
|
|||||||
bytes
|
bytes
|
||||||
The meta region.
|
The meta region.
|
||||||
"""
|
"""
|
||||||
wad_data = io.BytesIO(self.wad)
|
return self.wad_meta_data
|
||||||
wad_data.seek(self.wad_meta_offset)
|
|
||||||
meta_data = wad_data.read(self.wad_meta_size)
|
def set_cert_data(self, cert_data) -> None:
|
||||||
return meta_data
|
"""Sets the certificate data of the WAD. Also calculates the new size.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
cert_data : bytes
|
||||||
|
The new certificate data.
|
||||||
|
"""
|
||||||
|
self.wad_cert_data = cert_data
|
||||||
|
# Calculate the size of the new cert data.
|
||||||
|
self.wad_cert_size = len(cert_data)
|
||||||
|
|
||||||
|
def set_crl_data(self, crl_data) -> None:
|
||||||
|
"""Sets the crl data of the WAD. Also calculates the new size.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
crl_data : bytes
|
||||||
|
The new crl data.
|
||||||
|
"""
|
||||||
|
self.wad_crl_data = crl_data
|
||||||
|
# Calculate the size of the new crl data.
|
||||||
|
self.wad_crl_size = len(crl_data)
|
||||||
|
|
||||||
|
def set_tmd_data(self, tmd_data) -> None:
|
||||||
|
"""Sets the TMD data of the WAD. Also calculates the new size.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
tmd_data : bytes
|
||||||
|
The new TMD data.
|
||||||
|
"""
|
||||||
|
self.wad_tmd_data = tmd_data
|
||||||
|
# Calculate the size of the new TMD data.
|
||||||
|
self.wad_tmd_size = len(tmd_data)
|
||||||
|
|
||||||
|
def set_ticket_data(self, tik_data) -> None:
|
||||||
|
"""Sets the Ticket data of the WAD. Also calculates the new size.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
tik_data : bytes
|
||||||
|
The new TMD data.
|
||||||
|
"""
|
||||||
|
self.wad_tik_data = tik_data
|
||||||
|
# Calculate the size of the new Ticket data.
|
||||||
|
self.wad_tik_size = len(tik_data)
|
||||||
|
|
||||||
|
def set_content_data(self, content_data) -> None:
|
||||||
|
"""Sets the content data of the WAD. Also calculates the new size.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
content_data : bytes
|
||||||
|
The new content data.
|
||||||
|
"""
|
||||||
|
self.wad_content_data = content_data
|
||||||
|
# Calculate the size of the new content data.
|
||||||
|
self.wad_content_size = len(content_data)
|
||||||
|
|
||||||
|
def set_meta_data(self, meta_data) -> None:
|
||||||
|
"""Sets the meta data of the WAD. Also calculates the new size.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
meta_data : bytes
|
||||||
|
The new meta data.
|
||||||
|
"""
|
||||||
|
self.wad_meta_data = meta_data
|
||||||
|
# Calculate the size of the new meta data.
|
||||||
|
self.wad_meta_size = len(meta_data)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user