#!/usr/bin/env python3 """OpenCE's home screen art: sce_sys/icon0.png (512x512) and sce_sys/pic1.png (1920x1080). Made from art/ (not in the repository: it is your game's): art/halo_logo.png, the HALO logo of your own ui.map (ui\\shell\\main_menu\\halo_logo, 1024x256 DXT5: scripts/make-art.py --logo extracts it), and art/background.png, a 1920x1080 picture of the game (a frame of your own PS4 clip). Without them it falls back to OpenCE's own icon (port/assets/icon/opence-icon-render.png in the checkout). Usage: python3 scripts/make-art.py [out dir, default sce_sys] python3 scripts/make-art.py --logo """ import os import struct import sys import zlib from PIL import Image, ImageDraw, ImageEnhance, ImageFilter FONT_LIGHT = "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf" CHECKOUT_ICON = os.path.expanduser("~/opence-build/src/OpenCE/port/assets/icon/opence-icon-render.png") def extract_logo(ui_map, art): """the HALO logo out of an Xbox ui.map (cache version 5, zlib after the 2 KB header)""" raw = open(ui_map, "rb").read() data = raw[:0x800] + zlib.decompress(raw[0x800:]) tag_offset = struct.unpack_from(" 12 else 0).getbbox() if box: background = background.crop((0, box[1], background.width, box[3])) # pic1: the picture (its left part: the subject off to the right), darker at the top left for the logo pic = cover(background, (1920, 1080), 0.0) pic = ImageEnhance.Brightness(pic).enhance(0.9) shade = Image.new("L", (1920, 1080), 0) ImageDraw.Draw(shade).ellipse([-500, -420, 1300, 560], fill=190) shade = shade.filter(ImageFilter.GaussianBlur(120)) pic.paste((4, 8, 20), (0, 0), shade) big = logo.resize((820, round(logo.height * 820 / logo.width)), Image.LANCZOS) glow = Image.new("RGBA", pic.size, (0, 0, 0, 0)) glow.paste((90, 150, 255, 255), (70, 90), big.getchannel("A")) glow = glow.filter(ImageFilter.GaussianBlur(18)) pic = pic.convert("RGBA") pic.alpha_composite(Image.eval(glow, lambda v: v // 2)) pic.alpha_composite(big, (70, 90)) pic.convert("RGB").save(os.path.join(out, "pic1.png")) # icon0: the picture's middle, the logo across its foot icon = cover(background, (512, 512)) if background.width / background.height < 1.4 else \ cover(background.crop((background.width // 2 - background.height // 2, 0, background.width // 2 + background.height // 2, background.height)), (512, 512)) icon = ImageEnhance.Brightness(icon).enhance(0.95).convert("RGBA") icon.paste((2, 6, 16, 255), (0, 0), fade((512, 512), 250, 470, 235)) small = logo.resize((470, round(logo.height * 470 / logo.width)), Image.LANCZOS) icon.alpha_composite(small, (21, 512 - small.height - 34)) icon.convert("RGB").save(os.path.join(out, "icon0.png")) print(f"art: {out}/icon0.png, {out}/pic1.png (the game's)") def fallback_art(out): """OpenCE's icon, when art/ has nothing""" icon = Image.open(CHECKOUT_ICON).convert("RGBA").resize((512, 512), Image.LANCZOS) flat = Image.new("RGBA", (512, 512), (6, 14, 34, 255)) flat.alpha_composite(icon) flat.convert("RGB").save(os.path.join(out, "icon0.png")) pic = Image.new("RGB", (1920, 1080), (6, 14, 34)) pic.paste(flat.resize((900, 900)).convert("RGB"), (510, 90)) pic.save(os.path.join(out, "pic1.png")) print(f"art: {out}/icon0.png, {out}/pic1.png (OpenCE's icon)") def main(): if sys.argv[1] == "--logo": extract_logo(sys.argv[2], sys.argv[3]) return art = sys.argv[1] out = sys.argv[2] if len(sys.argv) > 2 else "sce_sys" os.makedirs(out, exist_ok=True) if os.path.isfile(os.path.join(art, "halo_logo.png")) and os.path.isfile(os.path.join(art, "background.png")): halo_art(art, out) else: fallback_art(out) if __name__ == "__main__": main()