Таблицы анимации Кида: kid_data.bin -> KID\kid.ani
Все ресурсы Кида теперь зовутся kid.*: kid.arc (атласы), kid.pal (палитра), kid.ani (кадры + seqtbl). Расширение .ani говорит о содержимом: это не «какие-то данные», а таблица кадров и байткод последовательностей движения. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -142,7 +142,7 @@ KID_DATA := $(KID_PAGES) $(KID_VPAGES) $(KID_DIR)/kid.pal \
|
||||
$(KID_DIR)/sword.atl $(KID_DIR)/sword_v.atl
|
||||
# Таблицы анимации (кадры+seqtbl) — отдельный бинарь в EMM-странице, его
|
||||
# делает pop_extract_kid_data.py (не упаковщик спрайтов) — своё правило ниже.
|
||||
KID_BIN := $(KID_DIR)/kid_data.bin
|
||||
KID_BIN := $(KID_DIR)/kid.ani
|
||||
|
||||
# АРХИВ KID. Шестьдесят файлов в одном: замер 2026-08-25 — `open` 51,4 мс
|
||||
# против 32,6 мс на чтение 16 КБ, то есть на одних только открытиях набор
|
||||
@@ -150,7 +150,7 @@ KID_BIN := $(KID_DIR)/kid_data.bin
|
||||
# упаковщик печатает в kid_arc.h (константы ARC_KID_*).
|
||||
KID_ARC := $(KID_DIR)/kid.arc
|
||||
# В архив идут только атласы. Палитру читает gfx_pal_fload прямо в
|
||||
# видеопамять, а kid_data.bin — host-тесты своей файловой заглушкой; ради
|
||||
# видеопамять, а kid.ani — host-тесты своей файловой заглушкой; ради
|
||||
# двух файлов заводить обходные пути незачем.
|
||||
KID_ARC_SRC := $(KID_PAGES) $(KID_VPAGES) $(KID_DIR)/sword.atl \
|
||||
$(KID_DIR)/sword_v.atl
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
/* Смещение данных в странице анимации; ниже 0x100 — ISR-стаб W0. */
|
||||
#define KD_DATA_OFF 0x100u
|
||||
|
||||
extern uint8_t kdat_blk; /* EMM-блок страницы kid_data.bin */
|
||||
extern uint8_t kdat_blk; /* EMM-блок страницы kid.ani */
|
||||
extern uint8_t kdat_page; /* её номер (маппится в W0 на время play_seq) */
|
||||
extern uint8_t kdat_ok; /* данные загружены */
|
||||
|
||||
/* Файловый обмен с W3 делает общий резидентный bank_load_file(), поэтому
|
||||
* оркестратор загрузки kid_data.bin целиком живёт в холодном банке 8. */
|
||||
* оркестратор загрузки kid.ani целиком живёт в холодном банке 8. */
|
||||
|
||||
#endif /* _POP_KID_H */
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
#define SEQTBL_BASE 0x196Eu
|
||||
|
||||
/* {image, dx, dy, flags, sword}; chtab = sword>>6 (0=kid).
|
||||
* САМА таблица кадров и seqtbl лежат в kid_data.bin (EMM-
|
||||
* САМА таблица кадров и seqtbl лежат в kid.ani (EMM-
|
||||
* страница); здесь только тип и размеры. */
|
||||
typedef struct { uint8_t image; int8_t dx, dy; uint8_t flags, sword; } kframe;
|
||||
#define KID_NFRAMES 241
|
||||
#define KID_SEQTBL_LEN 2310
|
||||
|
||||
/* Раскладка kid_data.bin: кадры (KID_NFRAMES*5), затем seqtbl. */
|
||||
/* Раскладка kid.ani: кадры (KID_NFRAMES*5), затем seqtbl. */
|
||||
#define KID_BIN_FRAMES_OFF 0
|
||||
#define KID_BIN_SEQTBL_OFF 1205
|
||||
/* Таблица кадров СТРАЖА (frame_tbl_guard, seg006:372): индекс
|
||||
|
||||
@@ -205,7 +205,7 @@ void pop_guard_free(void) __banked
|
||||
* ДИАПАЗОН — весь, а не «обычный случай». Отрицательные X реальны:
|
||||
* obj_x = 2*fwd − 116 уходит в минус, как только fwd < 58 (левее
|
||||
* x_bump[5]), то есть у левой кромки комнаты — это не экзотика. По
|
||||
* фактическим данным кадров (kid_data.bin: dx Кида −5..+10, стража
|
||||
* фактическим данным кадров (kid.ani: dx Кида −5..+10, стража
|
||||
* −2..+10) при x типа uint8_t и render_dx ∈ {−140, 0, +140} полный
|
||||
* диапазон obj_x = −416..695; таблица кроет −448..703 с запасом.
|
||||
* Деление ниже поэтому недостижимо и оставлено страховкой на случай
|
||||
|
||||
@@ -1028,7 +1028,7 @@ static void intro_restore_game_palette(void)
|
||||
*
|
||||
* Движок общий с игрой, и это главное: последовательности крутит наш
|
||||
* play_seq (pop_kid_play/pop_guard_play), кадры принцессы берутся из
|
||||
* таблицы КАТСЦЕН (kid_data.bin, KID_BIN_CFRAMES_OFF), мышь и Кид — из
|
||||
* таблицы КАТСЦЕН (kid.ani, KID_BIN_CFRAMES_OFF), мышь и Кид — из
|
||||
* таблицы Кида, как в оригинале (frame_table_kid общая для kid и mouse).
|
||||
* Отличается только ОТРИСОВКА: спрайты принцессы лежат в PV-атласах, а
|
||||
* Кид/мышь — в игровых kid-атласах, поэтому в pv.pal под них отведена
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* pop_kboot.c — ЗАГРУЗКА ресурсов Кида: атласы chtab_2 (kid0..27.atl) и
|
||||
* страница таблиц анимации (kid_data.bin). БАНК 8.
|
||||
* страница таблиц анимации (kid.ani). БАНК 8.
|
||||
*
|
||||
* Отрабатывает раз за игру (и на выходе — освобождение), поэтому места в
|
||||
* резиденте W1 не занимает: контракт с интерпретатором — _pop_kid.h, там
|
||||
|
||||
@@ -54,7 +54,7 @@ uint8_t kid_npages;
|
||||
* kid_set_seq / pop_char_set_seq. */
|
||||
static const uint16_t kid_seq_off[KID_NSEQ] = KID_SEQ_OFF_INIT;
|
||||
|
||||
/* ---- Данные анимации в EMM-странице (kid_data.bin) ------------------ *
|
||||
/* ---- Данные анимации в EMM-странице (kid.ani) ----------------------- *
|
||||
* Таблица кадров (241*5 Б) и seqtbl (2310 Б) занимали 3.5 КБ в _CODE окна
|
||||
* W1/W2 — самый дефицитный ресурс. Теперь они лежат в отдельной EMM-
|
||||
* странице, которая маппится в W0 РОВНО на время play_seq (раз за тик), а
|
||||
|
||||
@@ -32,7 +32,7 @@ extern uint8_t pop_next_level;
|
||||
int pop_kid_load(uint8_t npages) __banked;
|
||||
|
||||
/* Данные анимации (таблица кадров + seqtbl) — отдельная EMM-страница
|
||||
* (kid_data.bin): в _CODE окна W1/W2 они занимали 3.5 КБ. Грузить ДО
|
||||
* (kid.ani): в _CODE окна W1/W2 они занимали 3.5 КБ. Грузить ДО
|
||||
* первого kid_init/play_seq. 0 — OK, -1 — ошибка (без них Kid не оживёт).
|
||||
* Страница маппится в W0 внутри play_seq, раз за тик. */
|
||||
int pop_kid_data_load(const char *path) __banked;
|
||||
|
||||
@@ -897,8 +897,8 @@ int pop_boot(void) __banked
|
||||
pop_cd_init(); /* метка «фон трогали» — пустые диапазоны */
|
||||
/* pop_cheats/speed применит pop_settings_apply после pop_sfx_init. */
|
||||
pop_guard_reset();
|
||||
if (pop_kid_data_load("KID\\kid_data.bin") != 0) { /* кадры+seqtbl в EMM-странице */
|
||||
printf("kid_data.bin load failed\n");
|
||||
if (pop_kid_data_load("KID\\kid.ani") != 0) { /* кадры+seqtbl в EMM-странице */
|
||||
printf("kid.ani load failed\n");
|
||||
return -1;
|
||||
}
|
||||
pop_guard_load(); /* атласы стража (GUARD\\g0..g4) */
|
||||
|
||||
@@ -25,7 +25,7 @@ static uint8_t sc_fg[30];
|
||||
void sc_init(void)
|
||||
{
|
||||
kid_blob_install(); /* таблицы туда, куда смотрит pop_kid */
|
||||
pop_kid_data_load("KID\\KID_DATA.BIN");
|
||||
pop_kid_data_load("KID\\KID.ANI");
|
||||
pop_kid_hp_newgame();
|
||||
}
|
||||
|
||||
|
||||
@@ -96,19 +96,19 @@ def main():
|
||||
f.write("#ifndef KID_DATA_H\n#define KID_DATA_H\n#include <stdint.h>\n\n")
|
||||
f.write("#define SEQTBL_BASE 0x%04Xu\n\n" % SEQTBL_BASE)
|
||||
|
||||
# frame table и seqtbl В .h НЕ ПОПАДАЮТ — они уезжают в kid_data.bin
|
||||
# frame table и seqtbl В .h НЕ ПОПАДАЮТ — они уезжают в kid.ani
|
||||
# (EMM-страница): 3.5 КБ в _CODE окна W1/W2 нам дороже, чем один
|
||||
# gfx_w0_map за тик. См. applications/PoP/docs/layout_plan_v2.md §5.1.
|
||||
f.write("/* {image, dx, dy, flags, sword}; chtab = sword>>6 (0=kid).\n"
|
||||
" * САМА таблица кадров и seqtbl лежат в kid_data.bin (EMM-\n"
|
||||
" * САМА таблица кадров и seqtbl лежат в kid.ani (EMM-\n"
|
||||
" * страница); здесь только тип и размеры. */\n")
|
||||
f.write("typedef struct { uint8_t image; int8_t dx, dy; "
|
||||
"uint8_t flags, sword; } kframe;\n")
|
||||
f.write("#define KID_NFRAMES %d\n" % len(frames))
|
||||
f.write("#define KID_SEQTBL_LEN %d\n\n" % len(seqtbl))
|
||||
|
||||
# раскладка kid_data.bin (смещения ОТ НАЧАЛА ДАННЫХ страницы)
|
||||
f.write("/* Раскладка kid_data.bin: кадры (KID_NFRAMES*5), затем seqtbl. */\n")
|
||||
# раскладка kid.ani (смещения ОТ НАЧАЛА ДАННЫХ страницы)
|
||||
f.write("/* Раскладка kid.ani: кадры (KID_NFRAMES*5), затем seqtbl. */\n")
|
||||
f.write("#define KID_BIN_FRAMES_OFF 0\n")
|
||||
f.write("#define KID_BIN_SEQTBL_OFF %d\n" % (len(frames) * 5))
|
||||
f.write("/* Таблица кадров СТРАЖА (frame_tbl_guard, seg006:372): индекс\n"
|
||||
@@ -148,9 +148,9 @@ def main():
|
||||
f.write(emit_c(vals, 12, fmt).replace("\n", " \\\n") + " \\\n}\n")
|
||||
f.write("\n#endif\n")
|
||||
|
||||
# kid_data.bin: кадры (по 5 байт) + seqtbl подряд
|
||||
# kid.ani: кадры (по 5 байт) + seqtbl подряд
|
||||
os.makedirs(OUT_BIN_DIR, exist_ok=True)
|
||||
binpath = os.path.join(OUT_BIN_DIR, "kid_data.bin")
|
||||
binpath = os.path.join(OUT_BIN_DIR, "kid.ani")
|
||||
with open(binpath, "wb") as b:
|
||||
for (img, dx, dy, fl, sw) in frames:
|
||||
b.write(bytes((img & 0xFF, dx & 0xFF, dy & 0xFF, fl & 0xFF, sw & 0xFF)))
|
||||
@@ -159,7 +159,7 @@ def main():
|
||||
b.write(bytes((img & 0xFF, dx & 0xFF, dy & 0xFF, fl & 0xFF, sw & 0xFF)))
|
||||
for (img, dx, dy, fl, sw) in cframes:
|
||||
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 + len(cframes)*5} Б "
|
||||
print(f"kid.ani: {len(frames)*5 + len(seqtbl) + len(gframes)*5 + len(cframes)*5} Б "
|
||||
f"(кадры Kid + seqtbl + кадры стража + кадры катсцен) -> {binpath}")
|
||||
|
||||
print(f"kid_data.h: {len(frames)} кадров, seqtbl {len(seqtbl)} Б, "
|
||||
|
||||
Reference in New Issue
Block a user