Compare commits

...

2 Commits

4 changed files with 67 additions and 7 deletions

View File

@ -19,7 +19,9 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Install ccache for Nuitka - name: Install ccache for Nuitka
run: sudo apt update && sudo apt install -y ccache libicu70 run: |
sudo apt update && \
sudo apt install -y ccache patchelf
- name: Set up Python 3.12 - name: Set up Python 3.12
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
@ -36,7 +38,7 @@ jobs:
cd ~ cd ~
tar cvf WiiPy.tar wiipy tar cvf WiiPy.tar wiipy
- name: Upload Application - name: Upload Application
uses: actions/upload-artifact@v4.3.0 uses: actions/upload-artifact@v4
with: with:
path: ~/WiiPy.tar path: ~/WiiPy.tar
name: WiiPy-Linux-bin name: WiiPy-Linux-bin
@ -63,7 +65,7 @@ jobs:
cd ~ cd ~
tar cvf WiiPy.tar wiipy tar cvf WiiPy.tar wiipy
- name: Upload Application - name: Upload Application
uses: actions/upload-artifact@v4.3.0 uses: actions/upload-artifact@v4
with: with:
path: ~/WiiPy.tar path: ~/WiiPy.tar
name: WiiPy-macOS-x86_64-bin name: WiiPy-macOS-x86_64-bin
@ -90,7 +92,7 @@ jobs:
cd ~ cd ~
tar cvf WiiPy.tar wiipy tar cvf WiiPy.tar wiipy
- name: Upload Application - name: Upload Application
uses: actions/upload-artifact@v4.3.0 uses: actions/upload-artifact@v4
with: with:
path: ~/WiiPy.tar path: ~/WiiPy.tar
name: WiiPy-macOS-arm64-bin name: WiiPy-macOS-arm64-bin
@ -114,7 +116,7 @@ jobs:
- name: Build Application - name: Build Application
run: .\Build.ps1 run: .\Build.ps1
- name: Upload Application - name: Upload Application
uses: actions/upload-artifact@v4.3.0 uses: actions/upload-artifact@v4
with: with:
path: D:\a\WiiPy\WiiPy\wiipy.exe path: D:\a\WiiPy\WiiPy\wiipy.exe
name: WiiPy-Windows-bin name: WiiPy-Windows-bin

28
commands/archive/lz77.py Normal file
View File

@ -0,0 +1,28 @@
# "commands/archive/lz77.py" from WiiPy by NinjaCheetah
# https://github.com/NinjaCheetah/WiiPy
import pathlib
import libWiiPy
from modules.core import fatal_error
def handle_lz77_compress(args):
print("Compression is not implemented yet.")
def handle_lz77_decompress(args):
input_path = pathlib.Path(args.input)
if args.output is not None:
output_path = pathlib.Path(args.output)
else:
output_path = pathlib.Path(input_path.name + ".out")
if not input_path.exists():
fatal_error(f"The specified file \"{input_path}\" does not exist!")
lz77_data = input_path.read_bytes()
data = libWiiPy.archive.decompress_lz77(lz77_data)
output_path.write_bytes(data)
print("LZ77 file decompressed!")

View File

@ -26,8 +26,15 @@ def handle_u8_unpack(args):
if not input_path.exists(): if not input_path.exists():
fatal_error(f"The specified input file \"{input_path}\" does not exist!") fatal_error(f"The specified input file \"{input_path}\" does not exist!")
u8_data = input_path.read_bytes()
# U8 archives are sometimes compressed. In the event that the provided data is LZ77 data, assume it's a compressed
# U8 archive and decompress it before continuing. Standard checks will then catch it if it was something else.
if u8_data[0:4] == b'LZ77':
u8_data = libWiiPy.archive.decompress_lz77(u8_data)
# Output path is deliberately not checked in any way because libWiiPy already has those checks, and it's easier # Output path is deliberately not checked in any way because libWiiPy already has those checks, and it's easier
# and cleaner to only have one component doing all the checks. # and cleaner to only have one component doing all the checks.
libWiiPy.archive.extract_u8(input_path.read_bytes(), str(output_path)) libWiiPy.archive.extract_u8(u8_data, str(output_path))
print("U8 archive unpacked!") print("U8 archive unpacked!")

View File

@ -5,6 +5,7 @@ import argparse
from importlib.metadata import version from importlib.metadata import version
from commands.archive.ash import * from commands.archive.ash import *
from commands.archive.lz77 import *
from commands.archive.theme import * from commands.archive.theme import *
from commands.archive.u8 import * from commands.archive.u8 import *
from commands.nand.emunand import * from commands.nand.emunand import *
@ -30,7 +31,7 @@ if __name__ == "__main__":
# Argument parser for the ASH subcommand. # Argument parser for the ASH subcommand.
ash_parser = subparsers.add_parser("ash", help="compress/decompress an ASH file", ash_parser = subparsers.add_parser("ash", help="compress/decompress an ASH file",
description="compress/decompress an ASH file") description="compress/decompress an ASH file")
ash_subparsers = ash_parser.add_subparsers(title="emunand", dest="emunand", required=True) ash_subparsers = ash_parser.add_subparsers(title="ash", dest="ash", required=True)
# ASH compress parser. # ASH compress parser.
ash_compress_parser = ash_subparsers.add_parser("compress", help="compress a file into an ASH file", ash_compress_parser = ash_subparsers.add_parser("compress", help="compress a file into an ASH file",
description="compress a file into an ASH file; by default, this " description="compress a file into an ASH file; by default, this "
@ -146,6 +147,28 @@ if __name__ == "__main__":
iospatch_parser.add_argument("-ns", "--no-shared", action="store_true", iospatch_parser.add_argument("-ns", "--no-shared", action="store_true",
help="set all patched content to be non-shared") help="set all patched content to be non-shared")
# Argument parser for the LZ77 subcommand.
lz77_parser = subparsers.add_parser("lz77", help="compress/decompress data using LZ77 compression",
description="compress/decompress data using LZ77 compression")
lz77_subparsers = lz77_parser.add_subparsers(title="lz77", dest="lz77", required=True)
# LZ77 compress parser.
lz77_compress_parser = lz77_subparsers.add_parser("compress", help="compress a file with LZ77 compression",
description="compress a file with LZ77 compression; by default, "
"this will output to <input file>.lz77")
lz77_compress_parser.set_defaults(func=handle_lz77_compress)
lz77_compress_parser.add_argument("input", metavar="IN", type=str, help="file to compress")
lz77_compress_parser.add_argument("-o", "--output", metavar="OUT", type=str,
help="file to output the compressed data to (optional)")
# LZ77 decompress parser.
lz77_decompress_parser = lz77_subparsers.add_parser("decompress", help="decompress an LZ77-compressed file",
description="decompress an LZ77-compressed file; by default, "
"this will output to <input file>.out")
lz77_decompress_parser.set_defaults(func=handle_lz77_decompress)
lz77_decompress_parser.add_argument("input", metavar="IN", type=str,
help="LZ77-compressed file to decompress")
lz77_decompress_parser.add_argument("-o", "--output", metavar="OUT", type=str,
help="file to output the decompressed data to (optional)")
# Argument parser for the NUS subcommand. # Argument parser for the NUS subcommand.
nus_parser = subparsers.add_parser("nus", help="download data from the NUS", nus_parser = subparsers.add_parser("nus", help="download data from the NUS",
description="download from the NUS") description="download from the NUS")