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>
This commit is contained in:
@@ -91,7 +91,18 @@ static void blit_b(atlas_t *a, uint8_t idx, int x, int ybottom)
|
||||
}
|
||||
|
||||
/* heal в room-space (со сдвигом POP_YOFF) — все heal слоя фона/loose. */
|
||||
static void heal_off(int x, int y, int w, int h) { gfx_heal(x, y + POP_YOFF, w, h); }
|
||||
static void heal_off(int x, int y, int w, int h)
|
||||
{
|
||||
int sy = y + POP_YOFF;
|
||||
/* Без клипа — линейным ядром (~2.9×, как gfx_blit_noclip): общий
|
||||
* gfx_heal платит за клип/16-бит/split, а не за пиксели (замер:
|
||||
* 11 658 тактов на heal 22×22). */
|
||||
if (x >= 0 && sy >= 0 && w > 0 && h > 0 && w < 256 && h < 256 &&
|
||||
x + w <= 320 && sy + h <= 256)
|
||||
gfx_heal_noclip(x, sy, (uint8_t)w, (uint8_t)h);
|
||||
else
|
||||
gfx_heal(x, sy, w, h);
|
||||
}
|
||||
|
||||
/* Область, куда в этом кадре рисовался ОВЕРЛЕЙ (не футпринт fore, а
|
||||
* draw_other_overlay/floor_overlay/полоса потолка). Оверлей включается
|
||||
@@ -271,6 +282,20 @@ static uint8_t tile_mod(int row, int col)
|
||||
return g_bg[row * 10 + col];
|
||||
}
|
||||
|
||||
/* Тип тайла «как он РИСУЕТСЯ» — порт подстановки нажатой кнопки из
|
||||
* get_tile_to_draw (seg008:240): opener → floor, closer → stuck, когда таймер
|
||||
* связи > 1. Любой слой, который выбирает ветку отрисовки по типу тайла,
|
||||
* обязан смотреть на ПОДСТАВЛЕННЫЙ тип (иначе кнопка, на которой стоит Kid,
|
||||
* ведёт себя как «не пол» — напр. climb-оверлей уходил в draw_other_overlay
|
||||
* и закрашивал Kid целым тайлом вместо узкой кромки floor_left_overlay). */
|
||||
static uint8_t tile_code_drawn(int row, int col)
|
||||
{
|
||||
uint8_t code = tile_code(row, col);
|
||||
if (code == 0x0F) { if ((pop_doorlink2(tile_mod(row, col)) & 0x1F) > 1) code = 1; }
|
||||
else if (code == 0x06) { if ((pop_doorlink2(tile_mod(row, col)) & 0x1F) > 1) code = 5; }
|
||||
return code;
|
||||
}
|
||||
|
||||
/* seg008.c:1255 (без FAKE_TILES): сосед — стена, если его тип == 20.
|
||||
* На кромке col0 сосед по умолчанию = стена (как render_room). */
|
||||
static uint8_t wall_modifier(int row, int col)
|
||||
@@ -682,7 +707,7 @@ void pop_torch_draw(int row, int col, uint8_t modif)
|
||||
int x = (col + 1 < 10 ? COL_XH[col + 1] : COL_XH[col] + 4) * 8 + 8;
|
||||
int yb = 63 * row + 62 - 40;
|
||||
if (modif >= 9) return;
|
||||
heal_off(x - 2, yb - 19, 22, 22);
|
||||
heal_off(x - 1, yb - 18, 18, 19);
|
||||
gfx_set_bank(GFX_BANK_SPRITE);
|
||||
pot_b((uint8_t)(modif + 1), x, yb);
|
||||
gfx_set_bank(GFX_BANK_NORMAL);
|
||||
@@ -988,12 +1013,10 @@ static int8_t y_to_row(int y) /* y_to_row_mod4 (seg006, TILE_SIZEY=
|
||||
|
||||
static void fore_only_tile(int row, int col)
|
||||
{
|
||||
uint8_t code = tile_code(row, col);
|
||||
const piece *t;
|
||||
/* Нажатая кнопка → пол/stuck (get_tile_to_draw), иначе поверх Kid лезет
|
||||
* передняя грань КНОПКИ. */
|
||||
if (code == 0x0F) { if ((pop_doorlink2(tile_mod(row, col)) & 0x1F) > 1) code = 1; }
|
||||
else if (code == 0x06) { if ((pop_doorlink2(tile_mod(row, col)) & 0x1F) > 1) code = 5; }
|
||||
uint8_t code = tile_code_drawn(row, col);
|
||||
const piece *t;
|
||||
t = &tile_table[code];
|
||||
int x = COL_XH[col] * 8;
|
||||
int dmy = 63 * row + 62;
|
||||
@@ -1055,13 +1078,24 @@ static void fore_tile(int row, int col) /* передний слой одно
|
||||
* 137..144 индексирует floor_left_overlay. */
|
||||
static const uint8_t FLOOR_LEFT_OVERLAY[8] = {32, 151, 151, 150, 150, 151, 32, 32};
|
||||
|
||||
static void other_overlay_tile(int row, int col); /* fwd (draw_floor_overlay -> else) */
|
||||
|
||||
static void climb_overlay_tile(int row, int col, uint8_t fidx)
|
||||
{
|
||||
uint8_t code = tile_code(row, col);
|
||||
/* тип — ПОДСТАВЛЕННЫЙ (нажатая кнопка = пол): иначе кромка, за которую
|
||||
* Kid спускается/подтягивается, закрашивается целым тайлом */
|
||||
uint8_t code = tile_code_drawn(row, col);
|
||||
int x, dmy, dby;
|
||||
const piece *t;
|
||||
if (code != 1 && code != 3 && code != 5 && code != 19) return; /* не floor-тайл */
|
||||
if (tile_code(row, col - 1) != 0) return; /* слева не пусто → не кромка */
|
||||
if (code != 1 && code != 3 && code != 5 && code != 19) {
|
||||
/* seg008:1E3A draw_floor_overlay: floor-оверлей рисуется только для
|
||||
* floor/pillar/stuck/torch, а для ОСТАЛЬНЫХ тайлов вызывается
|
||||
* draw_other_overlay() — иначе кнопка (opener/closer), за кромку
|
||||
* которой Kid спускается, не перекрывает его. */
|
||||
other_overlay_tile(row, col);
|
||||
return;
|
||||
}
|
||||
x = COL_XH[col] * 8;
|
||||
dmy = 63 * row + 62;
|
||||
dby = dmy + 3;
|
||||
@@ -1082,16 +1116,12 @@ static void climb_overlay_tile(int row, int col, uint8_t fidx)
|
||||
* draw_tile_base, draw_tile_anim (свои пики) и draw_tile_bottom. */
|
||||
static void overlay_mid_tile(int row, int col)
|
||||
{
|
||||
uint8_t code = tile_code(row, col);
|
||||
uint8_t lcode = tile_code(row, col - 1);
|
||||
uint8_t code = tile_code_drawn(row, col);
|
||||
uint8_t lcode = tile_code_drawn(row, col - 1);
|
||||
const piece *t;
|
||||
int x = COL_XH[col] * 8;
|
||||
int dby = 63 * row + 65;
|
||||
int dmy = dby - 3;
|
||||
if (code == 0x0F) { if ((pop_doorlink2(tile_mod(row, col)) & 0x1F) > 1) code = 1; }
|
||||
else if (code == 0x06) { if ((pop_doorlink2(tile_mod(row, col)) & 0x1F) > 1) code = 5; }
|
||||
if (lcode == 0x0F) { if ((pop_doorlink2(tile_mod(row, col - 1)) & 0x1F) > 1) lcode = 1; }
|
||||
else if (lcode == 0x06) { if ((pop_doorlink2(tile_mod(row, col - 1)) & 0x1F) > 1) lcode = 5; }
|
||||
t = &tile_table[code];
|
||||
ov_mark(x, 63 * row + 2, 64, 64); /* тайл + правый сосед (грани) */
|
||||
if (code != 20 && lcode == 1) /* draw_tile_right: только 42 */
|
||||
|
||||
Reference in New Issue
Block a user