mirror of
https://github.com/NinjaCheetah/libWiiPy.git
synced 2025-04-25 12:51:01 -04:00
Add preliminary support for parsing 00000000.app
New module banner.py offers classes for IMD5 and IMET headers, U8 unpacker now supports U8 archives with IMET headers.
This commit is contained in:
parent
cfd105ba81
commit
855200bb98
@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "libWiiPy"
|
||||
version = "0.5.3"
|
||||
version = "0.6.0"
|
||||
authors = [
|
||||
{ name="NinjaCheetah", email="ninjacheetah@ncxprogramming.com" },
|
||||
{ name="Lillian Skinner", email="lillian@randommeaninglesscharacters.com" }
|
||||
|
@ -66,7 +66,28 @@ class U8Archive:
|
||||
u8_data.seek(0x0)
|
||||
self.u8_magic = u8_data.read(4)
|
||||
if self.u8_magic != b'\x55\xAA\x38\x2D':
|
||||
raise TypeError("This is not a valid U8 archive!")
|
||||
# Check for an IMET header, if the file doesn't start with the proper magic number. The header magic
|
||||
# may be at either 0x40 or 0x80 depending on whether this title has a build tag at the start or not.
|
||||
u8_data.seek(0x40)
|
||||
self.u8_magic = u8_data.read(4)
|
||||
if self.u8_magic == b'\x49\x4D\x45\x54':
|
||||
# IMET with no build tag means the U8 archive should start at 0x600.
|
||||
u8_data.seek(0x600)
|
||||
self.u8_magic = u8_data.read(4)
|
||||
if self.u8_magic != b'\x55\xAA\x38\x2D':
|
||||
raise TypeError("This is not a valid U8 archive!")
|
||||
else:
|
||||
# This check will pass if the IMET comes after a build tag.
|
||||
u8_data.seek(0x80)
|
||||
self.u8_magic = u8_data.read(4)
|
||||
if self.u8_magic == b'\x49\x4D\x45\x54':
|
||||
# IMET with a build tag means the U8 archive should start at 0x640.
|
||||
u8_data.seek(0x640)
|
||||
self.u8_magic = u8_data.read(4)
|
||||
if self.u8_magic != b'\x55\xAA\x38\x2D':
|
||||
raise TypeError("This is not a valid U8 archive!")
|
||||
else:
|
||||
raise TypeError("This is not a valid U8 archive!")
|
||||
# Offset of the root node, which will always be 0x20.
|
||||
self.root_node_offset = int.from_bytes(u8_data.read(4))
|
||||
# The size of the U8 header.
|
||||
@ -257,7 +278,7 @@ def _pack_u8_dir(u8_archive: U8Archive, current_path, node_count, parent_node):
|
||||
return u8_archive, node_count
|
||||
|
||||
|
||||
def pack_u8(input_path) -> bytes:
|
||||
def pack_u8(input_path, generate_imet=False, imet_titles:List[str]=None) -> bytes:
|
||||
"""
|
||||
Packs the provided file or folder into a new U8 archive, and returns the raw file data for it.
|
||||
|
||||
@ -265,6 +286,12 @@ def pack_u8(input_path) -> bytes:
|
||||
----------
|
||||
input_path
|
||||
The path to the input file or folder.
|
||||
generate_imet : bool, optional
|
||||
Whether an IMET header should be generated for this U8 archive or not. IMET headers are only used for channel
|
||||
banners (00000000.app). Defaults to False.
|
||||
imet_titles : List[str], optional
|
||||
A list of the channel title in different languages for the IMET header. If only one item is provided, that
|
||||
item will be used for all entries in the header. Defaults to None, and is only used when generate_imet is True.
|
||||
|
||||
Returns
|
||||
-------
|
||||
@ -287,4 +314,4 @@ def pack_u8(input_path) -> bytes:
|
||||
elif input_path.is_file():
|
||||
raise ValueError("This does not appear to be a directory.")
|
||||
else:
|
||||
raise FileNotFoundError("Input directory: \"" + str(input_path) + "\" does not exist!")
|
||||
raise FileNotFoundError(f"Input directory: \"{input_path}\" does not exist!")
|
||||
|
73
src/libWiiPy/title/banner.py
Normal file
73
src/libWiiPy/title/banner.py
Normal file
@ -0,0 +1,73 @@
|
||||
# "title/banner.py" from libWiiPy by NinjaCheetah & Contributors
|
||||
# https://github.com/NinjaCheetah/libWiiPy
|
||||
#
|
||||
# See https://wiibrew.org/wiki/Opening.bnr for details about the Wii's banner format
|
||||
|
||||
from dataclasses import dataclass as _dataclass
|
||||
from typing import List
|
||||
|
||||
|
||||
@_dataclass
|
||||
class IMD5Header:
|
||||
"""
|
||||
An IMD5Header object that contains the properties of an IMD5 header. These headers precede the data of banner.bin
|
||||
and icon.bin inside the banner (00000000.app) of a channel, and are used to verify the data of those files.
|
||||
|
||||
An IMD5 header is always 32 bytes long.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
magic : str
|
||||
Magic number for the header, should be "IMD5".
|
||||
file_size : int
|
||||
The size of the file this header precedes.
|
||||
zeros : int
|
||||
8 bytes of zero padding.
|
||||
md5_hash : bytes
|
||||
The MD5 hash of the file this header precedes.
|
||||
"""
|
||||
magic: str # Should always be "IMD5"
|
||||
file_size: int
|
||||
zeros: int
|
||||
md5_hash: bytes
|
||||
|
||||
|
||||
@_dataclass
|
||||
class IMETHeader:
|
||||
"""
|
||||
An IMETHeader object that contains the properties of an IMET header. These headers precede the data of a channel
|
||||
banner (00000000.app), and are used to store metadata about the banner and verify its data.
|
||||
|
||||
An IMET header is always 1,536 bytes long.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
zeros : int
|
||||
64 bytes of zero padding.
|
||||
magic : str
|
||||
Magic number for the header, should be "IMD5".
|
||||
hash_size : int
|
||||
Length of the MD5 hash.
|
||||
imet_version : int
|
||||
Version of the IMET header. Normally always 3.
|
||||
sizes : List[int]
|
||||
The file sizes of icon.bin, banner.bin, and sound.bin.
|
||||
flag1 : int
|
||||
Unknown.
|
||||
channel_names : List[str]
|
||||
The name of the channel this header is for in Japanese, English, German, French, Spanish, Italian, Dutch,
|
||||
Simplified Chinese, Traditional Chinese, and Korean, in that order.
|
||||
zeros2 : int
|
||||
An additional 588 bytes of zero padding.
|
||||
md5_hash : bytes
|
||||
"MD5 of 0 to 'hashsize' in header. crypto should be all 0's when calculating final MD5" -WiiBrew
|
||||
"""
|
||||
zeros: int
|
||||
magic: str # Should always be "IMET"
|
||||
hash_size: int
|
||||
imet_version: int # Always 3?
|
||||
sizes: List[int] # Should only have 3 items
|
||||
flag1: int # Unknown
|
||||
channel_names: List[str] # Should have 10 items
|
||||
zeros2: int
|
||||
md5_hash: bytes
|
@ -23,12 +23,11 @@ class _TitleLimit:
|
||||
Attributes
|
||||
----------
|
||||
limit_type : int
|
||||
The type of play limit applied.
|
||||
The type of play limit applied. 0 and 3 are none, 1 is a time limit, and 4 is a launch count limit.
|
||||
maximum_usage : int
|
||||
The maximum value for the type of play limit applied.
|
||||
"""
|
||||
# The type of play limit applied.
|
||||
# 0 = None, 1 = Time Limit, 3 = None, 4 = Launch Count
|
||||
limit_type: int
|
||||
# The maximum value of the limit applied.
|
||||
maximum_usage: int
|
||||
|
Loading…
x
Reference in New Issue
Block a user