#!/usr/bin/env python3 """ pop_pack_guard.py — упаковщик спрайтов СТРАЖА (chtab_5_guard, база 750). Оригинал грузит стражей из отдельного .DAT по типу уровня (GUARD/FAT/SKEL/VIZIER/SHADOW, seg000:1092); уровень 1 — обычный «guard», то есть data/GUARD/res(750+id).png. Палитра — НЕ из PNG: оригинал подменяет её из res10.bin (guard_palettes, 7 палитр по 16 цветов, 6-бит) по level.guards_color; на уровне 1 у обоих стражей color = 2. Выход: poc/res/guard/g0..gN.atl (по 8 спрайтов на страницу, адресация id>>3 / id&7 — как у Kid) + группа палитры 0x90..0x9F в общий kid.pal (его собирает pop_pack_kid.py, см. GUARD_PAL_BASE там). """ import os import sys from PIL import Image HERE = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, HERE) import pop_pack_bg as B from pop_pack_kid import transpose_cols GUARD_DIR = os.path.join(HERE, "..", "SDLPoP", "data", "GUARD") PAL_BIN = os.path.join(HERE, "..", "SDLPoP", "data", "PRINCE", "res10.bin") OUT_DIR = os.path.join(HERE, "..", "poc", "res", "guard") PAL_BASE = 0x90 # слоты палитры Sprinter под стража COLOR = 2 # level.guards_color обоих стражей уровня 1 SHIFT = 3 # g[id>>3], idx id&7 (спрайты крупные) MASK = (1 << SHIFT) - 1 MAX_ID = 34 # res751..res784 def load_guard(id): """id -> res(750+id).png -> (w, h, 8bpp COLUMN-MAJOR); 0 -> 0xFF (прозр.).""" path = os.path.join(GUARD_DIR, f"res{750 + id}.png") if not os.path.exists(path): return None im = Image.open(path) if im.mode != "P": B.die(f"res{750+id}: mode {im.mode}, ожидался P") src = im.tobytes() rowmajor = bytes((0xFF if v == 0 else PAL_BASE + v) for v in src) return im.width, im.height, transpose_cols(im.width, im.height, rowmajor) def guard_palette(): """16 цветов (r,g,b 0..63) из res10.bin для COLOR.""" b = open(PAL_BIN, "rb").read() off = 0x30 * COLOR - 0x30 return [(b[off + i * 3], b[off + i * 3 + 1], b[off + i * 3 + 2]) for i in range(16)] def main(): os.makedirs(OUT_DIR, exist_ok=True) pages = {} n = 0 for id in range(1, MAX_ID + 1): g = load_guard(id) if g is None: continue pages.setdefault(id >> SHIFT, {})[id & MASK] = g n += 1 if not pages: B.die("нет спрайтов стража") total = 0 for pg in range(max(pages) + 1): nm = f"g{pg}.atl" cnt, sz = B.pack_atlas(os.path.join(OUT_DIR, nm), pages.get(pg, {})) total += sz print(f" {nm}: {len(pages.get(pg, {}))} спрайтов, каталог {cnt}, {sz} Б") print(f"ИТОГО: {n} спрайтов стража, {max(pages)+1} EMM-страниц, {total} Б -> {OUT_DIR}") if __name__ == "__main__": main()