CLIP-1: heal Кида и стража — линейным ядром, когда клип не нужен

kid_heal/pop_guard_heal звали gfx_heal всегда, хотя рисуют ровно тот
прямоугольник, который блит в большинстве кадров кладёт noclip-ядром.
Все три места heal (+ heal_off фона) сведены к общему pop_heal_fast.

Замер в MAME, счётчики totalcycles на входах kid_heal и kid_tick (вся
группа heal за кадр), комната 1, Кид стоит:
  клипающее ядро  26 200 тактов/кадр (149 кадров)
  noclip          15 848 тактов/кадр (239 кадров)
−10 352 такта, −39.5 %.  A/B в одном прогоне: вторая половина снята с
пропатченным в памяти условием (jr nz → jr), то есть на той же геометрии.

Размер СУММАРНО −362 Б: _CODE +17, BANK2 −116 (свободно 2708 — это тесный
банк из рисков levels_plan §5), BANK3 −263, BANK4 без изменений.

Грабли по дороге: первым заходом хелпер был static inline в pop_bg.h —
SDCC 4.5 И встраивает тело (181 Б) в каждый вызов, И оставляет копию в
каждом TU, который видит заголовок.  pop_guard_heal раздулся с ~60 до
663 Б, итого +1091 Б в _CODE и +636 Б в банке стража.  Отсюда pop_draw.c:
обычная функция в резиденте W1, из банков это прямой call без трамплина.

pop_room_clip_borders оставлен клипающим осознанно (320 не лезет в 8 бит,
гейт border_dirty редкий) — причина записана в коде.

Проверено визуально: ходьба, прыжок, спуск, позиция за решёткой шва
(straddle — там работает клипающий фолбэк) — артефактов нет.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Александр Петров
2026-08-01 21:53:30 +03:00
parent d552cbaca9
commit 1146c57544
11 changed files with 277 additions and 139 deletions
+14 -5
View File
@@ -12,6 +12,7 @@
#include "pop_kid.h"
#include "pop_guard.h" /* Guard/pop_gframe/CHARID_* — интерпретатор общий */
#include "pop_bg.h" /* POP_YOFF — вертикальное центрирование */
#include "_pop_draw.h" /* pop_onscreen_cols / pop_heal_fast */
#include "pop_map.h" /* pop_clip_char_top (clip_char) */
#include "pop_geom.h"
#include "kid_data.h"
@@ -108,7 +109,9 @@ void pop_kid_img_blit(uint8_t image, int x, int y)
h = (uint16_t)(img[2] | ((uint16_t)img[3] << 8));
/* Атласы Кида хранятся COLUMN-MAJOR (transpose_cols в pop_pack_kid —
* ради бесплатного горизонтального флипа), поэтому блит обязан быть
* колоночным. Row-major gfx_blit_noclip выдал бы марку транспонированной. */
* колоночным. Row-major gfx_blit_noclip выдал бы марку транспонированной.
* noclip БЕЗ проверки (CLIP-1): единственный вызывающий — полоса HP
* (pop_gdraw.c), у неё координаты фиксированные и заведомо на экране. */
if (w && h) gfx_blit_cols_part_noclip(x, y, img, 0, 0, 0);
gfx_w0_unmap();
}
@@ -605,14 +608,20 @@ void kid_draw_splash(void)
gfx_w0_unmap();
}
/* Восстановить фон из теневой копии на месте ПРЕДЫДУЩЕГО кадра Kid. */
/* Восстановить фон из теневой копии на месте ПРЕДЫДУЩЕГО кадра Kid.
*
* pop_heal_fast, а не голый gfx_heal: прямоугольник тут — это ровно тот
* прямоугольник, который kid_draw нарисовал noclip-ядром, то есть в
* подавляющем большинстве кадров он заведомо на экране. Клипающий путь
* остаётся для straddle (kid_render_dx = ∓140) и падения ниже поля —
* там координата реально уходит за экран. */
void kid_heal(void)
{
uint8_t p = gfx_get_draw_page();
if (kid_lvalid[p])
gfx_heal(kid_lx[p], kid_ly[p] + POP_YOFF, kid_lw[p], kid_lh[p]); /* +YOFF: центрирование */
if (kid_lvalid[p]) /* +YOFF: центрирование */
pop_heal_fast(kid_lx[p], kid_ly[p] + POP_YOFF, kid_lw[p], kid_lh[p]);
if (kid_ovalid[p])
gfx_heal(kid_ox[p], kid_oy[p] + POP_YOFF, kid_ow[p], kid_oh[p]);
pop_heal_fast(kid_ox[p], kid_oy[p] + POP_YOFF, kid_ow[p], kid_oh[p]);
kid_lvalid[p] = kid_ovalid[p] = 0;
}