mirror of
https://github.com/NinjaCheetah/libWiiPy.git
synced 2025-04-27 22:01:01 -04:00
Unfinished wiiload module and LZ77 compression code
This commit is contained in:
parent
f0b79e1f39
commit
e7070b6758
@ -6,6 +6,64 @@
|
|||||||
import io
|
import io
|
||||||
|
|
||||||
|
|
||||||
|
def compress_lz77(data: bytes) -> bytes:
|
||||||
|
"""
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
data
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
|
||||||
|
"""
|
||||||
|
def compare_bytes(byte1: bytes, offset1: int, byte2: bytes, offset2: int, len_max: int, abs_len_max: int) -> int:
|
||||||
|
num_matched = 0
|
||||||
|
if len_max > abs_len_max:
|
||||||
|
len_max = abs_len_max
|
||||||
|
for i in range(0, len_max):
|
||||||
|
if byte1[offset1 + 1] == byte2[offset2 + 1]:
|
||||||
|
num_matched += 1
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
if num_matched == len_max:
|
||||||
|
offset1 -= len_max
|
||||||
|
for i in range(0, abs_len_max - len_max):
|
||||||
|
if byte1[offset1 + 1] == byte2[offset2 + 1]:
|
||||||
|
num_matched += 1
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
return num_matched
|
||||||
|
|
||||||
|
def search_match(buffer: bytes, pos: int) -> (int, int):
|
||||||
|
bytes_left = len(buffer) - pos
|
||||||
|
# Default to only looking back 4096 bytes, unless we've moved fewer than 4096 bytes, in which case we should
|
||||||
|
# only look as far back as we've gone.
|
||||||
|
max_dist = 0x1000
|
||||||
|
if max_dist > pos:
|
||||||
|
max_dist = pos
|
||||||
|
# We want the longest match we can find.
|
||||||
|
biggest_match = 0
|
||||||
|
biggest_match_pos = 0
|
||||||
|
# Default to only matching up to 18 bytes, unless fewer than 18 bytes remain, in which case we can only match
|
||||||
|
# up to that many bytes.
|
||||||
|
max_len = 0x12
|
||||||
|
if max_len > bytes_left:
|
||||||
|
max_len = bytes_left
|
||||||
|
for i in range(1, max_dist):
|
||||||
|
num_compare = max_len
|
||||||
|
if num_compare > i:
|
||||||
|
num_compare = i
|
||||||
|
if num_compare > max_len:
|
||||||
|
num_compare = max_len
|
||||||
|
num_matched = compare_bytes(buffer, pos - i, buffer, pos, max_len, 0x12)
|
||||||
|
|
||||||
|
output_data = b'LZ77\x10'
|
||||||
|
# Write the header by finding the size of the uncompressed data.
|
||||||
|
output_data += int.to_bytes(len(data), 3, 'little')
|
||||||
|
search_match(data, 0)
|
||||||
|
|
||||||
|
|
||||||
def decompress_lz77(lz77_data: bytes) -> bytes:
|
def decompress_lz77(lz77_data: bytes) -> bytes:
|
||||||
"""
|
"""
|
||||||
Decompresses LZ77-compressed data and returns the decompressed result. Supports data both with and without the
|
Decompresses LZ77-compressed data and returns the decompressed result. Supports data both with and without the
|
||||||
|
62
src/libWiiPy/title/wiiload.py
Normal file
62
src/libWiiPy/title/wiiload.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
# "title/wiiload.py" from libWiiPy by NinjaCheetah & Contributors
|
||||||
|
# https://github.com/NinjaCheetah/libWiiPy
|
||||||
|
#
|
||||||
|
# This code is adapted from "wiiload.py", which can be found on the WiiBrew page for Wiiload.
|
||||||
|
# https://pastebin.com/4nWAkBpw
|
||||||
|
#
|
||||||
|
# See https://wiibrew.org/wiki/Wiiload for details about how Wiiload works
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import zlib
|
||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
|
||||||
|
|
||||||
|
def send_bin_wiiload(target_ip: str, bin_data: bytes, name: str) -> None:
|
||||||
|
"""
|
||||||
|
Sends an ELF or DOL binary to The Homebrew Channel via Wiiload. This requires the IP address of the console you
|
||||||
|
want to send the binary to.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
target_ip: str
|
||||||
|
The IP address of the console to send the binary to.
|
||||||
|
bin_data: bytes
|
||||||
|
The data of the ELF or DOL to send.
|
||||||
|
name: str
|
||||||
|
The name of the application being sent.
|
||||||
|
"""
|
||||||
|
wii_ip = (target_ip, 4299)
|
||||||
|
|
||||||
|
WIILOAD_VERSION_MAJOR=0
|
||||||
|
WIILOAD_VERSION_MINOR=5
|
||||||
|
|
||||||
|
len_uncompressed = len(bin_data)
|
||||||
|
c_data = zlib.compress(bin_data, 6)
|
||||||
|
|
||||||
|
chunk_size = 1024*128
|
||||||
|
chunks = [c_data[i:i+chunk_size] for i in range(0, len(c_data), chunk_size)]
|
||||||
|
|
||||||
|
args = [name]
|
||||||
|
args = "\x00".join(args) + "\x00"
|
||||||
|
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
s.connect(wii_ip)
|
||||||
|
|
||||||
|
s.send("HAXX")
|
||||||
|
s.send(struct.pack("B", WIILOAD_VERSION_MAJOR)) # one byte, unsigned
|
||||||
|
s.send(struct.pack("B", WIILOAD_VERSION_MINOR)) # one byte, unsigned
|
||||||
|
s.send(struct.pack(">H",len(args))) # bigendian, 2 bytes, unsigned
|
||||||
|
s.send(struct.pack(">L",len(c_data))) # bigendian, 4 bytes, unsigned
|
||||||
|
s.send(struct.pack(">L",len_uncompressed)) # bigendian, 4 bytes, unsigned
|
||||||
|
|
||||||
|
print(len(chunks),"chunks to send")
|
||||||
|
for piece in chunks:
|
||||||
|
s.send(piece)
|
||||||
|
sys.stdout.write("."); sys.stdout.flush()
|
||||||
|
sys.stdout.write("\n")
|
||||||
|
|
||||||
|
s.send(args)
|
||||||
|
|
||||||
|
s.close()
|
||||||
|
print("done")
|
Loading…
x
Reference in New Issue
Block a user