|
| 1 | +#!/usr/bin/env python3 |
| 2 | + |
| 3 | +import sys |
| 4 | +import re |
| 5 | +import os |
| 6 | +from pathlib import Path |
| 7 | +import crunch64 |
| 8 | + |
| 9 | +# Asset unpacker v0.1 (WIP) |
| 10 | + |
| 11 | +# Read a big endian 32-bit value from a bytearray file with a given offset. |
| 12 | +def read_32_be_value(file_arr, i): |
| 13 | + return (file_arr[i + 0] << 24) + (file_arr[i + 1] << 16) \ |
| 14 | + + (file_arr[i + 2] << 8) + (file_arr[i + 3]) |
| 15 | + |
| 16 | +# -------------------------- |
| 17 | +# Main program |
| 18 | +# -------------------------- |
| 19 | + |
| 20 | +assets_path = "assets/us/" |
| 21 | + |
| 22 | +filepath = Path(sys.argv[1]) |
| 23 | +filename = os.path.splitext(os.path.basename(filepath))[0] |
| 24 | + |
| 25 | +file = open(filepath, 'rb') |
| 26 | +file_header = bytearray(file.read(0x10)) |
| 27 | + |
| 28 | +#print("[DEBUG] File path:", filepath) |
| 29 | +#print("[DEBUG] File name:", filename) |
| 30 | + |
| 31 | +# Magic check for multi asset bin. If no match, treat as a single asset bin, and just copy it to the expected folder. |
| 32 | +if file_header[0] != 0x00 or file_header[1] != 0x00 or file_header[2] != 0x00 or file_header[3] != 0x00 or file_header[4] != 0x00 or file_header[5] != 0x00 or file_header[6] != 0x00 or file_header[7] != 0x00: |
| 33 | + file_path_to_write = assets_path + filename + "/0/0.bin" |
| 34 | + os.makedirs(os.path.dirname(file_path_to_write), exist_ok=True) |
| 35 | + with open(file_path_to_write, 'wb') as f: |
| 36 | + fin = open(filepath, 'rb') |
| 37 | + f.write(fin.read()) |
| 38 | + sys.exit(0) |
| 39 | + |
| 40 | +# Otherwise, process as multi. |
| 41 | +bin_size = read_32_be_value(file_header, 8) |
| 42 | +file_count = read_32_be_value(file_header, 12) |
| 43 | + |
| 44 | +#print("[DEBUG] Size:", hex(bin_size)) |
| 45 | +#print("[DEBUG] File count:", file_count) |
| 46 | + |
| 47 | +# Reallocate the file based on the bin size. First seek back to the start, then reallocate. |
| 48 | +file.seek(0, os.SEEK_SET) |
| 49 | +file_bytes = bytearray(file.read(bin_size)) |
| 50 | + |
| 51 | +file_num = 0 |
| 52 | +while file_num < file_count: |
| 53 | + #print("[DEBUG] Processing File #:", file_num) |
| 54 | + # Get bin offset and bin size for the # file being processed. |
| 55 | + bin_offset = read_32_be_value(file_bytes, 0x10 + (file_num * 0x10) + 0) |
| 56 | + bin_size = read_32_be_value(file_bytes, 0x10 + (file_num * 0x10) + 4) |
| 57 | + #print("[DEBUG] File Offset:", hex(bin_offset)) |
| 58 | + #print("[DEBUG] File Size:", hex(bin_size)) |
| 59 | + # Seek to the file offset. |
| 60 | + file.seek(bin_offset, os.SEEK_SET) |
| 61 | + sub_file_bytes = bytearray(file.read(bin_size)) |
| 62 | + file_path_to_write = assets_path + filename + "/" + str(file_num) + "/" + str(file_num) + ".bin" |
| 63 | + #print("[DEBUG] Path to write:", file_path_to_write) |
| 64 | + os.makedirs(os.path.dirname(file_path_to_write), exist_ok=True) |
| 65 | + file_to_write = open(file_path_to_write, 'wb') |
| 66 | + file_to_write.write(sub_file_bytes) |
| 67 | + file_num = file_num + 1 |
0 commit comments