Files
Sprinter-SDCC/applications/PoP/roomtest/pop_shadow.c
T
snark13 30bcc3459b Атлас Тени: запечённый набор вместо спрайтов стража
Оригинал кладёт спрайт дважды — прозрачным блитом в x и XOR-блиттером в
x+1; пакетный блит так не умеет, поэтому результат запечён упаковщиком.
Две половины, как и у оригинала: sk* — кадры вне боя (спрайты Кида),
sf* — кадры 150..189 (SHADOW.DAT, тоже графика Кида).  251 спрайт,
32 EMM-страницы, палитра 16 цветов в 0xA0..0xAF.

Закрывает BUG-SHADOW-SET: раньше тип 4 уходил в guard_names, и Тень в
бою дралась серым стражем.

Грабля: kid.pal заливает все 256 записей и затирает слоты Тени —
палитра вынесена в pop_shadow_pal_apply рядом с pop_bg_pal_apply.

Проверено в MAME на 6-м уровне: силуэт с контуром, как в оригинале.
2026-08-20 11:22:53 +03:00

89 lines
4.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* pop_shadow.c — загрузка запечённого набора спрайтов Тени. Зачем набор
* отдельный и почему половин две — в шапке pop_shadow.h.
*
* Код ХОЛОДНЫЙ (раз на уровень), поэтому живёт в банке 8 вместе с прочей
* загрузкой. Сами atlas_t — в W2: их читает отрисовка из банка 4, а
* данные видны из любого банка.
*/
#include <stdint.h>
#include <gfx.h>
#include <sprite.h>
#include "pop_shadow.h"
#include "pop_shadow_atlas.h"
atlas_t pop_shadow_kid[POP_SHADOW_KID_PAGES];
atlas_t pop_shadow_fgt[POP_SHADOW_FGT_PAGES];
uint8_t pop_shadow_kid_n, pop_shadow_fgt_n;
/* ГРУЗИМ ОДИН РАЗ НА ЗАПУСК, а не по уровням.
*
* Тень бывает на ЧЕТЫРЁХ уровнях: 4 — рождается прыжком сквозь зеркало
* (jump_through_mirror, seg003:0811, ставит Char.charid = charid_1_shadow
* прямо из Кида), 5 — крадёт зелье, 6 — прыгает через пропасть, 12 —
* дерётся. Читается как три, потому что таблиц init_shad_N всего три
* (5/6/12): четвёртой нет — на 4-м Тень копируется с Кида, а не поднимается
* из таблицы. Так вот, напрашивается
* грузить набор только там, как это сделано с перевёрнутыми наборами
* (pop_vflip_load_all зовётся лишь на POP_UPSIDE_LEVEL). Решение
* пользователя — грузить сразу, и оно правильное по двум причинам:
* страниц EMM с запасом (32 из ~215 свободных), а вот забыть перезагрузку
* на границе уровня легко — ровно так и появился BUG-SHADOW-SET. Разовая
* загрузка убирает целый класс ошибок и заодно не тормозит переход между
* уровнями на 32 файла. */
int pop_shadow_load(void) __banked
{
uint8_t i;
if (pop_shadow_kid_n || pop_shadow_fgt_n) return 0; /* уже загружен */
for (i = 0; i < POP_SHADOW_KID_PAGES; i++) {
if (atlas_load(&pop_shadow_kid[i], pop_shadow_kid_atl[i]) != 0) {
pop_shadow_free();
return -1;
}
pop_shadow_kid_n = (uint8_t)(i + 1);
}
for (i = 0; i < POP_SHADOW_FGT_PAGES; i++) {
if (atlas_load(&pop_shadow_fgt[i], pop_shadow_fgt_atl[i]) != 0) {
pop_shadow_free();
return -1;
}
pop_shadow_fgt_n = (uint8_t)(i + 1);
}
pop_shadow_pal_apply();
return 0;
}
/* ПАЛИТРА ОТДЕЛЬНО ОТ ЗАГРУЗКИ, и это не косметика.
*
* `gfx_pal_fload("KID\\kid.pal")` заливает ВСЕ 256 записей — это единая
* игровая палитра, — и затирает любые слоты, выставленные до него. Ровно
* та же беда уже была с тайлсетом: сразу за ним стоит pop_bg_pal_apply,
* который возвращает цвета env/wall. Наши 0xA0..0xAF из той же оперы, и
* в первом заходе я на это наступил: набор грузился, силуэт рисовался
* правильной формы, но ЦЕЛИКОМ ЧЁРНЫЙ (поймано пользователем на 6-м
* уровне). Поэтому вызов живёт рядом с pop_bg_pal_apply, а не внутри
* загрузки атласов.
*
* Обе страницы дабл-буфера: у них свои палитры. Через буфер в W2 —
* gfx_pal_load отдаёт указатель BIOS ($A4), а тот читает только
* #4000-#BFFF и банковую rodata не увидит. */
void pop_shadow_pal_apply(void) __banked
{
uint8_t buf[64], k;
if (!pop_shadow_kid_n) return; /* набора нет — нечего красить */
for (k = 0; k < 64; k++) buf[k] = pop_shadow_pal[k];
gfx_pal_load(0, POP_SHADOW_PAL_BASE, 16, buf);
gfx_pal_load(1, POP_SHADOW_PAL_BASE, 16, buf);
}
void pop_shadow_free(void) __banked
{
uint8_t i;
for (i = 0; i < pop_shadow_kid_n; i++) atlas_free(&pop_shadow_kid[i]);
for (i = 0; i < pop_shadow_fgt_n; i++) atlas_free(&pop_shadow_fgt[i]);
pop_shadow_kid_n = pop_shadow_fgt_n = 0;
}