mirror of
https://github.com/EmiiBytee/np2kai-ps4.git
synced 2026-10-06 10:00:13 +02:00
73 lines
2.5 KiB
Python
Executable File
73 lines
2.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import re
|
|
import struct
|
|
from pathlib import Path
|
|
|
|
SELF_MAGIC = bytes.fromhex("4f153d1d")
|
|
PNG_MAGIC = b"\x89PNG\r\n\x1a\n"
|
|
|
|
|
|
def fail(message: str) -> None:
|
|
raise SystemExit(f"ERROR: {message}")
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(
|
|
description="Validate PS4 package metadata before create-gp4/PkgTool."
|
|
)
|
|
parser.add_argument("--version", required=True)
|
|
parser.add_argument("--title-id", required=True)
|
|
parser.add_argument("--content-id", required=True)
|
|
parser.add_argument("--right-sprx", required=True, type=Path)
|
|
parser.add_argument("--icon", required=True, type=Path)
|
|
args = parser.parse_args()
|
|
|
|
if re.fullmatch(r"[0-9]{2}\.[0-9]{2}", args.version) is None:
|
|
fail(
|
|
f"APP_VER/VERSION '{args.version}' is invalid; PS4 expects XX.YY "
|
|
"(for example 01.35)."
|
|
)
|
|
if re.fullmatch(r"[A-Z]{4}[0-9]{5}", args.title_id) is None:
|
|
fail(f"TITLE_ID '{args.title_id}' is not WXYZ12345 format.")
|
|
expected_content = (
|
|
rf"[A-Z]{{2}}[0-9]{{4}}-{re.escape(args.title_id)}_"
|
|
rf"[0-9]{{2}}-[A-Z0-9]{{16}}"
|
|
)
|
|
if re.fullmatch(expected_content, args.content_id) is None:
|
|
fail(f"CONTENT_ID '{args.content_id}' is malformed or mismatches TITLE_ID.")
|
|
|
|
if not args.right_sprx.is_file():
|
|
fail(f"missing game-right module: {args.right_sprx}")
|
|
right = args.right_sprx.read_bytes()
|
|
if len(right) < 4096:
|
|
fail(f"game-right module is unexpectedly small: {len(right)} bytes")
|
|
if right[:4] != SELF_MAGIC:
|
|
fail(
|
|
f"{args.right_sprx} does not have the Orbis SELF magic "
|
|
f"{SELF_MAGIC.hex()}."
|
|
)
|
|
|
|
if not args.icon.is_file():
|
|
fail(f"missing icon: {args.icon}")
|
|
with args.icon.open("rb") as handle:
|
|
header = handle.read(24)
|
|
if len(header) != 24 or header[:8] != PNG_MAGIC or header[12:16] != b"IHDR":
|
|
fail(f"{args.icon} is not a valid PNG with an IHDR header")
|
|
width, height = struct.unpack(">II", header[16:24])
|
|
if (width, height) != (512, 512):
|
|
fail(f"icon0.png must be 512x512, got {width}x{height}")
|
|
|
|
print("NP2kai PS4 package metadata validation: PASS")
|
|
print(f"- SFO APP_VER/VERSION: {args.version} (XX.YY)")
|
|
print(f"- TITLE_ID: {args.title_id}")
|
|
print(f"- CONTENT_ID: {args.content_id}")
|
|
print(f"- right.sprx: Orbis SELF, {len(right)} bytes")
|
|
print(f"- icon0.png: {width}x{height} PNG")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|