PoP: факелы и зелья (chtab_1) + быстрый блит фона gfx_blit_noclip

Графика chtab_1 (flame/sword/potion) — новый атлас pop_pot.atl:
- склянка зелья берётся из chtab_1 (seg008 draw_tile_fore: id 12 малая /
  13 большая при типах 2..4), а НЕ chtab_6 id 12 — res212 в VDUNGEON нет,
  каскад падал на VPALACE и рисовал кусок дворцовой декорации («мусорный
  объект» в комнате 5);
- пакуем chtab_1 целиком (id 1..23): пламя, склянки, кадры пузырька;
- MONO-блит (method_3_blit_mono, seg009:3040) красит спрайт цветом из
  ОБЩЕЙ 16-цветной палитры экрана — она добавлена в 0x30..0x3F, палитра
  chtab_1 в 0x40..0x4F; пузырёк пакуется силуэтом цвета 12 (красный),
  его маска — цвета 0;
- в env-атлас добавлено основание факела (env 146, seg008:489 — рисует
  правый сосед); в статический render_room оно не попадало.

Анимация (seg007 animate_torch/animate_potion + seg000:0B12
anim_tile_modif): при входе в комнату факелам и зельям задаётся случайная
стартовая фаза и заводится trob; факел — get_torch_frame, пламя в ячейке
ПРАВОГО соседа (xh = draw_xh+1, y = draw_main_y−40); зелье —
bubble_next_frame по младшим 3 битам модификатора (старшие 5 = тип, при
загрузке уровня modif <<= 3, seg009).  Пламя и пузырёк не запекаются в
фон: heal своей области + кадр поверх.  Скорость пламени /2 — наш
логический кадр короче игрового тика оригинала.

Скорость отрисовки (профиль в MAME, кадр = 430 080 тактов):
- замер показал, что цена блита почти НЕ зависит от размера — 13 288
  тактов на спрайт 32×3 против 4 617 у линейного спрайтового ядра без
  клипа; платим за проход gfx_blit → gfx_blit_part → _gfx_blit_full;
- в libbgi добавлен gfx_blit_noclip() — блит без клипа в ТЕКУЩЕМ банке
  (putsprite не годится: навязывает GFX_BANK_SPRITE, фону нужен
  TRANSPARENT ради ОЗУ-копии); pop_bg.blit_b уходит на него, когда
  спрайт целиком на экране и не нужен g_clip_top → ~2.9× на блит;
- W3-скобку ставит САМА libbgi: из модуля с --w3 её вызывать нельзя —
  после _bgi_begin окно W3 занято видеобанком и код вызывающего исчезает
  (проявлялось белым экраном);
- редрой шва больше не перерисовывает полосу потолка (bar начинается с
  POP_YOFF+3) — это удваивало стоимость блока при анимации решётки;
- docs/size_optimization_plan.md §7–§8: замеры, сделанное и запас
  (батчинг W3-скобки, решётка одним спрайтом, лишние блиты).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-27 20:53:04 +03:00
parent 63a3b60524
commit c127a4b0d2
16 changed files with 377 additions and 16 deletions
+35
View File
@@ -0,0 +1,35 @@
/*
* gfx_blit_noclip — блит ЦЕЛОЙ картинки getimage-формата БЕЗ клипа, в
* ТЕКУЩЕМ банке (gfx_set_bank). Быстрый вариант gfx_blit для тайловых
* движков: вызывающий гарантирует, что картинка целиком на экране.
*
* Зачем отдельная функция: gfx_blit идёт через общее ядро _gfx_blit_full
* (16-битная арифметика, клип, пересчёт src, нарезка полос >256) — замер
* в MAME (PoP roomtest, 2026-07-27): 13 288 тактов на блит спрайта 32×3,
* т.е. цена почти не зависит от размера, платим за проход по цепочке.
* Линейное спрайтовое ядро на том же спрайте — 4 617 тактов (в 2.9 раза
* быстрее): 8-битные w/h, без split, без клип-кода.
*
* От putsprite отличается тем, что НЕ навязывает GFX_BANK_SPRITE: фон
* рисуется в GFX_BANK_TRANSPARENT (0xFF не пишется, но ОЗУ-копия
* обновляется — иначе gfx_heal сотрёт нарисованное).
*
* W3-скобка ставится ЗДЕСЬ (код libbgi живёт в W1): вызывать её из
* приложения, собранного с --w3, нельзя — после _bgi_begin окно W3
* занято видеобанком и код вызывающего исчезает из адресного
* пространства (проверено: белый экран).
*
* Ограничения: w,h ≤ 255; картинка целиком в пределах экрана. Не
* подходит — зовите gfx_blit/gfx_blit_part.
*/
#include "../_bgi.h"
void gfx_blit_noclip(int x, int y, const void *img)
{
const uint8_t *p = (const uint8_t *)img;
_bgi_begin();
_gfx_blit_sprite_noclip(x, y, p + 4, (uint16_t)(p[0] | (p[1] << 8)),
p[0], p[2]);
_bgi_end();
}