Files
Sprinter-SDCC/libbgi/common/gfx_blit_cols.c
T
snark13 6582154381 PoP roomtest: clip_char (верхняя обрезка спрайта) + подстановка нажатой кнопки
Спуск Кида с кнопки (room8, кромка (0,6)) рисовался неверно: Кид просвечивал
в щель между кнопкой и ближним столбом, а ближняя рука была срезана до одного
оторванного пикселя.  Две независимые причины.

1. Не был портирован clip_char() (seg006:1749) — оригинал перед add_objtable
   обрезает спрайт персонажа сверху по y_clip[curr_row+1], когда тайл над
   головой стена или пол.  Порт: pop_clip_char_top() (pop_map.c, метрики по
   set_char_collision) + новый примитив gfx_blit_cols_part() в libbgi (блит
   column-major с пропуском skip верхних строк; обрезка сверху бесплатна —
   колонка непрерывна в ОЗУ, сдвигается только старт).  gfx_blit_cols стал
   тонкой обёрткой над ним.  kid_heal чистит уже ОБРЕЗАННЫЙ прямоугольник,
   иначе стирается кромка пола над срезом.

2. climb_overlay_tile (порт draw_floor_overlay, seg008:1E3A) выбирал ветку по
   СЫРОМУ коду тайла, а get_tile_to_draw (seg008:240) подменяет нажатую кнопку
   на floor/stuck.  Тайл-кнопка не проходил тест floor → уходил в
   draw_other_overlay, который кладёт поверх Кида ВЕСЬ тайл вместо узкой
   кромки floor_left_overlay[frame-137].  Фикс — tile_code_drawn(): одна
   подстановка на все слои (fore_only_tile/overlay_mid_tile перестали её
   дублировать, W3 −293 Б).

Проверено покадрово в MAME (шаг gv + снимок): кадры спуска 148..138 чистые,
после приземления на кнопке мусора нет.

Заодно: gfx_heal_noclip() (пара к gfx_blit_noclip; heal 11658 -> 8982 тактов)
и rest_pending в pop_trob — холостой проход по 30 тайлам только когда есть
отложенные редрои пик/кнопок (pop_process_trobs 89-111К -> 70-92К тактов).

START_ROOM временно = 8 (отладка спуска с кнопки), вернуть на 6/старт уровня.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-28 09:50:47 +03:00

30 lines
1.9 KiB
C

/*
* gfx_blit_cols — блит спрайта column-major (getimage-заголовок uint16 w,h;
* далее пиксели ПО КОЛОНКАМ: колонка 0 сверху вниз, потом колонка 1, ...)
* в (x,y) текущим банком (gfx_set_bank; 0x5C/0x58 прозрачный). Каждая
* колонка — вертикальный accel-burst (_bgi_blit_cols_raw).
*
* flip != 0 — ГОРИЗОНТАЛЬНОЕ зеркало (для направления персонажа): источник
* читается с последней колонки к первой (sstride отрицательный), правая
* колонка ложится в левый x экрана. Без CPU-реверса и без второй копии
* атласа. Зеркало происходит ВНУТРИ футпринта [x, x+w); чтобы держать
* "hot-point" персонажа на месте (как оригинал: xpos -= w), вызывающий
* при флипе подаёт x = anchor - w (см. pop_kid.c kid_draw).
*
* Клип по экрану ЕСТЬ (аналог _gfx_blit_full, но роли осей зеркальны:
* x = номер КОЛОНКИ, y = смещение ВНУТРИ колонки). sstride считается по
* ПОЛНОЙ высоте (колонки в ОЗУ лежат full_h друг от друга), длина accel-
* блока — по обрезанной. Спрайты Kid < 256 по обеим осям → нарезка на
* полосы >256 не нужна (raw принимает uint8_t w,h; 0 => 256). img вне W3.
*
* Тело (вместе с клипом) — в gfx_blit_cols_part.c: этот вызов = «весь кадр,
* без обрезки сверху».
*/
#include <stdint.h>
#include "../_bgi.h"
void gfx_blit_cols(int x, int y, const void *img, uint8_t flip)
{
gfx_blit_cols_part(x, y, img, flip, 0, 0);
}