mirror of
https://github.com/NinjaCheetah/libWiiPy.git
synced 2025-04-26 13:21:01 -04:00
Entirely restructured package to make it more of a proper Python package
THIS IS A BREAKING COMMIT! ALL v0.2.X BASED PROJECTS WILL NEED TO BE UPDATED TO SUPPORT v0.3.X!
This commit is contained in:
parent
bc9224e40b
commit
ade4b68394
0
src/__init__.py
Normal file
0
src/__init__.py
Normal file
@ -1,14 +1,9 @@
|
|||||||
# "__init__.py" from libWiiPy by NinjaCheetah & Contributors
|
# "__init__.py" from libWiiPy by NinjaCheetah & Contributors
|
||||||
# https://github.com/NinjaCheetah/libWiiPy
|
# https://github.com/NinjaCheetah/libWiiPy
|
||||||
#
|
#
|
||||||
# These are the essential modules from libWiiPy that you'd probably want imported by default.
|
# These are the essential submodules from libWiiPy that you'd probably want imported by default.
|
||||||
|
|
||||||
from .commonkeys import *
|
__all__ = ["archive", "title"]
|
||||||
from .content import *
|
|
||||||
from .ticket import *
|
from . import archive
|
||||||
from .crypto import *
|
from . import title
|
||||||
from .title import *
|
|
||||||
from .tmd import *
|
|
||||||
from .wad import *
|
|
||||||
from .nus import *
|
|
||||||
from .u8 import *
|
|
||||||
|
4
src/libWiiPy/archive/__init__.py
Normal file
4
src/libWiiPy/archive/__init__.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# "archive/__init__.py" from libWiiPy by NinjaCheetah & Contributors
|
||||||
|
# https://github.com/NinjaCheetah/libWiiPy
|
||||||
|
|
||||||
|
from .u8 import *
|
@ -1,4 +1,4 @@
|
|||||||
# "u8.py" from libWiiPy by NinjaCheetah & Contributors
|
# "archive/u8.py" from libWiiPy by NinjaCheetah & Contributors
|
||||||
# https://github.com/NinjaCheetah/libWiiPy
|
# https://github.com/NinjaCheetah/libWiiPy
|
||||||
#
|
#
|
||||||
# See https://wiibrew.org/wiki/U8_archive for details about the U8 archive format
|
# See https://wiibrew.org/wiki/U8_archive for details about the U8 archive format
|
||||||
@ -6,14 +6,38 @@
|
|||||||
import io
|
import io
|
||||||
import binascii
|
import binascii
|
||||||
import os
|
import os
|
||||||
|
from dataclasses import dataclass
|
||||||
from typing import List
|
from typing import List
|
||||||
from .types import U8Node
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class U8Node:
|
||||||
|
"""
|
||||||
|
A U8Node object that contains the data of a single node in a U8 file header. Each node keeps track of whether this
|
||||||
|
node is for a file or directory, the offset of the name of the file/directory, the offset of the data for the file/
|
||||||
|
directory, and the size of the data.
|
||||||
|
|
||||||
|
Attributes
|
||||||
|
----------
|
||||||
|
type : int
|
||||||
|
Whether this node refers to a file or a directory. Either 0x0000 for files, or 0x0100 for directories.
|
||||||
|
name_offset : int
|
||||||
|
The offset of the name of the file/directory this node refers to.
|
||||||
|
data_offset : int
|
||||||
|
The offset of the data for the file/directory this node refers to.
|
||||||
|
size : int
|
||||||
|
The size of the data for this node.
|
||||||
|
"""
|
||||||
|
type: int
|
||||||
|
name_offset: int
|
||||||
|
data_offset: int
|
||||||
|
size: int
|
||||||
|
|
||||||
|
|
||||||
class U8Archive:
|
class U8Archive:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""
|
"""
|
||||||
A U8 object that allows for extracting and packing U8 archives.
|
A U8 object that allows for managing the contents of a U8 archive.
|
||||||
|
|
||||||
Attributes
|
Attributes
|
||||||
----------
|
----------
|
||||||
@ -77,33 +101,54 @@ class U8Archive:
|
|||||||
else:
|
else:
|
||||||
self.u8_file_data_list.append(b'')
|
self.u8_file_data_list.append(b'')
|
||||||
|
|
||||||
def extract_to_folder(self, output_folder) -> None:
|
def dump(self) -> None:
|
||||||
if os.path.isdir(output_folder):
|
"""
|
||||||
raise ValueError("Output folder already exists!")
|
Dumps the U8Archive object into a U8 file.
|
||||||
if self.u8_node_list is []:
|
"""
|
||||||
raise ValueError("No U8 file is loaded!")
|
u8_data = b''
|
||||||
|
# Magic number.
|
||||||
|
u8_data += b'\x55\xAA\x38\x2D'
|
||||||
|
# Root node offset (this is always 0x20).
|
||||||
|
u8_data += int.to_bytes(0x20, 4)
|
||||||
|
|
||||||
os.mkdir(output_folder)
|
|
||||||
|
|
||||||
current_dir = ""
|
def extract_u8(u8_data, output_folder) -> None:
|
||||||
for node in range(len(self.u8_node_list)):
|
if os.path.isdir(output_folder):
|
||||||
if self.u8_node_list[node].name_offset != 0:
|
raise ValueError("Output folder already exists!")
|
||||||
if self.u8_node_list[node].type == 256:
|
|
||||||
if self.u8_node_list[node].data_offset == 0:
|
os.mkdir(output_folder)
|
||||||
os.mkdir(os.path.join(output_folder, self.file_name_list[node]))
|
|
||||||
current_dir = self.file_name_list[node]
|
u8_archive = U8Archive()
|
||||||
elif self.u8_node_list[node].data_offset < node:
|
u8_archive.load(u8_data)
|
||||||
lower_path = os.path.join(output_folder, current_dir)
|
|
||||||
os.mkdir(os.path.join(lower_path, self.file_name_list[node]))
|
current_dir = ""
|
||||||
current_dir = os.path.join(current_dir, self.file_name_list[node])
|
for node in range(len(u8_archive.u8_node_list)):
|
||||||
elif self.u8_node_list[node].type == 0:
|
if u8_archive.u8_node_list[node].name_offset != 0:
|
||||||
|
if u8_archive.u8_node_list[node].type == 256:
|
||||||
|
if u8_archive.u8_node_list[node].data_offset == 0:
|
||||||
|
os.mkdir(os.path.join(output_folder, u8_archive.file_name_list[node]))
|
||||||
|
current_dir = u8_archive.file_name_list[node]
|
||||||
|
elif u8_archive.u8_node_list[node].data_offset < node:
|
||||||
lower_path = os.path.join(output_folder, current_dir)
|
lower_path = os.path.join(output_folder, current_dir)
|
||||||
output_file = open(os.path.join(lower_path, self.file_name_list[node]), "wb")
|
os.mkdir(os.path.join(lower_path, u8_archive.file_name_list[node]))
|
||||||
output_file.write(self.u8_file_data_list[node])
|
current_dir = os.path.join(current_dir, u8_archive.file_name_list[node])
|
||||||
output_file.close()
|
elif u8_archive.u8_node_list[node].type == 0:
|
||||||
|
lower_path = os.path.join(output_folder, current_dir)
|
||||||
def pack_from_folder(self, input_folder) -> None:
|
output_file = open(os.path.join(lower_path, u8_archive.file_name_list[node]), "wb")
|
||||||
if not os.path.isdir(input_folder):
|
output_file.write(u8_archive.u8_file_data_list[node])
|
||||||
raise ValueError("Input folder does not exist!")
|
output_file.close()
|
||||||
|
|
||||||
|
|
||||||
|
def pack_u8(input_data) -> None:
|
||||||
|
if os.path.isdir(input_data):
|
||||||
|
raise ValueError("Only single-file packing is currently supported!")
|
||||||
|
elif os.path.isfile(input_data):
|
||||||
|
with open(input_data, "rb") as f:
|
||||||
|
u8_archive = U8Archive()
|
||||||
|
|
||||||
|
file_name = os.path.basename(input_data)
|
||||||
|
|
||||||
|
u8_archive.file_name_list.append(file_name)
|
||||||
|
u8_archive.u8_file_data_list.append(f.read())
|
||||||
|
|
||||||
|
|
8
src/libWiiPy/title/__init__.py
Normal file
8
src/libWiiPy/title/__init__.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# "title/__init__.py" from libWiiPy by NinjaCheetah & Contributors
|
||||||
|
# https://github.com/NinjaCheetah/libWiiPy
|
||||||
|
|
||||||
|
from .content import *
|
||||||
|
from .ticket import *
|
||||||
|
from .title import *
|
||||||
|
from .tmd import *
|
||||||
|
from .wad import *
|
@ -1,4 +1,4 @@
|
|||||||
# "commonkeys.py" from libWiiPy by NinjaCheetah & Contributors
|
# "title/commonkeys.py" from libWiiPy by NinjaCheetah & Contributors
|
||||||
# https://github.com/NinjaCheetah/libWiiPy
|
# https://github.com/NinjaCheetah/libWiiPy
|
||||||
|
|
||||||
import binascii
|
import binascii
|
@ -1,4 +1,4 @@
|
|||||||
# "content.py" from libWiiPy by NinjaCheetah & Contributors
|
# "title/content.py" from libWiiPy by NinjaCheetah & Contributors
|
||||||
# https://github.com/NinjaCheetah/libWiiPy
|
# https://github.com/NinjaCheetah/libWiiPy
|
||||||
#
|
#
|
||||||
# See https://wiibrew.org/wiki/Title for details about how titles are formatted
|
# See https://wiibrew.org/wiki/Title for details about how titles are formatted
|
||||||
@ -7,8 +7,8 @@ import io
|
|||||||
import sys
|
import sys
|
||||||
import hashlib
|
import hashlib
|
||||||
from typing import List
|
from typing import List
|
||||||
from .types import ContentRecord
|
from src.libWiiPy.types import ContentRecord
|
||||||
from .crypto import decrypt_content, encrypt_content
|
from src.libWiiPy.title.crypto import decrypt_content, encrypt_content
|
||||||
|
|
||||||
|
|
||||||
class ContentRegion:
|
class ContentRegion:
|
@ -1,9 +1,9 @@
|
|||||||
# "crypto.py" from libWiiPy by NinjaCheetah & Contributors
|
# "title/crypto.py" from libWiiPy by NinjaCheetah & Contributors
|
||||||
# https://github.com/NinjaCheetah/libWiiPy
|
# https://github.com/NinjaCheetah/libWiiPy
|
||||||
|
|
||||||
import struct
|
import struct
|
||||||
from .commonkeys import get_common_key
|
from src.libWiiPy.title.commonkeys import get_common_key
|
||||||
from .shared import convert_tid_to_iv
|
from src.libWiiPy.shared import convert_tid_to_iv
|
||||||
|
|
||||||
from Crypto.Cipher import AES
|
from Crypto.Cipher import AES
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
# "nus.py" from libWiiPy by NinjaCheetah & Contributors
|
# "title/nus.py" from libWiiPy by NinjaCheetah & Contributors
|
||||||
# https://github.com/NinjaCheetah/libWiiPy
|
# https://github.com/NinjaCheetah/libWiiPy
|
||||||
#
|
#
|
||||||
# See https://wiibrew.org/wiki/NUS for details about the NUS
|
# See https://wiibrew.org/wiki/NUS for details about the NUS
|
||||||
@ -6,9 +6,9 @@
|
|||||||
import requests
|
import requests
|
||||||
import hashlib
|
import hashlib
|
||||||
from typing import List
|
from typing import List
|
||||||
from .title import Title
|
from src.libWiiPy.title.title import Title
|
||||||
from .tmd import TMD
|
from src.libWiiPy.title.tmd import TMD
|
||||||
from .ticket import Ticket
|
from src.libWiiPy.title.ticket import Ticket
|
||||||
|
|
||||||
nus_endpoint = ["http://nus.cdn.shop.wii.com/ccs/download/", "http://ccs.cdn.wup.shop.nintendo.net/ccs/download/"]
|
nus_endpoint = ["http://nus.cdn.shop.wii.com/ccs/download/", "http://ccs.cdn.wup.shop.nintendo.net/ccs/download/"]
|
||||||
|
|
@ -1,12 +1,12 @@
|
|||||||
# "ticket.py" from libWiiPy by NinjaCheetah & Contributors
|
# "title/ticket.py" from libWiiPy by NinjaCheetah & Contributors
|
||||||
# https://github.com/NinjaCheetah/libWiiPy
|
# https://github.com/NinjaCheetah/libWiiPy
|
||||||
#
|
#
|
||||||
# See https://wiibrew.org/wiki/Ticket for details about the ticket format
|
# See https://wiibrew.org/wiki/Ticket for details about the ticket format
|
||||||
|
|
||||||
import io
|
import io
|
||||||
import binascii
|
import binascii
|
||||||
from .crypto import decrypt_title_key
|
from src.libWiiPy.title.crypto import decrypt_title_key
|
||||||
from .types import TitleLimit
|
from src.libWiiPy.types import TitleLimit
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
|||||||
# "title.py" from libWiiPy by NinjaCheetah & Contributors
|
# "title/title.py" from libWiiPy by NinjaCheetah & Contributors
|
||||||
# https://github.com/NinjaCheetah/libWiiPy
|
# https://github.com/NinjaCheetah/libWiiPy
|
||||||
#
|
#
|
||||||
# See https://wiibrew.org/wiki/Title for details about how titles are formatted
|
# See https://wiibrew.org/wiki/Title for details about how titles are formatted
|
||||||
|
|
||||||
from .content import ContentRegion
|
from src.libWiiPy.title.content import ContentRegion
|
||||||
from .ticket import Ticket
|
from src.libWiiPy.title.ticket import Ticket
|
||||||
from .tmd import TMD
|
from src.libWiiPy.title.tmd import TMD
|
||||||
from .wad import WAD
|
from src.libWiiPy.title.wad import WAD
|
||||||
|
|
||||||
|
|
||||||
class Title:
|
class Title:
|
@ -1,4 +1,4 @@
|
|||||||
# "tmd.py" from libWiiPy by NinjaCheetah & Contributors
|
# "title/tmd.py" from libWiiPy by NinjaCheetah & Contributors
|
||||||
# https://github.com/NinjaCheetah/libWiiPy
|
# https://github.com/NinjaCheetah/libWiiPy
|
||||||
#
|
#
|
||||||
# See https://wiibrew.org/wiki/Title_metadata for details about the TMD format
|
# See https://wiibrew.org/wiki/Title_metadata for details about the TMD format
|
||||||
@ -7,7 +7,7 @@ import io
|
|||||||
import binascii
|
import binascii
|
||||||
import struct
|
import struct
|
||||||
from typing import List
|
from typing import List
|
||||||
from .types import ContentRecord
|
from src.libWiiPy.types import ContentRecord
|
||||||
|
|
||||||
|
|
||||||
class TMD:
|
class TMD:
|
@ -1,11 +1,11 @@
|
|||||||
# "wad.py" from libWiiPy by NinjaCheetah & Contributors
|
# "title/wad.py" from libWiiPy by NinjaCheetah & Contributors
|
||||||
# https://github.com/NinjaCheetah/libWiiPy
|
# https://github.com/NinjaCheetah/libWiiPy
|
||||||
#
|
#
|
||||||
# See https://wiibrew.org/wiki/WAD_files for details about the WAD format
|
# See https://wiibrew.org/wiki/WAD_files for details about the WAD format
|
||||||
|
|
||||||
import io
|
import io
|
||||||
import binascii
|
import binascii
|
||||||
from .shared import align_value, pad_bytes
|
from src.libWiiPy.shared import align_value, pad_bytes
|
||||||
|
|
||||||
|
|
||||||
class WAD:
|
class WAD:
|
@ -49,27 +49,3 @@ class TitleLimit:
|
|||||||
limit_type: int
|
limit_type: int
|
||||||
# The maximum value of the limit applied.
|
# The maximum value of the limit applied.
|
||||||
maximum_usage: int
|
maximum_usage: int
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class U8Node:
|
|
||||||
"""
|
|
||||||
A U8Node object that contains the data of a single node in a U8 file header. Each node keeps track of whether this
|
|
||||||
node is for a file or directory, the offset of the name of the file/directory, the offset of the data for the file/
|
|
||||||
directory, and the size of the data.
|
|
||||||
|
|
||||||
Attributes
|
|
||||||
----------
|
|
||||||
type : int
|
|
||||||
Whether this node refers to a file or a directory. Either 0x0000 for files, or 0x0100 for directories.
|
|
||||||
name_offset : int
|
|
||||||
The offset of the name of the file/directory this node refers to.
|
|
||||||
data_offset : int
|
|
||||||
The offset of the data for the file/directory this node refers to.
|
|
||||||
size : int
|
|
||||||
The size of the data for this node.
|
|
||||||
"""
|
|
||||||
type: int
|
|
||||||
name_offset: int
|
|
||||||
data_offset: int
|
|
||||||
size: int
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user