Уровень 4: второй тайлсет (дворец) — ассеты и переключение (шаги A и B)
Порт tbl_envir_ki[tbl_level_type[level]] (seg000:1108): оригинал под один и тот же набор id грузит РАЗНЫЙ .DAT — VDUNGEON или VPALACE. Упаковщик (toolchain/pop_pack_bg.py): - аргумент набора: `pop_pack_bg.py dungeon|palace`. Каскад каталогов — сначала свой набор, потом чужой фолбэком (в распакованном data/ res230/ 231/348 есть только в VDUNGEON, два десятка — только в VPALACE). - ОБА набора пакуются по одному объединению id, поэтому раскладка id -> (страница, idx) общая и заголовок один: коду достаточно подменить имена файлов. - PALACE_ENV_IDS: 78/80/82 (doortop_fram_bot), 81/83 (doortop_fram_top), 84 (полоска стены), 145 (stripe_id) — их рисует только палас, render_room про них не знает. - ENV_SHIFT 5 -> 4: с паласными кусками страница 2 переваливала за 16 КБ (16 996). Цена — 10 страниц EMM на набор вместо 5, при 215 свободных. - *tile.pal: 32 записи (env 0x50..0x5F + wall 0x60..0x6F) на набор. Полная kid.pal не трогается — Кид, страж, меч и зелья в других слотах. Движок: - pop_level_type() (tbl_level_type, SDLPoP data.h:840): дворцовые уровни 4, 5, 6, 10, 11, 14. Живёт в pop_level.c, потому что по типу расходятся не только атласы, но и ветки отрисовки seg008, кладка стены и модификатор пустой клетки от упавшей плиты (remove_loose, seg007:0EB8). - pop_bg_load(set): no-op при том же наборе, при смене выгружает старый (иначе текут 12 EMM-страниц) и правит 32 записи палитры в ОБЕ страницы дабл-буфера. Зовётся на старте и на границе уровня, не в кадре. - Путь к атласу склеивается на месте (bg_path): двадцать строк-имён в банке — лишние полкилобайта. Проверено в MAME: уровень 1 (подземелье) рисуется как прежде; уровень 4 (-DFIRST_LEVEL=4) — дворцовые арки, окна, пол, решётчатая дверь уровня, Кид не перекрашен. Стены пока чёрные: паласный wall_pattern — шаг C. tests-host: 5/5. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -2,32 +2,40 @@
|
|||||||
* Сгенерировано toolchain/pop_pack_bg.py — НЕ править вручную.
|
* Сгенерировано toolchain/pop_pack_bg.py — НЕ править вручную.
|
||||||
*
|
*
|
||||||
* Прямая адресация (ноль remap-таблиц в W2):
|
* Прямая адресация (ноль remap-таблиц в W2):
|
||||||
* ENV фон id N -> atlas env_bg[N>>5], idx N&31
|
* ENV фон id N -> atlas env_bg[N>>4], idx N&15
|
||||||
* WALL id N -> atlas wall, idx N
|
* WALL id N -> atlas wall, idx N
|
||||||
* FORE id N -> atlas fore, idx N
|
* FORE id N -> atlas fore, idx N
|
||||||
|
*
|
||||||
|
* ДВА ТАЙЛСЕТА (порт tbl_envir_ki[tbl_level_type], seg000:1108):
|
||||||
|
* 0 = подземелье (pop_*), 1 = дворец (pal_*). Набор id и раскладка
|
||||||
|
* у них ОДНИ И ТЕ ЖЕ — меняются только файлы и 32 записи палитры
|
||||||
|
* (env 0x50..0x5F, wall 0x60..0x6F), см. *tile.pal.
|
||||||
*/
|
*/
|
||||||
#ifndef POP_BG_ATLAS_H
|
#ifndef POP_BG_ATLAS_H
|
||||||
#define POP_BG_ATLAS_H
|
#define POP_BG_ATLAS_H
|
||||||
|
|
||||||
#define POP_ENV_SHIFT 5
|
#define POP_ENV_SHIFT 4
|
||||||
#define POP_ENV_MASK 31
|
#define POP_ENV_MASK 15
|
||||||
#define POP_ENV_PAGES 5
|
#define POP_ENV_PAGES 10
|
||||||
|
#define POP_TILESETS 2
|
||||||
|
|
||||||
/* Палитра: env-слоты, wall-слоты (сприйт-пиксель i -> база+i). */
|
/* Палитра: env-слоты, wall-слоты (спрайт-пиксель i -> база+i). */
|
||||||
#define POP_PAL_ENV 0x50
|
#define POP_PAL_ENV 0x50
|
||||||
#define POP_PAL_WALL 0x60
|
#define POP_PAL_WALL 0x60
|
||||||
|
|
||||||
/* Имена файлов атласов (грузятся atlas_load). */
|
/* Имена файлов атласов по тайлсету (грузятся atlas_load). Таблицы
|
||||||
static const char *const pop_env_atl[POP_ENV_PAGES] = {
|
* видны только тому, кто попросил POP_BG_ATLAS_NAMES: иначе копия
|
||||||
"pop_env0.atl",
|
* строк уедет в каждый включивший заголовок модуль. */
|
||||||
"pop_env1.atl",
|
#ifdef POP_BG_ATLAS_NAMES
|
||||||
"pop_env2.atl",
|
static const char *const pop_env_atl[POP_TILESETS][POP_ENV_PAGES] = {
|
||||||
"pop_env3.atl",
|
{ "pop_env0.atl", "pop_env1.atl", "pop_env2.atl", "pop_env3.atl", "pop_env4.atl", "pop_env5.atl", "pop_env6.atl", "pop_env7.atl", "pop_env8.atl", "pop_env9.atl" },
|
||||||
"pop_env4.atl",
|
{ "pal_env0.atl", "pal_env1.atl", "pal_env2.atl", "pal_env3.atl", "pal_env4.atl", "pal_env5.atl", "pal_env6.atl", "pal_env7.atl", "pal_env8.atl", "pal_env9.atl" },
|
||||||
};
|
};
|
||||||
#define POP_WALL_ATL "pop_wall.atl"
|
static const char *const pop_wall_atl[POP_TILESETS] = { "pop_wall.atl", "pal_wall.atl" };
|
||||||
#define POP_FORE_ATL "pop_fore.atl"
|
static const char *const pop_fore_atl[POP_TILESETS] = { "pop_fore.atl", "pal_fore.atl" };
|
||||||
#define POP_POT_ATL "pop_pot.atl" /* chtab_1: зелья */
|
static const char *const pop_tile_pal[POP_TILESETS] = { "pop_tile.pal", "pal_tile.pal" };
|
||||||
|
#endif /* POP_BG_ATLAS_NAMES */
|
||||||
|
#define POP_POT_ATL "pop_pot.atl" /* chtab_1: зелья, от набора не зависит */
|
||||||
#define POP_PAL_POT 0x40
|
#define POP_PAL_POT 0x40
|
||||||
#define POP_BG_PAL "pop_bg.pal"
|
#define POP_BG_PAL "pop_bg.pal"
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -35,7 +35,7 @@ MEMORY ?= huge # small-раскладка + банки кода в W
|
|||||||
# ВАЖНО: любое сравнение занятости банков имеет смысл только при ОДНОМ и том
|
# ВАЖНО: любое сравнение занятости банков имеет смысл только при ОДНОМ и том
|
||||||
# же ALLOCS — иначе сравниваются не правки, а уровни оптимизации.
|
# же ALLOCS — иначе сравниваются не правки, а уровни оптимизации.
|
||||||
ALLOCS ?= 3000
|
ALLOCS ?= 3000
|
||||||
EXTRA_FLAGS ?= --gfx 256 --max-allocs $(ALLOCS) --bank 2=pop_bg.c --bank 7=pop_room.c --bank 4=pop_cdraw.c --bank 3=pop_map.c --bank 1=guards.c --bank 5=pop_ctrl.c --bank 6=pop_trob.c $(PROF_FLAGS)
|
EXTRA_FLAGS ?= --gfx 256 -I $(CURDIR)/../poc/res/bg --max-allocs $(ALLOCS) --bank 2=pop_bg.c --bank 7=pop_room.c --bank 4=pop_cdraw.c --bank 3=pop_map.c --bank 1=guards.c --bank 5=pop_ctrl.c --bank 6=pop_trob.c $(PROF_FLAGS)
|
||||||
# Профилирование полосами бордюра (см. PROF() в roomtest.c) — ВКЛЮЧЕНО по
|
# Профилирование полосами бордюра (см. PROF() в roomtest.c) — ВКЛЮЧЕНО по
|
||||||
# умолчанию, пока идёт работа с производительностью; make PROF=0 выключает.
|
# умолчанию, пока идёт работа с производительностью; make PROF=0 выключает.
|
||||||
# Каждая фаза кадра красит бордюр в свой цвет, высота полосы на скриншоте
|
# Каждая фаза кадра красит бордюр в свой цвет, высота полосы на скриншоте
|
||||||
@@ -52,9 +52,16 @@ LVL_DIR := $(CURDIR)/../SDLPoP/data/LEVELS
|
|||||||
# диске. res2000 — демо-уровень, в скоуп не входит.
|
# диске. res2000 — демо-уровень, в скоуп не входит.
|
||||||
LVL_NUMS := 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
|
LVL_NUMS := 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
|
||||||
LVL_DATA := $(foreach n,$(LVL_NUMS),$(LVL_DIR)/res20$(n).bin)
|
LVL_DATA := $(foreach n,$(LVL_NUMS),$(LVL_DIR)/res20$(n).bin)
|
||||||
BG_DATA := $(BG_DIR)/pop_env0.atl $(BG_DIR)/pop_env1.atl $(BG_DIR)/pop_env2.atl \
|
# ДВА тайлсета: pop_* — подземелье (уровни 1-3, 7-9, 12, 13, 15),
|
||||||
$(BG_DIR)/pop_env3.atl $(BG_DIR)/pop_env4.atl \
|
# pal_* — дворец (4-6, 10, 11, 14). Раскладка id у них общая, различаются
|
||||||
$(BG_DIR)/pop_wall.atl $(BG_DIR)/pop_fore.atl \
|
# файлы и палитра тайлсета (*tile.pal, 32 записи). chtab_1 (pop_pot.atl:
|
||||||
|
# пламя, меч-предмет, зелья) от набора не зависит — один на оба.
|
||||||
|
BG_SETS := pop pal
|
||||||
|
BG_PAGES := 0 1 2 3 4 5 6 7 8 9
|
||||||
|
BG_DATA := $(foreach s,$(BG_SETS),\
|
||||||
|
$(foreach n,$(BG_PAGES),$(BG_DIR)/$(s)_env$(n).atl) \
|
||||||
|
$(BG_DIR)/$(s)_wall.atl $(BG_DIR)/$(s)_fore.atl \
|
||||||
|
$(BG_DIR)/$(s)_tile.pal) \
|
||||||
$(BG_DIR)/pop_pot.atl
|
$(BG_DIR)/pop_pot.atl
|
||||||
# ВСЕ 28 страниц Kid — иначе кадры торможения/разворота/приседа (image>23)
|
# ВСЕ 28 страниц Kid — иначе кадры торможения/разворота/приседа (image>23)
|
||||||
# не рисуются (отрисовка пропускает незагруженную страницу). Палитра —
|
# не рисуются (отрисовка пропускает незагруженную страницу). Палитра —
|
||||||
@@ -93,7 +100,7 @@ hdd: $(EXAMPLE).exe
|
|||||||
|
|
||||||
TC := $(PROJ_ROOT)/applications/PoP/toolchain
|
TC := $(PROJ_ROOT)/applications/PoP/toolchain
|
||||||
$(BG_DATA): $(TC)/pop_pack_bg.py $(TC)/render_room.py
|
$(BG_DATA): $(TC)/pop_pack_bg.py $(TC)/render_room.py
|
||||||
cd $(TC) && python3 pop_pack_bg.py
|
cd $(TC) && python3 pop_pack_bg.py dungeon && python3 pop_pack_bg.py palace
|
||||||
$(GUARD_DATA): $(TC)/pop_pack_guard.py
|
$(GUARD_DATA): $(TC)/pop_pack_guard.py
|
||||||
cd $(TC) && python3 pop_pack_guard.py
|
cd $(TC) && python3 pop_pack_guard.py
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
/* Загрузить 7 атласов фона. Звать ДО initgraph (как poc.c — atlas_load
|
/* Загрузить 7 атласов фона. Звать ДО initgraph (как poc.c — atlas_load
|
||||||
* трогает W3; проверенный порядок). Палитру pop_bg.pal грузит ПРИЛОЖЕНИЕ
|
* трогает W3; проверенный порядок). Палитру pop_bg.pal грузит ПРИЛОЖЕНИЕ
|
||||||
* после initgraph (gfx_pal_fload). 0 — OK, -1 — ошибка. */
|
* после initgraph (gfx_pal_fload). 0 — OK, -1 — ошибка. */
|
||||||
int pop_bg_load(void) __banked;
|
int pop_bg_load(uint8_t set) __banked; /* 0 подземелье, 1 дворец */
|
||||||
|
|
||||||
/* Освободить EMM-страницы атласов. */
|
/* Освободить EMM-страницы атласов. */
|
||||||
void pop_bg_free(void) __banked;
|
void pop_bg_free(void) __banked;
|
||||||
|
|||||||
@@ -450,6 +450,19 @@ uint8_t pop_level_guard(uint8_t room, uint8_t *tile, int8_t *dir,
|
|||||||
return (uint8_t)(t < 30);
|
return (uint8_t)(t < 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* tbl_level_type (SDLPoP data.h:840). Держим ЗДЕСЬ, а не в слое фона:
|
||||||
|
* тип уровня нужен не только атласам — по нему расходятся ветки отрисовки
|
||||||
|
* (seg008), кладка стены (wall_pattern) и модификатор пустой клетки от
|
||||||
|
* упавшей плиты (remove_loose, seg007:0EB8). */
|
||||||
|
static const uint8_t LEVEL_TYPE[16] = {
|
||||||
|
0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t pop_level_type(void)
|
||||||
|
{
|
||||||
|
return LEVEL_TYPE[pop_current_level & 15];
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t pop_level_start_room(void) { return start_byte(BP_START + 0); }
|
uint8_t pop_level_start_room(void) { return start_byte(BP_START + 0); }
|
||||||
uint8_t pop_level_start_pos(void) { return start_byte(BP_START + 1); }
|
uint8_t pop_level_start_pos(void) { return start_byte(BP_START + 1); }
|
||||||
int8_t pop_level_start_dir(void) { return (int8_t)start_byte(BP_START + 2); }
|
int8_t pop_level_start_dir(void) { return (int8_t)start_byte(BP_START + 2); }
|
||||||
|
|||||||
@@ -135,6 +135,13 @@ uint8_t pop_guard_state_x(uint8_t room);
|
|||||||
uint8_t pop_level_guard(uint8_t room, uint8_t *tile, int8_t *dir,
|
uint8_t pop_level_guard(uint8_t room, uint8_t *tile, int8_t *dir,
|
||||||
uint8_t *color, uint8_t *skill);
|
uint8_t *color, uint8_t *skill);
|
||||||
|
|
||||||
|
/* tbl_level_type (SDLPoP data.h:840) — какой тайлсет у уровня:
|
||||||
|
* 0 подземелье, 1 дворец. Дворцовые: 4, 5, 6, 10, 11, 14. Индекс —
|
||||||
|
* НОМЕР уровня; элемент 0 — демо-уровень. Оригинал по нему выбирает и
|
||||||
|
* .DAT окружения (tbl_envir_ki, seg000:1108), и десяток веток отрисовки
|
||||||
|
* в seg008, и графику стража (GUARD1/GUARD2). */
|
||||||
|
uint8_t pop_level_type(void);
|
||||||
|
|
||||||
uint8_t pop_level_start_room(void);
|
uint8_t pop_level_start_room(void);
|
||||||
uint8_t pop_level_start_pos(void);
|
uint8_t pop_level_start_pos(void);
|
||||||
int8_t pop_level_start_dir(void);
|
int8_t pop_level_start_dir(void);
|
||||||
|
|||||||
@@ -8,6 +8,9 @@
|
|||||||
*
|
*
|
||||||
* Только DUNGEON-стиль (Фаза 1).
|
* Только DUNGEON-стиль (Фаза 1).
|
||||||
*/
|
*/
|
||||||
|
/* Имена файлов атласов обоих тайлсетов нужны только здесь; макрос обязан
|
||||||
|
* стоять ДО первого включения pop_bg_atlas.h (его тянет pop_tile.h). */
|
||||||
|
#define POP_BG_ATLAS_NAMES
|
||||||
#include <graphics.h>
|
#include <graphics.h>
|
||||||
#include <gfx.h>
|
#include <gfx.h>
|
||||||
#include <sprite.h>
|
#include <sprite.h>
|
||||||
@@ -22,34 +25,87 @@
|
|||||||
#include "pop_level.h" /* pop_doorlink2 — состояние нажатия кнопки */
|
#include "pop_level.h" /* pop_doorlink2 — состояние нажатия кнопки */
|
||||||
#include "pop_kid.h" /* Kid.curr_col/curr_row — порядок оверлеев */
|
#include "pop_kid.h" /* Kid.curr_col/curr_row — порядок оверлеев */
|
||||||
#include "pop_cdraw.h" /* pop_cd — габарит кадра Кида (y-порядок плиты) */
|
#include "pop_cdraw.h" /* pop_cd — габарит кадра Кида (y-порядок плиты) */
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
static const char *const ENV_ATL[5] = {
|
/* ---- Тайлсет: подземелье / дворец ----------------------------------- *
|
||||||
/* Ресурсы разложены по каталогам образа (8.3, как в DSS): BG — фон,
|
* Порт tbl_envir_ki[tbl_level_type[level]] (seg000:1108): оригинал под один
|
||||||
* KID — персонаж, GUARD — стражи, LEVELS — уровни. Иначе корень диска
|
* и тот же набор id грузит РАЗНЫЙ .DAT — VDUNGEON или VPALACE. У нас так
|
||||||
* зарастает десятками .atl. */
|
* же: раскладка id -> (страница, idx) общая (упаковщик печёт оба набора по
|
||||||
"BG\\pop_env0.atl", "BG\\pop_env1.atl", "BG\\pop_env2.atl",
|
* одному объединению id), меняются только файлы атласов и 32 записи
|
||||||
"BG\\pop_env3.atl", "BG\\pop_env4.atl"
|
* палитры — env 0x50..0x5F и wall 0x60..0x6F. Кид, страж, меч и зелья
|
||||||
};
|
* живут в других слотах, поэтому общая kid.pal не трогается. */
|
||||||
|
static uint8_t bg_set = 0xFF; /* какой набор сейчас загружен */
|
||||||
|
|
||||||
int pop_bg_load(void) __banked
|
/* Ресурсы разложены по каталогам образа (8.3, как в DSS): BG — фон, KID —
|
||||||
|
* персонаж, GUARD — стражи, LEVELS — уровни. Иначе корень диска зарастает
|
||||||
|
* десятками .atl. Путь склеиваем на месте: держать по строке на каждый из
|
||||||
|
* двадцати атласов — лишние полкилобайта в банке. */
|
||||||
|
static char bg_path_buf[20];
|
||||||
|
|
||||||
|
static const char *bg_path(const char *name)
|
||||||
|
{
|
||||||
|
char *d = bg_path_buf;
|
||||||
|
*d++ = 'B'; *d++ = 'G'; *d++ = '\\';
|
||||||
|
while (*name) *d++ = *name++;
|
||||||
|
*d = 0;
|
||||||
|
return bg_path_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 32 записи (env, затем wall) в ОБЕ палитры: у страниц дабл-буфера они
|
||||||
|
* раздельные. Буфер — на стеке: gfx_pal_load отдаёт указатель BIOS ($A4),
|
||||||
|
* а тот читает только #4000-#BFFF, то есть банковую rodata бы не увидел
|
||||||
|
* (те же грабли, что в pop_guard_set_palette). */
|
||||||
|
static int bg_load_tile_pal(const char *name)
|
||||||
|
{
|
||||||
|
uint8_t buf[64];
|
||||||
|
int fd = open(bg_path(name), O_RDONLY);
|
||||||
|
if (fd < 0) return -1;
|
||||||
|
if (read(fd, buf, 64) != 64) { close(fd); return -1; }
|
||||||
|
gfx_pal_load(0, POP_PAL_ENV, 16, buf);
|
||||||
|
gfx_pal_load(1, POP_PAL_ENV, 16, buf);
|
||||||
|
if (read(fd, buf, 64) != 64) { close(fd); return -1; }
|
||||||
|
gfx_pal_load(0, POP_PAL_WALL, 16, buf);
|
||||||
|
gfx_pal_load(1, POP_PAL_WALL, 16, buf);
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Загрузить набор set (0 подземелье, 1 дворец). Повторный вызов с тем же
|
||||||
|
* набором ничего не делает; со сменой — сначала выгружает старый, иначе
|
||||||
|
* EMM-страницы утекут (их по 12 на набор). */
|
||||||
|
int pop_bg_load(uint8_t set) __banked
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 5; i++)
|
if (set >= POP_TILESETS) return -1;
|
||||||
if (atlas_load(&pop_env[i], ENV_ATL[i]) != 0) return -1;
|
if (set == bg_set) return 0;
|
||||||
if (atlas_load(&pop_wall_at, "BG\\pop_wall.atl") != 0) return -1;
|
if (bg_set != 0xFF) { /* смена набора — освободить старый */
|
||||||
if (atlas_load(&pop_fore_at, "BG\\pop_fore.atl") != 0) return -1;
|
for (i = 0; i < POP_ENV_PAGES; i++) atlas_free(&pop_env[i]);
|
||||||
if (atlas_load(&pop_pot_at, "BG\\pop_pot.atl") != 0) return -1;
|
atlas_free(&pop_wall_at);
|
||||||
return 0;
|
atlas_free(&pop_fore_at);
|
||||||
|
}
|
||||||
|
for (i = 0; i < POP_ENV_PAGES; i++)
|
||||||
|
if (atlas_load(&pop_env[i], bg_path(pop_env_atl[set][i])) != 0) return -1;
|
||||||
|
if (atlas_load(&pop_wall_at, bg_path(pop_wall_atl[set])) != 0) return -1;
|
||||||
|
if (atlas_load(&pop_fore_at, bg_path(pop_fore_atl[set])) != 0) return -1;
|
||||||
|
if (bg_set == 0xFF && /* chtab_1 от набора не зависит */
|
||||||
|
atlas_load(&pop_pot_at, bg_path(POP_POT_ATL)) != 0) return -1;
|
||||||
|
bg_set = set;
|
||||||
|
/* Палитра — ПОСЛЕ атласов: если атлас не загрузился, цвета остаются от
|
||||||
|
* прежнего набора и картинка хотя бы не разъезжается. */
|
||||||
|
return bg_load_tile_pal(pop_tile_pal[set]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_bg_free(void) __banked
|
void pop_bg_free(void) __banked
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 5; i++)
|
if (bg_set == 0xFF) return;
|
||||||
|
for (i = 0; i < POP_ENV_PAGES; i++)
|
||||||
atlas_free(&pop_env[i]);
|
atlas_free(&pop_env[i]);
|
||||||
atlas_free(&pop_wall_at);
|
atlas_free(&pop_wall_at);
|
||||||
atlas_free(&pop_fore_at);
|
atlas_free(&pop_fore_at);
|
||||||
atlas_free(&pop_pot_at);
|
atlas_free(&pop_pot_at);
|
||||||
|
bg_set = 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint8_t SPIKES_FRAM_RIGHT[10] = {0, 134, 135, 136, 137, 138, 137, 135, 134, 0};
|
static const uint8_t SPIKES_FRAM_RIGHT[10] = {0, 134, 135, 136, 137, 138, 137, 135, 134, 0};
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
#include "_pop_draw.h" /* pop_heal_fast */
|
#include "_pop_draw.h" /* pop_heal_fast */
|
||||||
|
|
||||||
/* ---- Состояние (писучее, _DATA/W2 — видно из любого банка) ---------- */
|
/* ---- Состояние (писучее, _DATA/W2 — видно из любого банка) ---------- */
|
||||||
atlas_t pop_env[5], pop_wall_at, pop_fore_at, pop_pot_at;
|
atlas_t pop_env[POP_ENV_PAGES], pop_wall_at, pop_fore_at, pop_pot_at;
|
||||||
|
|
||||||
const uint8_t *pop_t_fg, *pop_t_bg, *pop_t_lfg, *pop_t_lbg;
|
const uint8_t *pop_t_fg, *pop_t_bg, *pop_t_lfg, *pop_t_lbg;
|
||||||
const uint8_t *pop_t_below, *pop_t_above, *pop_t_abovemod;
|
const uint8_t *pop_t_below, *pop_t_above, *pop_t_abovemod;
|
||||||
@@ -262,7 +262,7 @@ void pop_blit_b(atlas_t *a, uint8_t idx, int x, int ybottom)
|
|||||||
gfx_w0_unmap();
|
gfx_w0_unmap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_env_b(uint8_t id, int x, int yb) { pop_blit_b(&pop_env[id >> 5], (uint8_t)(id & 31), x, yb); }
|
void pop_env_b(uint8_t id, int x, int yb) { pop_blit_b(&pop_env[id >> POP_ENV_SHIFT], (uint8_t)(id & POP_ENV_MASK), x, yb); }
|
||||||
void pop_wall_b(uint8_t id, int x, int yb) { pop_blit_b(&pop_wall_at, id, x, yb); }
|
void pop_wall_b(uint8_t id, int x, int yb) { pop_blit_b(&pop_wall_at, id, x, yb); }
|
||||||
void pop_fore_b(uint8_t id, int x, int yb) { pop_blit_b(&pop_fore_at, id, x, yb); }
|
void pop_fore_b(uint8_t id, int x, int yb) { pop_blit_b(&pop_fore_at, id, x, yb); }
|
||||||
void pop_pot_b(uint8_t id, int x, int yb) { pop_blit_b(&pop_pot_at, id, x, yb); }
|
void pop_pot_b(uint8_t id, int x, int yb) { pop_blit_b(&pop_pot_at, id, x, yb); }
|
||||||
|
|||||||
@@ -31,9 +31,13 @@
|
|||||||
#include "pop_geom.h" /* pop_rnd_t — сид кладки комнаты */
|
#include "pop_geom.h" /* pop_rnd_t — сид кладки комнаты */
|
||||||
|
|
||||||
/* ---- Атласы фона (прямая адресация id) ------------------------------ *
|
/* ---- Атласы фона (прямая адресация id) ------------------------------ *
|
||||||
* env[id>>5] idx id&31 — chtab_6 environment; wall — chtab_7; fore —
|
* env[id>>POP_ENV_SHIFT] idx id&POP_ENV_MASK — chtab_6 environment;
|
||||||
* передний слой; pot — chtab_1 (зелья, меч-предмет). */
|
* wall — chtab_7; fore — передний слой; pot — chtab_1 (зелья, меч).
|
||||||
extern atlas_t pop_env[5], pop_wall_at, pop_fore_at, pop_pot_at;
|
* Раскладка и число страниц — из pop_bg_atlas.h (генерит упаковщик).
|
||||||
|
* Тайлсетов ДВА (подземелье/дворец), но раскладка id у них общая:
|
||||||
|
* подменяются только файлы и 32 записи палитры (см. pop_bg_set_tileset). */
|
||||||
|
#include "pop_bg_atlas.h"
|
||||||
|
extern atlas_t pop_env[POP_ENV_PAGES], pop_wall_at, pop_fore_at, pop_pot_at;
|
||||||
|
|
||||||
/* ---- Текущая отрисованная комната ----------------------------------- *
|
/* ---- Текущая отрисованная комната ----------------------------------- *
|
||||||
* fg — foretable-коды, bg — модификаторы; lfg/lbg — правый столбец ЛЕВОГО
|
* fg — foretable-коды, bg — модификаторы; lfg/lbg — правый столбец ЛЕВОГО
|
||||||
|
|||||||
@@ -479,7 +479,11 @@ int main(void)
|
|||||||
uint8_t cheat_prev = 0, immo_prev = 0, sword_prev = 0, nlvl_prev = 0;
|
uint8_t cheat_prev = 0, immo_prev = 0, sword_prev = 0, nlvl_prev = 0;
|
||||||
uint8_t xdec_prev = 0, xinc_prev = 0;
|
uint8_t xdec_prev = 0, xinc_prev = 0;
|
||||||
|
|
||||||
if (pop_bg_load() != 0) { /* атласы — ДО initgraph (снимает DSS-страницу W0) */
|
/* Набор фона — по типу СТАРТОВОГО уровня. Атласы грузятся ДО initgraph
|
||||||
|
* (тот снимает DSS-страницу W0); уровень к этому моменту ещё не прочитан,
|
||||||
|
* поэтому тип берём напрямую от номера. */
|
||||||
|
pop_current_level = FIRST_LEVEL;
|
||||||
|
if (pop_bg_load(pop_level_type()) != 0) {
|
||||||
puts("pop_bg_load failed");
|
puts("pop_bg_load failed");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -757,6 +761,14 @@ int main(void)
|
|||||||
* пределы, и персонаж просто не виден. */
|
* пределы, и персонаж просто не виден. */
|
||||||
pop_guard_free();
|
pop_guard_free();
|
||||||
pop_guard_load();
|
pop_guard_load();
|
||||||
|
/* Тайлсет: подземелье <-> дворец (порт tbl_envir_ki,
|
||||||
|
* seg000:1108). Внутри — no-op, если тип не менялся;
|
||||||
|
* при смене выгружает старые атласы и правит 32 записи
|
||||||
|
* палитры. Только на границе уровня, не в кадре. */
|
||||||
|
if (pop_bg_load(pop_level_type()) != 0) {
|
||||||
|
puts("bg set load failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
/* Всё состояние прошлого уровня сносит сам pop_start_level:
|
/* Всё состояние прошлого уровня сносит сам pop_start_level:
|
||||||
* pop_trob_reset обнуляет room_seen (модификаторы комнат
|
* pop_trob_reset обнуляет room_seen (модификаторы комнат
|
||||||
* перечитаются из НОВОЙ страницы), тайлы/стражи приезжают
|
* перечитаются из НОВОЙ страницы), тайлы/стражи приезжают
|
||||||
|
|||||||
@@ -129,7 +129,37 @@ CHOMPER_BLOOD_COLOR = VGA16_PAL_BASE + 12 # тот же mono-цвет 12 (seg0
|
|||||||
# рисуется chtab_6 id 146). В статический render_room не попадает.
|
# рисуется chtab_6 id 146). В статический render_room не попадает.
|
||||||
TORCH_ENV_IDS = {146}
|
TORCH_ENV_IDS = {146}
|
||||||
|
|
||||||
ENV_SHIFT = 5 # env фон: страница = id>>5, idx = id&31
|
# ---- Два тайлсета: подземелье и дворец --------------------------------
|
||||||
|
# Оригинал грузит РАЗНЫЙ .DAT под один и тот же набор id:
|
||||||
|
# tbl_envir_ki[tbl_level_type[level]] -> VDUNGEON / VPALACE (seg000:1108),
|
||||||
|
# то есть id спрайта от набора НЕ зависит — меняется только картинка и
|
||||||
|
# палитра (env 0x50..0x5F, wall 0x60..0x6F). Поэтому оба набора пакуются
|
||||||
|
# по ОДНОМУ И ТОМУ ЖЕ объединению id: раскладка id -> (страница, idx)
|
||||||
|
# остаётся одна, и коду достаточно подменить ИМЕНА файлов.
|
||||||
|
#
|
||||||
|
# Порядок каталогов — каскад: сначала «свой» набор, потом чужой как
|
||||||
|
# фолбэк (в распакованном data/ несколько id есть только в одном из них:
|
||||||
|
# res230/231/348 только в VDUNGEON, два десятка — только в VPALACE).
|
||||||
|
SETS = {
|
||||||
|
"dungeon": ("pop_", lambda: (R.VDUNGEON_DIR, R.VPALACE_DIR)),
|
||||||
|
"palace": ("pal_", lambda: (R.VPALACE_DIR, R.VDUNGEON_DIR)),
|
||||||
|
}
|
||||||
|
SRC_DIRS = None # ставит main() по выбранному набору
|
||||||
|
|
||||||
|
# Спрайты, которые рисуются ТОЛЬКО на паласных уровнях (seg008):
|
||||||
|
# 78, 80, 82 doortop_fram_bot (низ верха двери, draw_tile_right)
|
||||||
|
# 81, 83 doortop_fram_top (draw_tile_topright)
|
||||||
|
# 84 полоска на стене (draw_tile_right, tiles_20_wall)
|
||||||
|
# 145 stripe_id соседнего тайла (draw_tile_right)
|
||||||
|
# render_room про них не знает (он рисует по подземельной ветке), поэтому
|
||||||
|
# добавляем явно — иначе при переключении набора в этих местах будет дыра.
|
||||||
|
PALACE_ENV_IDS = {78, 80, 81, 82, 83, 84, 145}
|
||||||
|
|
||||||
|
ENV_SHIFT = 4 # env фон: страница = id>>SHIFT, idx = id&MASK.
|
||||||
|
# Было 5: паласный набор добавляет куски верха
|
||||||
|
# двери (78..84), и страница 2 переваливала за
|
||||||
|
# 16 КБ. При 4 обе раскладки укладываются, цена
|
||||||
|
# — 10 страниц EMM на набор вместо 5.
|
||||||
ENV_MASK = (1 << ENV_SHIFT) - 1
|
ENV_MASK = (1 << ENV_SHIFT) - 1
|
||||||
|
|
||||||
# ---- .atl формат (== libbgi, но каталог не ограничен 19) --------------
|
# ---- .atl формат (== libbgi, но каталог не ограничен 19) --------------
|
||||||
@@ -194,7 +224,8 @@ NO_TRANSP_ENV_IDS = {36, 43, 73, 74, 96, 149} | LEVELDOOR_ENV_IDS
|
|||||||
|
|
||||||
|
|
||||||
def load_indexed(chtab, id, opaque=False, mono=None):
|
def load_indexed(chtab, id, opaque=False, mono=None):
|
||||||
"""PNG (mode P, 16 цветов) -> (w, h, bytes 8bpp). Каскад VDUNGEON->VPALACE.
|
"""PNG (mode P, 16 цветов) -> (w, h, bytes 8bpp). Каскад по SRC_DIRS
|
||||||
|
(порядок задаёт выбранный тайлсет, см. SETS).
|
||||||
Пиксель 0 -> 0xFF (прозрач); i -> base+i (env 0x50 / wall 0x60).
|
Пиксель 0 -> 0xFF (прозрач); i -> base+i (env 0x50 / wall 0x60).
|
||||||
|
|
||||||
opaque=True — пиксель 0 остаётся ЦВЕТОМ (base+0 = чёрный), а не ключом
|
opaque=True — пиксель 0 остаётся ЦВЕТОМ (base+0 = чёрный), а не ключом
|
||||||
@@ -203,7 +234,7 @@ def load_indexed(chtab, id, opaque=False, mono=None):
|
|||||||
pal_base = 0x60 if chtab == R.CHTAB_WALL else 0x50
|
pal_base = 0x60 if chtab == R.CHTAB_WALL else 0x50
|
||||||
fname = f"res{base_res + id}.png"
|
fname = f"res{base_res + id}.png"
|
||||||
path = None
|
path = None
|
||||||
for d in (R.VDUNGEON_DIR, R.VPALACE_DIR):
|
for d in SRC_DIRS:
|
||||||
p = os.path.join(d, fname)
|
p = os.path.join(d, fname)
|
||||||
if os.path.exists(p):
|
if os.path.exists(p):
|
||||||
path = p
|
path = p
|
||||||
@@ -306,11 +337,29 @@ def scale6to8(v):
|
|||||||
return (v * 255) // 63
|
return (v * 255) // 63
|
||||||
|
|
||||||
|
|
||||||
|
def read_pal16(res, d):
|
||||||
|
b = open(os.path.join(d, res), "rb").read()
|
||||||
|
return [(b[4 + i * 3], b[4 + i * 3 + 1], b[4 + i * 3 + 2]) for i in range(16)]
|
||||||
|
|
||||||
|
|
||||||
|
def build_tileset_palette(out_path):
|
||||||
|
"""Палитра ТОЛЬКО тайлсета: 32 записи B,G,R,0 — env (16) затем wall (16).
|
||||||
|
Ею подменяются слоты 0x50..0x6F при смене типа уровня; полная игровая
|
||||||
|
палитра (kid.pal) при этом не трогается, потому что Кид, страж, меч и
|
||||||
|
зелья живут в других слотах (levels_plan §3). Порядок каталогов —
|
||||||
|
SRC_DIRS, то есть файл соответствует выбранному набору."""
|
||||||
|
pal = bytearray(32 * 4)
|
||||||
|
src = read_pal16("res200.pal", SRC_DIRS[0]) + read_pal16("res360.pal", SRC_DIRS[0])
|
||||||
|
for i, (r, g, b) in enumerate(src):
|
||||||
|
pal[i * 4:i * 4 + 4] = bytes((scale6to8(b), scale6to8(g), scale6to8(r), 0))
|
||||||
|
with open(out_path, "wb") as f:
|
||||||
|
f.write(pal)
|
||||||
|
|
||||||
|
|
||||||
def build_palette(out_path):
|
def build_palette(out_path):
|
||||||
"""256-записная палитра B,G,R,0: env@0x50..0x5F, wall@0x60..0x6F."""
|
"""256-записная палитра B,G,R,0: env@0x50..0x5F, wall@0x60..0x6F."""
|
||||||
def read_pal(res, d):
|
def read_pal(res, d):
|
||||||
b = open(os.path.join(d, res), "rb").read()
|
return read_pal16(res, d)
|
||||||
return [(b[4 + i * 3], b[4 + i * 3 + 1], b[4 + i * 3 + 2]) for i in range(16)]
|
|
||||||
|
|
||||||
env = read_pal("res200.pal", R.VDUNGEON_DIR)
|
env = read_pal("res200.pal", R.VDUNGEON_DIR)
|
||||||
wall = read_pal("res360.pal", R.VDUNGEON_DIR)
|
wall = read_pal("res360.pal", R.VDUNGEON_DIR)
|
||||||
@@ -334,7 +383,10 @@ def build_palette(out_path):
|
|||||||
|
|
||||||
|
|
||||||
# ---- 5. C-заголовок --------------------------------------------------
|
# ---- 5. C-заголовок --------------------------------------------------
|
||||||
def write_header(out_path, env_pages, wall_name, fore_name):
|
def write_header(out_path, env_pages):
|
||||||
|
"""Заголовок ОДИН на оба тайлсета: раскладка id -> (страница, idx) у них
|
||||||
|
общая (пакуются по одному объединению id), различаются только имена
|
||||||
|
файлов и палитра. Поэтому здесь два массива имён и один индекс."""
|
||||||
lines = [
|
lines = [
|
||||||
"/* pop_bg_atlas.h — раскладка атласов статического фона PoP.",
|
"/* pop_bg_atlas.h — раскладка атласов статического фона PoP.",
|
||||||
" * Сгенерировано toolchain/pop_pack_bg.py — НЕ править вручную.",
|
" * Сгенерировано toolchain/pop_pack_bg.py — НЕ править вручную.",
|
||||||
@@ -343,6 +395,11 @@ def write_header(out_path, env_pages, wall_name, fore_name):
|
|||||||
" * ENV фон id N -> atlas env_bg[N>>%d], idx N&%d" % (ENV_SHIFT, ENV_MASK),
|
" * ENV фон id N -> atlas env_bg[N>>%d], idx N&%d" % (ENV_SHIFT, ENV_MASK),
|
||||||
" * WALL id N -> atlas wall, idx N",
|
" * WALL id N -> atlas wall, idx N",
|
||||||
" * FORE id N -> atlas fore, idx N",
|
" * FORE id N -> atlas fore, idx N",
|
||||||
|
" *",
|
||||||
|
" * ДВА ТАЙЛСЕТА (порт tbl_envir_ki[tbl_level_type], seg000:1108):",
|
||||||
|
" * 0 = подземелье (pop_*), 1 = дворец (pal_*). Набор id и раскладка",
|
||||||
|
" * у них ОДНИ И ТЕ ЖЕ — меняются только файлы и 32 записи палитры",
|
||||||
|
" * (env 0x50..0x5F, wall 0x60..0x6F), см. *tile.pal.",
|
||||||
" */",
|
" */",
|
||||||
"#ifndef POP_BG_ATLAS_H",
|
"#ifndef POP_BG_ATLAS_H",
|
||||||
"#define POP_BG_ATLAS_H",
|
"#define POP_BG_ATLAS_H",
|
||||||
@@ -350,22 +407,32 @@ def write_header(out_path, env_pages, wall_name, fore_name):
|
|||||||
"#define POP_ENV_SHIFT %d" % ENV_SHIFT,
|
"#define POP_ENV_SHIFT %d" % ENV_SHIFT,
|
||||||
"#define POP_ENV_MASK %d" % ENV_MASK,
|
"#define POP_ENV_MASK %d" % ENV_MASK,
|
||||||
"#define POP_ENV_PAGES %d" % len(env_pages),
|
"#define POP_ENV_PAGES %d" % len(env_pages),
|
||||||
|
"#define POP_TILESETS 2",
|
||||||
"",
|
"",
|
||||||
"/* Палитра: env-слоты, wall-слоты (сприйт-пиксель i -> база+i). */",
|
"/* Палитра: env-слоты, wall-слоты (спрайт-пиксель i -> база+i). */",
|
||||||
"#define POP_PAL_ENV 0x50",
|
"#define POP_PAL_ENV 0x50",
|
||||||
"#define POP_PAL_WALL 0x60",
|
"#define POP_PAL_WALL 0x60",
|
||||||
"",
|
"",
|
||||||
"/* Имена файлов атласов (грузятся atlas_load). */",
|
"/* Имена файлов атласов по тайлсету (грузятся atlas_load). Таблицы",
|
||||||
"static const char *const pop_env_atl[POP_ENV_PAGES] = {",
|
" * видны только тому, кто попросил POP_BG_ATLAS_NAMES: иначе копия",
|
||||||
|
" * строк уедет в каждый включивший заголовок модуль. */",
|
||||||
|
"#ifdef POP_BG_ATLAS_NAMES",
|
||||||
|
"static const char *const pop_env_atl[POP_TILESETS][POP_ENV_PAGES] = {",
|
||||||
]
|
]
|
||||||
for pg in range(len(env_pages)):
|
for prefix, _ in SETS.values():
|
||||||
nm = env_pages[pg]
|
row = ", ".join(('"%s%s"' % (prefix, nm.split("_", 1)[1]) if nm else "0")
|
||||||
lines.append(' %s,' % ('"%s"' % nm if nm else "0 /* пусто */"))
|
for nm in env_pages)
|
||||||
|
lines.append(" { %s }," % row)
|
||||||
lines += [
|
lines += [
|
||||||
"};",
|
"};",
|
||||||
'#define POP_WALL_ATL "%s"' % wall_name,
|
'static const char *const pop_wall_atl[POP_TILESETS] = { %s };'
|
||||||
'#define POP_FORE_ATL "%s"' % fore_name,
|
% ", ".join('"%swall.atl"' % p for p, _ in SETS.values()),
|
||||||
'#define POP_POT_ATL "pop_pot.atl" /* chtab_1: зелья */',
|
'static const char *const pop_fore_atl[POP_TILESETS] = { %s };'
|
||||||
|
% ", ".join('"%sfore.atl"' % p for p, _ in SETS.values()),
|
||||||
|
'static const char *const pop_tile_pal[POP_TILESETS] = { %s };'
|
||||||
|
% ", ".join('"%stile.pal"' % p for p, _ in SETS.values()),
|
||||||
|
"#endif /* POP_BG_ATLAS_NAMES */",
|
||||||
|
'#define POP_POT_ATL "pop_pot.atl" /* chtab_1: зелья, от набора не зависит */',
|
||||||
"#define POP_PAL_POT 0x%02X" % POT_PAL_BASE,
|
"#define POP_PAL_POT 0x%02X" % POT_PAL_BASE,
|
||||||
'#define POP_BG_PAL "pop_bg.pal"',
|
'#define POP_BG_PAL "pop_bg.pal"',
|
||||||
"",
|
"",
|
||||||
@@ -377,6 +444,14 @@ def write_header(out_path, env_pages, wall_name, fore_name):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
global SRC_DIRS
|
||||||
|
set_name = sys.argv[1] if len(sys.argv) > 1 else "dungeon"
|
||||||
|
if set_name not in SETS:
|
||||||
|
die(f"набор '{set_name}': ожидался один из {', '.join(SETS)}")
|
||||||
|
prefix, dirs = SETS[set_name]
|
||||||
|
SRC_DIRS = dirs()
|
||||||
|
print(f"набор: {set_name} (источник {os.path.basename(SRC_DIRS[0])}, "
|
||||||
|
f"фолбэк {os.path.basename(SRC_DIRS[1])}), префикс {prefix}")
|
||||||
os.makedirs(OUT_DIR, exist_ok=True)
|
os.makedirs(OUT_DIR, exist_ok=True)
|
||||||
used = collect_used()
|
used = collect_used()
|
||||||
env_ids = sorted(set(id for ch, id in used if ch != R.CHTAB_WALL)
|
env_ids = sorted(set(id for ch, id in used if ch != R.CHTAB_WALL)
|
||||||
@@ -392,7 +467,8 @@ def main():
|
|||||||
| CHOMPER_BLOOD_IDS # кровь (mono)
|
| CHOMPER_BLOOD_IDS # кровь (mono)
|
||||||
| CHOMPER_BLOOD_FORE_IDS
|
| CHOMPER_BLOOD_FORE_IDS
|
||||||
| OPENER_NOFLOOR_ENV_IDS # + opener без пола слева
|
| OPENER_NOFLOOR_ENV_IDS # + opener без пола слева
|
||||||
| LEVELDOOR_ENV_IDS) # + дверь уровня (створка/лестница)
|
| LEVELDOOR_ENV_IDS # + дверь уровня (створка/лестница)
|
||||||
|
| PALACE_ENV_IDS) # + куски, что рисует только палас
|
||||||
wall_ids = sorted(id for ch, id in used if ch == R.CHTAB_WALL)
|
wall_ids = sorted(id for ch, id in used if ch == R.CHTAB_WALL)
|
||||||
|
|
||||||
env_bg = [i for i in env_ids if i not in FORE_ENV_IDS]
|
env_bg = [i for i in env_ids if i not in FORE_ENV_IDS]
|
||||||
@@ -410,7 +486,7 @@ def main():
|
|||||||
total_bytes = 0
|
total_bytes = 0
|
||||||
for pg in range(max_pg + 1):
|
for pg in range(max_pg + 1):
|
||||||
if pg in pages:
|
if pg in pages:
|
||||||
nm = f"pop_env{pg}.atl"
|
nm = f"{prefix}env{pg}.atl"
|
||||||
cnt, sz = pack_atlas(os.path.join(OUT_DIR, nm), pages[pg])
|
cnt, sz = pack_atlas(os.path.join(OUT_DIR, nm), pages[pg])
|
||||||
total_bytes += sz
|
total_bytes += sz
|
||||||
env_page_names.append(nm)
|
env_page_names.append(nm)
|
||||||
@@ -421,18 +497,18 @@ def main():
|
|||||||
|
|
||||||
# WALL -> idx=id
|
# WALL -> idx=id
|
||||||
wall_entries = {id: load_indexed(R.CHTAB_WALL, id) for id in wall_ids}
|
wall_entries = {id: load_indexed(R.CHTAB_WALL, id) for id in wall_ids}
|
||||||
cnt, sz = pack_atlas(os.path.join(OUT_DIR, "pop_wall.atl"), wall_entries)
|
cnt, sz = pack_atlas(os.path.join(OUT_DIR, prefix + "wall.atl"), wall_entries)
|
||||||
total_bytes += sz
|
total_bytes += sz
|
||||||
print(f" pop_wall.atl: {len(wall_ids)} спрайтов, каталог {cnt}, {sz} Б")
|
print(f" {prefix}wall.atl: {len(wall_ids)} спрайтов, каталог {cnt}, {sz} Б")
|
||||||
|
|
||||||
# FORE -> idx=id
|
# FORE -> idx=id
|
||||||
fore_entries = {id: load_indexed(R.CHTAB_ENV, id, False,
|
fore_entries = {id: load_indexed(R.CHTAB_ENV, id, False,
|
||||||
CHOMPER_BLOOD_COLOR
|
CHOMPER_BLOOD_COLOR
|
||||||
if id in CHOMPER_BLOOD_FORE_IDS else None)
|
if id in CHOMPER_BLOOD_FORE_IDS else None)
|
||||||
for id in env_fore}
|
for id in env_fore}
|
||||||
cnt, sz = pack_atlas(os.path.join(OUT_DIR, "pop_fore.atl"), fore_entries)
|
cnt, sz = pack_atlas(os.path.join(OUT_DIR, prefix + "fore.atl"), fore_entries)
|
||||||
total_bytes += sz
|
total_bytes += sz
|
||||||
print(f" pop_fore.atl: {len(env_fore)} спрайтов, каталог {cnt}, {sz} Б")
|
print(f" {prefix}fore.atl: {len(env_fore)} спрайтов, каталог {cnt}, {sz} Б")
|
||||||
|
|
||||||
# POTION (chtab_1) -> idx=id: склянки + кадры пузырька + маска
|
# POTION (chtab_1) -> idx=id: склянки + кадры пузырька + маска
|
||||||
# chtab_1 целиком (res151..res173 = id 1..23): пламя факелов, меч-предмет,
|
# chtab_1 целиком (res151..res173 = id 1..23): пламя факелов, меч-предмет,
|
||||||
@@ -452,13 +528,15 @@ def main():
|
|||||||
pot_entries[id] = load_potion(id, opaque=True)
|
pot_entries[id] = load_potion(id, opaque=True)
|
||||||
else:
|
else:
|
||||||
pot_entries[id] = load_potion(id)
|
pot_entries[id] = load_potion(id)
|
||||||
|
# chtab_1 (пламя/меч/зелья) от тайлсета НЕ зависит — пакуем один раз.
|
||||||
cnt, sz = pack_atlas(os.path.join(OUT_DIR, "pop_pot.atl"), pot_entries)
|
cnt, sz = pack_atlas(os.path.join(OUT_DIR, "pop_pot.atl"), pot_entries)
|
||||||
total_bytes += sz
|
total_bytes += sz
|
||||||
print(f" pop_pot.atl (chtab_1: факелы+зелья): {len(pot_entries)} спрайтов, каталог {cnt}, {sz} Б")
|
print(f" pop_pot.atl (chtab_1: факелы+зелья): {len(pot_entries)} спрайтов, каталог {cnt}, {sz} Б")
|
||||||
|
|
||||||
|
build_tileset_palette(os.path.join(OUT_DIR, prefix + "tile.pal"))
|
||||||
|
print(f" {prefix}tile.pal: 32 записи (env 0x50..0x5F + wall 0x60..0x6F)")
|
||||||
build_palette(os.path.join(OUT_DIR, "pop_bg.pal"))
|
build_palette(os.path.join(OUT_DIR, "pop_bg.pal"))
|
||||||
write_header(os.path.join(OUT_DIR, "pop_bg_atlas.h"),
|
write_header(os.path.join(OUT_DIR, "pop_bg_atlas.h"), env_page_names)
|
||||||
env_page_names, "pop_wall.atl", "pop_fore.atl")
|
|
||||||
|
|
||||||
n_pages = sum(1 for n in env_page_names if n) + 2
|
n_pages = sum(1 for n in env_page_names if n) + 2
|
||||||
print(f"ИТОГО: {len(env_bg)} env-фон + {len(wall_ids)} wall + "
|
print(f"ИТОГО: {len(env_bg)} env-фон + {len(wall_ids)} wall + "
|
||||||
|
|||||||
Reference in New Issue
Block a user