Уровень 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:
@@ -8,6 +8,9 @@
|
||||
*
|
||||
* Только DUNGEON-стиль (Фаза 1).
|
||||
*/
|
||||
/* Имена файлов атласов обоих тайлсетов нужны только здесь; макрос обязан
|
||||
* стоять ДО первого включения pop_bg_atlas.h (его тянет pop_tile.h). */
|
||||
#define POP_BG_ATLAS_NAMES
|
||||
#include <graphics.h>
|
||||
#include <gfx.h>
|
||||
#include <sprite.h>
|
||||
@@ -22,34 +25,87 @@
|
||||
#include "pop_level.h" /* pop_doorlink2 — состояние нажатия кнопки */
|
||||
#include "pop_kid.h" /* Kid.curr_col/curr_row — порядок оверлеев */
|
||||
#include "pop_cdraw.h" /* pop_cd — габарит кадра Кида (y-порядок плиты) */
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static const char *const ENV_ATL[5] = {
|
||||
/* Ресурсы разложены по каталогам образа (8.3, как в DSS): BG — фон,
|
||||
* KID — персонаж, GUARD — стражи, LEVELS — уровни. Иначе корень диска
|
||||
* зарастает десятками .atl. */
|
||||
"BG\\pop_env0.atl", "BG\\pop_env1.atl", "BG\\pop_env2.atl",
|
||||
"BG\\pop_env3.atl", "BG\\pop_env4.atl"
|
||||
};
|
||||
/* ---- Тайлсет: подземелье / дворец ----------------------------------- *
|
||||
* Порт tbl_envir_ki[tbl_level_type[level]] (seg000:1108): оригинал под один
|
||||
* и тот же набор id грузит РАЗНЫЙ .DAT — VDUNGEON или VPALACE. У нас так
|
||||
* же: раскладка id -> (страница, idx) общая (упаковщик печёт оба набора по
|
||||
* одному объединению id), меняются только файлы атласов и 32 записи
|
||||
* палитры — 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;
|
||||
for (i = 0; i < 5; i++)
|
||||
if (atlas_load(&pop_env[i], ENV_ATL[i]) != 0) return -1;
|
||||
if (atlas_load(&pop_wall_at, "BG\\pop_wall.atl") != 0) return -1;
|
||||
if (atlas_load(&pop_fore_at, "BG\\pop_fore.atl") != 0) return -1;
|
||||
if (atlas_load(&pop_pot_at, "BG\\pop_pot.atl") != 0) return -1;
|
||||
return 0;
|
||||
if (set >= POP_TILESETS) return -1;
|
||||
if (set == bg_set) return 0;
|
||||
if (bg_set != 0xFF) { /* смена набора — освободить старый */
|
||||
for (i = 0; i < POP_ENV_PAGES; i++) atlas_free(&pop_env[i]);
|
||||
atlas_free(&pop_wall_at);
|
||||
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
|
||||
{
|
||||
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_wall_at);
|
||||
atlas_free(&pop_fore_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};
|
||||
|
||||
Reference in New Issue
Block a user