PoP roomtest: блеск лежащего меча, клинок в руке, вспышка фона

Три расхождения с оригиналом на сцене подъёма меча (комната 15):

1. Лежащий меч не блестел.  Порт animate_sword (seg007:0425) +
   start_anim_sword (seg007:087C): при входе в комнату тайлу даётся
   случайная фаза (prandom & 0x1F), каждый кадр счётчик вниз, на 0 —
   новый период 0x28..0x67.  Кадр блеска рисуется РОВНО на modif==1
   ((modif==1)+10 в draw_tile), т.е. одиночная вспышка раз в 40..103
   тика.  Перерисовка тайла — по смене видимого кадра, схемой кнопки
   (текущая страница сразу, вторая через rest-цикл).

2. В кадрах «нашёл меч» клинка не было видно.  Порт
   add_sword_to_objtable (seg006:1798): клинок — ОТДЕЛЬНЫЙ спрайт
   chtab_0 поверх Kid со смещением из sword_tbl.  Смещения в ЭКРАННЫХ
   пикселях (оригинал применяет их после calc_screen_x_coord), поэтому
   берём уже масштабированный obj_x.  Из таблицы взяты только строки
   35..42 (кадры 229..236) — бой не портирован.  Новый атлас sword.atl
   (8 спрайтов, 1.6 КБ) + палитра chtab_0 в слотах 0x80..0x8F.
   Прямоугольник heal расширяется объединением с клинком, иначе он
   оставлял след за габаритом Kid.

3. Не было вспышки фона.  do_flash = set_bg_attr(0, color) — оригинал
   подменяет НУЛЕВУЮ запись палитры, вспыхивает всё чёрное поле экрана;
   proc_get_object ставит flash_color=14, flash_time=8.  У нас gfx_pal_set
   на обе страницы.  ВАЖНО: вызов gfx_pal_set(0,0,0,0,0) пятью литералами
   ломает SDCC 4.5 (эмитит невалидный `ld hl, a`) — обёрнуто в функцию с
   параметрами.

Попутно: TROBS_MAX 24 -> 30 (как в оригинале) + при входе в комнату из
списка выбрасываются «декоративные» trob ДРУГИХ комнат (факелы/зелья/
меч анимируются только в отрисованной).  Без этого отладочный обход всех
24 комнат забивал список, и новые анимации молча не заводились.

Проверено в MAME: блеск (брейк на редрое тайла срабатывает), клинок в
руке виден, фон вспыхивает жёлтым.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-29 17:22:22 +03:00
parent 1c91c5f92a
commit e1846369ad
11 changed files with 190 additions and 6 deletions
+29 -2
View File
@@ -89,8 +89,19 @@ static uint8_t room_label_redraw;
#define OVR_MAX 8
static uint8_t ovr_room[OVR_MAX], ovr_pos[OVR_MAX], ovr_tile[OVR_MAX], ovr_cnt;
/* Поднятый предмет (меч): tilepos и счётчик «запечь пол» по страницам. */
static uint8_t item_pos, item_bake;
/* Поднятый предмет (меч): tilepos и счётчик «запечь пол» по страницам.
* flash_on — вспышка фона активна (нулевая запись палитры подменена). */
static uint8_t item_pos, item_bake, flash_on;
/* Подмена НУЛЕВОЙ записи палитры на обеих страницах (do_flash/set_bg_attr).
* Через функцию с параметрами, а не пятью литералами в месте вызова: на
* gfx_pal_set(0,0,0,0,0) SDCC 4.5 выдаёт невалидный `ld hl, a`
* (см. .sprinter-cc-roomtest/roomtest.asm) и ассемблер падает. */
static void flash_bg(uint8_t r, uint8_t g, uint8_t b)
{
gfx_pal_set(0, 0, r, g, b);
gfx_pal_set(1, 0, r, g, b);
}
static void add_tile_override(uint8_t room, uint8_t pos, uint8_t tile)
{
@@ -191,6 +202,7 @@ int main(void)
puts("pop_bg_load failed");
return 1;
}
pop_sword_load(); /* меч в руке (без него кадры 229+ без клинка) */
if (pop_kid_load(28) != 0) { /* ВСЕ страницы: бег+стоп+разворот+присед+прыжок */
puts("kid atlas load failed");
return 1;
@@ -386,12 +398,27 @@ int main(void)
item_pos = (uint8_t)(pop_item_taken - 1);
item_bake = 2; /* запечь на ОБЕИХ страницах */
add_tile_override(cur_room, item_pos, TILE_FLOOR);
pop_add_trob(cur_room, item_pos, -1); /* меч убран — блеска больше нет */
pop_item_taken = 0;
}
if (item_bake) { /* стереть спрайт меча из фона страницы */
pop_floor_bake(item_pos / 10, item_pos % 10);
item_bake--;
}
if (pop_flash_time) {
/* do_flash (seg001:0908) = set_bg_attr(0, color): оригинал подменяет
* НУЛЕВУЮ запись палитры — вспыхивает всё чёрное поле экрана.
* У нас то же самое, но правим обе страницы (у каждой своя
* палитра). color_14_brightyellow = VGA 14. */
if (!flash_on) {
flash_bg(255, 255, 85); /* color_14_brightyellow */
flash_on = 1;
}
if (--pop_flash_time == 0) {
flash_bg(0, 0, 0); /* вернуть чёрный фон */
flash_on = 0;
}
}
io_border = 4; /* зеленый */
update_kid_render_dx(); /* straddle: смещение спрайта, если kid_room≠cur_room */
kid_draw(); /* нарисовать новый кадр (детект выхода за поле) */