Toolbox for analyzing and editing pkg application files for psp,ps3, ps4 and ps5, includes the most useful functions you might need.
| 1 | import struct |
| 2 | import io |
| 3 | import zipfile |
| 4 | from typing import List, Optional |
| 5 | |
| 6 | class Utils: |
| 7 | @staticmethod |
| 8 | def hex_to_binary(hex_string: str) -> bytes: |
| 9 | return bytes.fromhex(hex_string) |
| 10 | |
| 11 | @staticmethod |
| 12 | def hex_to_dec(hex_bytes: bytes, reverse: str = "") -> int: |
| 13 | if reverse == "reverse": |
| 14 | hex_bytes = hex_bytes[::-1] |
| 15 | return int.from_bytes(hex_bytes, byteorder='little') |
| 16 | |
| 17 | @staticmethod |
| 18 | def read_write_data(file_to_use: str, file_to_use2: str = "", method_read_or_write_or_both: str = "", |
| 19 | method_binary_or_integer: str = "", bin_data: Optional[bytes] = None, |
| 20 | bin_data2: int = 0, offset: int = 0, count: int = 0): |
| 21 | if method_read_or_write_or_both == "r": |
| 22 | with open(file_to_use, "rb") as f: |
| 23 | return f.read() |
| 24 | elif method_read_or_write_or_both == "w": |
| 25 | with open(file_to_use, "ab") as f: |
| 26 | if method_binary_or_integer == "bi": |
| 27 | f.write(bin_data) |
| 28 | elif method_binary_or_integer == "in": |
| 29 | f.write(bin_data2.to_bytes(4, byteorder='little')) |
| 30 | elif method_read_or_write_or_both == "b": |
| 31 | with open(file_to_use, "rb") as fr, open(file_to_use2, "ab") as fw: |
| 32 | working_buffer_size = min(4096, count) if count > 0 else 4096 |
| 33 | fr.seek(offset) |
| 34 | while True: |
| 35 | buffer = fr.read(working_buffer_size) |
| 36 | if not buffer: |
| 37 | break |
| 38 | fw.write(buffer) |
| 39 | if count > 0: |
| 40 | count -= len(buffer) |
| 41 | if count <= 0: |
| 42 | break |
| 43 | working_buffer_size = min(working_buffer_size, count) |
| 44 | |
| 45 | @staticmethod |
| 46 | def compare_bytes(a: bytes, b: bytes) -> bool: |
| 47 | return a == b |
| 48 | |
| 49 | @staticmethod |
| 50 | def extract_file_to_directory(zip_file_name: str, output_directory: str): |
| 51 | with zipfile.ZipFile(zip_file_name, 'r') as zip_ref: |
| 52 | zip_ref.extract("TheFileToExtract", output_directory) |
| 53 | |
| 54 | @staticmethod |
| 55 | def byte_to_string(buff: bytes) -> str: |
| 56 | return buff.hex().upper() |
| 57 | |
| 58 | @staticmethod |
| 59 | def generate_stream_from_string(s: str) -> io.BytesIO: |
| 60 | return io.BytesIO(s.encode()) |
| 61 | |
| 62 | @staticmethod |
| 63 | def read_uint32(stream: io.BytesIO) -> int: |
| 64 | return struct.unpack('<I', stream.read(4))[0] |
| 65 | |
| 66 | @staticmethod |
| 67 | def read_uint16(stream: io.BytesIO) -> int: |
| 68 | return struct.unpack('<H', stream.read(2))[0] |
| 69 | |
| 70 | @staticmethod |
| 71 | def read_ascii_string(stream: io.BytesIO, length: int) -> str: |
| 72 | return stream.read(length).decode('ascii') |
| 73 | |
| 74 | @staticmethod |
| 75 | def read_utf8_string(stream: io.BytesIO, length: int) -> str: |
| 76 | return stream.read(length).decode('utf-8') |
| 77 | |
| 78 | @staticmethod |
| 79 | def read_byte(stream: io.BytesIO, length: int) -> bytes: |
| 80 | return stream.read(length) |
| 81 | |
| 82 | @staticmethod |
| 83 | def bytes_to_bitmap(img_bytes: bytes): |
| 84 | # This would require a Python imaging library like Pillow |
| 85 | from PIL import Image |
| 86 | import io |
| 87 | return Image.open(io.BytesIO(img_bytes)) |
| 88 | |
| 89 | @staticmethod |
| 90 | def is_linux() -> bool: |
| 91 | import platform |
| 92 | return platform.system() == "Linux" |
| 93 | |
| 94 | @staticmethod |
| 95 | def contain(a: bytes, b: bytes) -> bool: |
| 96 | return a == b |
| 97 | |
| 98 | @staticmethod |
| 99 | def hex_to_string(hex_string: str) -> str: |
| 100 | return bytes.fromhex(hex_string).decode('ascii') |
| 101 | |
| 102 | @staticmethod |
| 103 | def hex(byte: int) -> str: |
| 104 | return f"{byte:02X}" |
| 105 | |
| 106 | @staticmethod |
| 107 | def byte_array_to_little_endian_integer(bits: bytes) -> int: |
| 108 | return int.from_bytes(bits, byteorder='little') |
| 109 | |
| 110 | @staticmethod |
| 111 | def byte_arrays_equal(first: bytes, second: bytes) -> bool: |
| 112 | return first == second |
| 113 | |
| 114 | @staticmethod |
| 115 | def byte_array_to_utf8_string(byte_array: bytes) -> str: |
| 116 | return byte_array.decode('utf-8') |
| 117 | |
| 118 | @staticmethod |
| 119 | def byte_array_to_hex_string(bytes_input: bytes) -> str: |
| 120 | return bytes_input.hex().upper() |
| 121 | |
| 122 | @staticmethod |
| 123 | def hex_string_to_long(str_hex: str) -> int: |
| 124 | return int(str_hex, 16) |
| 125 | |
| 126 | @staticmethod |
| 127 | def create_jagged_array(lengths: List[int]): |
| 128 | def create_inner(index: int): |
| 129 | if index == len(lengths) - 1: |
| 130 | return [None] * lengths[index] |
| 131 | return [create_inner(index + 1) for _ in range(lengths[index])] |
| 132 | return create_inner(0) |
| 133 | |
| 134 | @staticmethod |
| 135 | def clamp(value: int, min_value: int, max_value: int) -> int: |
| 136 | return max(min(value, max_value), min_value) |
| 137 | |
| 138 | @staticmethod |
| 139 | def clamp16(value: int) -> int: |
| 140 | return Utils.clamp(value, -32768, 32767) |
| 141 | |
| 142 | @staticmethod |
| 143 | def clamp4(value: int) -> int: |
| 144 | return Utils.clamp(value, -8, 7) |
| 145 | |
| 146 | |
| 147 |