PoP roomtest: страж — спрайты, таблица кадров и появление в комнате

Шаги 1-2 из плана стражей:

1. Спрайты (chtab_5_guard, база 750).  Новый упаковщик pop_pack_guard.py:
   data/GUARD/res751..784 -> GUARD\g0..g4.atl (5 EMM-страниц, адресация
   id>>3 / id&7, как у Kid).  Палитра берётся НЕ из PNG, а из res10.bin
   (guard_palettes: 7 палитр по 16 цветов, 6-бит) по level.guards_color —
   на уровне 1 у обоих стражей color = 2; группа слотов 0x90..0x9F
   добавлена в общий kid.pal.

2. Таблица кадров стража у оригинала СВОЯ (frame_tbl_guard, seg006:372,
   41 запись) и индексируется как frame + add_frame - 149, где add_frame
   = 70 для кадров 102..106.  Она дописана в kid_data.bin (3515 -> 3720 Б,
   смещение в KID_BIN_GFRAMES_OFF); pop_kid получил pop_kid_data_frame()
   — чтение кадра из ЛЮБОЙ таблицы страницы данных.

3. Появление: pop_level_guard() читает guards_tile/dir/color/skill из
   уровня, pop_guard_enter() ставит стража по enter_guard (seg002:0112) +
   pos_guards (seg003): row из тайла, y = y_land[row+1], x из колонки,
   charid = guard, sword сложен, alive = -1, HP = 3.  Отрисовка
   pop_guard_draw() — та же математика, что kid_draw (load_frame_to_obj +
   calc_screen_x_coord), но атлас стража и своя таблица кадров; heal по
   странице дабл-буфера, как у Kid.

Интерпретатора последовательностей у стража ПОКА НЕТ: кадр ставится
напрямую (166 = frame_166_stand_inactive, что и даёт seq_77 при входе в
комнату).  play_seq для произвольного персонажа + ИИ — следующая фаза.

Проверено в MAME: в комнате 3 страж появляется на своём месте (ряд 1,
кол 7) и рисуется; цвета совпадают с эталонным рендером спрайта в
палитре color=2.

ВНИМАНИЕ по памяти: куча W2 просела до 805 Б (было 2349).  Перед ИИ
стражей нужен шаг 5 плана (данные: room_modif 720 Б, dl1/dl2 512 Б,
_kbdraw_down 512 Б) либо вынос кода отрисовки стража в резидент W3.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-29 21:57:38 +03:00
parent 1dc89b0f26
commit 3dbad6120c
19 changed files with 314 additions and 7 deletions
@@ -26,10 +26,11 @@ def read(name):
return open(os.path.join(SRC, name)).read()
def parse_frame_table(txt):
"""frame_table_kid[] -> список (image, dx, dy, flags). Записи вида
{ IMG, 0xC0| 4, DX, DY, 0x40| 4 } — sword/flags как OR-выражения."""
m = re.search(r'const frame_type frame_table_kid\[\]\s*=\s*\{(.*?)\n\};', txt, re.S)
def parse_frame_table(txt, name="frame_table_kid"):
"""frame_table_kid[]/frame_tbl_guard[] -> список (image, dx, dy, flags).
Записи вида { IMG, 0xC0| 4, DX, DY, 0x40| 4 } — sword/flags как
OR-выражения."""
m = re.search(r'const frame_type ' + name + r'\[\]\s*=\s*\{(.*?)\n\};', txt, re.S)
body = m.group(1)
frames = []
for row in re.findall(r'\{([^}]*)\}', body):
@@ -65,6 +66,7 @@ def main():
seqc = read("seqtbl.c")
frames = parse_frame_table(seg006)
gframes = parse_frame_table(seg006, "frame_tbl_guard")
seqtbl = parse_byte_array(seqc, "original_seqtbl")
offs = parse_word_array(seqc, "original_seqtbl_offsets")
@@ -90,7 +92,11 @@ def main():
# раскладка kid_data.bin (смещения ОТ НАЧАЛА ДАННЫХ страницы)
f.write("/* Раскладка kid_data.bin: кадры (KID_NFRAMES*5), затем seqtbl. */\n")
f.write("#define KID_BIN_FRAMES_OFF 0\n")
f.write("#define KID_BIN_SEQTBL_OFF %d\n\n" % (len(frames) * 5))
f.write("#define KID_BIN_SEQTBL_OFF %d\n" % (len(frames) * 5))
f.write("/* Таблица кадров СТРАЖА (frame_tbl_guard, seg006:372): индекс\n"
" * frame + add_frame - 149 (add_frame=70 для кадров 102..106). */\n")
f.write("#define KID_NGFRAMES %d\n" % len(gframes))
f.write("#define KID_BIN_GFRAMES_OFF %d\n\n" % (len(frames) * 5 + len(seqtbl)))
# seq offsets
f.write("#define KID_NSEQ %d\n" % len(offs))
@@ -105,7 +111,9 @@ def main():
for (img, dx, dy, fl, sw) in frames:
b.write(bytes((img & 0xFF, dx & 0xFF, dy & 0xFF, fl & 0xFF, sw & 0xFF)))
b.write(bytes(seqtbl))
print(f"kid_data.bin: {len(frames)*5 + len(seqtbl)} Б -> {binpath}")
for (img, dx, dy, fl, sw) in gframes:
b.write(bytes((img & 0xFF, dx & 0xFF, dy & 0xFF, fl & 0xFF, sw & 0xFF)))
print(f"kid_data.bin: {len(frames)*5 + len(seqtbl) + len(gframes)*5} Б (кадры Kid + seqtbl + кадры стража) -> {binpath}")
print(f"kid_data.h: {len(frames)} кадров, seqtbl {len(seqtbl)} Б, "
f"{len(offs)} seq-оффсетов -> {OUT}")