Toolbox for analyzing and editing pkg application files for psp,ps3, ps4 and ps5, includes the most useful functions you might need.
| 1 | import io |
| 2 | import struct |
| 3 | import zipfile |
| 4 | import enum |
| 5 | from typing import Optional |
| 6 | |
| 7 | |
| 8 | class EndianType(enum.Enum): |
| 9 | BigEndian = "big" |
| 10 | LittleEndian = "little" |
| 11 | |
| 12 | |
| 13 | class Utils: |
| 14 | @staticmethod |
| 15 | def hex2binary(hex_str: str) -> bytes: |
| 16 | return bytes.fromhex(hex_str) |
| 17 | |
| 18 | @staticmethod |
| 19 | def hex_to_binary(hex_string: str) -> bytes: |
| 20 | return bytes.fromhex(hex_string) |
| 21 | |
| 22 | @staticmethod |
| 23 | def hex_to_dec(hex_bytes: bytes, reverse: str = "") -> int: |
| 24 | if reverse == "reverse": |
| 25 | hex_bytes = hex_bytes[::-1] |
| 26 | return int.from_bytes(hex_bytes, byteorder="big") |
| 27 | |
| 28 | @staticmethod |
| 29 | def read_write_data( |
| 30 | file_to_use: str, |
| 31 | file_to_use2: str = "", |
| 32 | method_read_or_write_or_both: str = "", |
| 33 | method_binary_or_integer: str = "", |
| 34 | bin_data: Optional[bytes] = None, |
| 35 | bin_data2: int = 0, |
| 36 | offset: int = 0, |
| 37 | count: int = 0, |
| 38 | ): |
| 39 | if method_read_or_write_or_both == "r": |
| 40 | with open(file_to_use, "rb") as f: |
| 41 | return f.read() |
| 42 | elif method_read_or_write_or_both == "w": |
| 43 | with open(file_to_use, "ab") as f: |
| 44 | if method_binary_or_integer == "bi": |
| 45 | f.write(bin_data or b"") |
| 46 | elif method_binary_or_integer == "in": |
| 47 | f.write(struct.pack("i", bin_data2)) |
| 48 | elif method_read_or_write_or_both == "b": |
| 49 | with open(file_to_use, "rb") as fr, open(file_to_use2, "ab") as fw: |
| 50 | fr.seek(offset) |
| 51 | buffer_size = 4096 |
| 52 | while count > 0: |
| 53 | buffer = fr.read(min(buffer_size, count)) |
| 54 | if not buffer: |
| 55 | break |
| 56 | fw.write(buffer) |
| 57 | count -= len(buffer) |
| 58 | |
| 59 | @staticmethod |
| 60 | def compare_bytes(a: bytes, b: bytes) -> bool: |
| 61 | return a == b |
| 62 | |
| 63 | @staticmethod |
| 64 | def extract_file_to_directory(zip_file_name: str, output_directory: str, member: str = None): |
| 65 | with zipfile.ZipFile(zip_file_name, "r") as zip_ref: |
| 66 | if member: |
| 67 | zip_ref.extract(member, output_directory) |
| 68 | else: |
| 69 | zip_ref.extractall(output_directory) |
| 70 | |
| 71 | @staticmethod |
| 72 | def byte_to_string(buff: bytes) -> str: |
| 73 | return buff.hex().upper() |
| 74 | |
| 75 | @staticmethod |
| 76 | def generate_stream_from_string(s: str) -> io.BytesIO: |
| 77 | return io.BytesIO(s.encode()) |
| 78 | |
| 79 | @staticmethod |
| 80 | def read_uint32(stream: io.BytesIO) -> int: |
| 81 | return struct.unpack("<I", stream.read(4))[0] |
| 82 | |
| 83 | @staticmethod |
| 84 | def read_uint16(stream: io.BytesIO) -> int: |
| 85 | return struct.unpack("<H", stream.read(2))[0] |
| 86 | |
| 87 | @staticmethod |
| 88 | def read_ascii_string(stream: io.BytesIO, length: int) -> str: |
| 89 | return stream.read(length).decode("ascii") |
| 90 | |
| 91 | @staticmethod |
| 92 | def read_utf8_string(stream: io.BytesIO, length: int) -> str: |
| 93 | return stream.read(length).decode("utf-8") |
| 94 | |
| 95 | @staticmethod |
| 96 | def read_byte(stream: io.BytesIO, length: int) -> bytes: |
| 97 | return stream.read(length) |
| 98 |