PoP roomtest: fore-слой — окно клипа, кэш кладки; кадр 2.5 -> 0.78 периода
Жалоба: стойка неподвижных Кида и стража занимала больше полутора
кадровых периодов. Гипотеза «виноват __banked» ЗАМЕРОМ НЕ
ПОДТВЕРДИЛАСЬ: весь банковый вызов (трамплин + смена страницы + тело
pop_guard_tick + возврат) стоит 654 такта при бюджете кадра 430 000.
Как мерил (выборка PC бесполезна — мост MAME отвечает из фреймового
колбэка, все сэмплы падают в обработчик прерывания): breakpoint'ы MAME с
действием {printf totalcycles; g} на входах фаз главного цикла, разности
соседних меток = стоимость фазы. Плюс профилирование полосами бордюра
(make PROF=1, макрос PROF() в roomtest.c) для быстрого взгляда.
Замер комнаты 3 (Kid + страж), такты, кадр = 430 000:
fore поверх стража 431 964
fore поверх Kid 402 816 -> 78 % всей работы кадра
остальное 241 956
ИТОГО 1 076 736 = 2.5 кадра
Две причины, обе устранены:
1. Fore-слой рисовал ЦЕЛЫЕ тайлы, хотя существует ровно для того, чтобы
вернуть куски поверх спрайта — за его прямоугольником в видеопамяти и
так правильный фон. Введено ОКНО клипа (pop_fore_set_clip): спрайт
сообщает свой итоговый габарит (у Kid — с клинком, брызгами и
обрезкой clip_char), fore-проход режет по нему. Отсев трёхступенчатый:
тайл целиком (tile_in_fclip, до обращения к атласу), кусок по грубому
габариту (до gfx_w0_map — w/h лежат в EMM-странице), и точный клип в
blit_b. Для последнего добавлен libbgi-примитив
gfx_blit_part_noclip — пара к gfx_blit_noclip, но под-прямоугольник.
2. Оставшиеся 341 К после клипа оказались НЕ пикселями: 18 вызовов
pop_prandom за проход, ~10 700 тактов каждый (32-битный LCG:
__mullong ~8 000 + __moduint). Раскладка кладки тайла — чистая
функция (комната, ряд, колонка), то есть константа комнаты, а
wall_pattern пересчитывал её каждый кадр. Теперь кэшируются готовые
РЕШЕНИЯ (что рисовать и с каким смещением), 3 байта на тайл, сброс в
pop_room_draw. Порядок вызовов prandom воспроизведён один в один,
включая то, что значение метки берётся только при сработавшем условии.
Итог того же замера: fore поверх стража 37 464, поверх Kid 46 464,
кадр целиком 334 716 = 0.78 периода (было 2.5). Ускорение 3.2x, сами
fore-проходы — 10x.
Проверка отсутствия регрессии: попиксельная разность скриншотов комнат
1/2/3 до и после — отличаются ТОЛЬКО языки пламени факелов (анимация),
кладка и метки совпадают байт в байт.
Побочно: sprinter-cc научился пробрасывать -DNAME в sdcc.
Память: куча W2 1245 -> 996 Б (кэш кладки 120 Б), резидент W3 12 819 ->
14 512 (свободно 1872 Б — становится тесно), банк 1 236/16384.
ВНИМАНИЕ: make size-check показывает рост 7 программ, но эталон
docs/size_baseline.tsv отстал (последний раз принят в 484b18d, libbgi
менялась в 95c22be/c127a4b/64ce633) — к этой правке рост отношения не
имеет: новый модуль библиотеки в чужие программы не линкуется.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -62,33 +62,73 @@ static int g_clip_top;
|
||||
/* Блит ленты idx атласа a: НИЗ спрайта на ybottom, левый край x,
|
||||
* прозрачно (0xFF). w/h читаются из getimage-заголовка ленты (в W0).
|
||||
* При g_clip_top рисуем только часть кадра ниже границы (gfx_blit_part). */
|
||||
/* ОКНО FORE-СЛОЯ (экранные координаты, полуинтервал). Пока оно включено,
|
||||
* blit_b рисует только ту часть куска, что попадает в окно.
|
||||
*
|
||||
* Зачем: fore-слой существует РОВНО для того, чтобы вернуть куски тайлов
|
||||
* поверх нарисованного персонажа — за пределами его прямоугольника в
|
||||
* видеопамяти и так лежит правильный фон. А рисовал он тайлы ЦЕЛИКОМ:
|
||||
* стена (код 20) — блок 64×63 = 4032 пикселя, и таких кусков за проход
|
||||
* до девяти. Замер в MAME 2026-07-29 (комната 3, Kid + страж): проход
|
||||
* поверх Kid — 402 816 тактов, поверх стража — 431 964, вместе 78 % всей
|
||||
* работы кадра при бюджете 430 000 тактов на кадр. С окном большинство
|
||||
* кусков отсекается целиком, остальные режутся до пересечения. */
|
||||
static int fclip_x0, fclip_y0, fclip_x1, fclip_y1;
|
||||
static uint8_t fclip_on;
|
||||
|
||||
void pop_fore_set_clip(int x, int y, int w, int h)
|
||||
{
|
||||
fclip_x0 = x; fclip_y0 = y;
|
||||
fclip_x1 = x + w; fclip_y1 = y + h;
|
||||
}
|
||||
|
||||
static void blit_b(atlas_t *a, uint8_t idx, int x, int ybottom)
|
||||
{
|
||||
const uint8_t *img;
|
||||
uint16_t w, h;
|
||||
int top;
|
||||
int top, dx, dy, dw, dh, sx = 0, sy = 0;
|
||||
if (idx >= a->count)
|
||||
return;
|
||||
/* Грубый отсев ДО маппинга страницы: реальные w/h лежат в заголовке
|
||||
* ленты, то есть в EMM-странице, и чтобы их прочитать, надо сделать
|
||||
* gfx_w0_map. Берём заведомо больший габарит (кадры фона не крупнее
|
||||
* 64×64) и, если он не задевает окно, уходим не заплатив ни за
|
||||
* atlas_image, ни за map/unmap. */
|
||||
if (fclip_on &&
|
||||
(x >= fclip_x1 || x + 64 <= fclip_x0 ||
|
||||
ybottom + POP_YOFF + 1 <= fclip_y0 ||
|
||||
ybottom + POP_YOFF - 64 >= fclip_y1))
|
||||
return;
|
||||
img = (const uint8_t *)atlas_image(a, idx);
|
||||
gfx_w0_map(a->page);
|
||||
w = (uint16_t)(img[0] | ((uint16_t)img[1] << 8));
|
||||
h = (uint16_t)(img[2] | ((uint16_t)img[3] << 8));
|
||||
top = ybottom - (int)h + 1 + POP_YOFF; /* +YOFF: центрирование */
|
||||
if (w && h) {
|
||||
if (g_clip_top && top < g_clip_top) {
|
||||
int sy = g_clip_top - top; /* пропустить верхние строки */
|
||||
if (sy < (int)h)
|
||||
gfx_blit_part(x, g_clip_top, img, 0, sy, (int)w, (int)h - sy);
|
||||
} else if (x >= 0 && top >= 0 && w < 256 && h < 256 &&
|
||||
x + (int)w <= 320 && top + (int)h <= 256) {
|
||||
/* Спрайт целиком на экране — линейное ядро без клипа: ~2.9×
|
||||
* быстрее (замер: 4617 против 13288 тактов на спрайт 32×3;
|
||||
* общее ядро gfx_blit платит за клип/16-бит/split, а не за
|
||||
* пиксели). W3-скобку ставит сама libbgi: из кода, собранного
|
||||
* с --w3, её вызывать нельзя (окно W3 уходит под видеобанк). */
|
||||
gfx_blit_noclip(x, top, img);
|
||||
dx = x; dy = top; dw = (int)w; dh = (int)h;
|
||||
if (g_clip_top && dy < g_clip_top) { /* полоса у потолка */
|
||||
sy = g_clip_top - dy; dy = g_clip_top; dh -= sy;
|
||||
}
|
||||
if (fclip_on) { /* окно fore-слоя */
|
||||
if (dx < fclip_x0) { int d = fclip_x0 - dx; sx += d; dx += d; dw -= d; }
|
||||
if (dy < fclip_y0) { int d = fclip_y0 - dy; sy += d; dy += d; dh -= d; }
|
||||
if (dx + dw > fclip_x1) dw = fclip_x1 - dx;
|
||||
if (dy + dh > fclip_y1) dh = fclip_y1 - dy;
|
||||
}
|
||||
if (w && h && dw > 0 && dh > 0) {
|
||||
/* Целиком на экране — линейное ядро без клипа: ~2.9× быстрее
|
||||
* (замер: 4617 против 13288 тактов на спрайт 32×3; общее ядро
|
||||
* gfx_blit платит за клип/16-бит/split, а не за пиксели).
|
||||
* W3-скобку ставит сама libbgi: из кода, собранного с --w3, её
|
||||
* вызывать нельзя (окно W3 уходит под видеобанк). */
|
||||
if (dx >= 0 && dy >= 0 && dw < 256 && dh < 256 &&
|
||||
dx + dw <= 320 && dy + dh <= 256 && w < 256) {
|
||||
if (sx == 0 && sy == 0 && dw == (int)w && dh == (int)h)
|
||||
gfx_blit_noclip(dx, dy, img);
|
||||
else
|
||||
gfx_blit_part_noclip(dx, dy, img, (uint8_t)sx, (uint8_t)sy,
|
||||
(uint8_t)dw, (uint8_t)dh);
|
||||
} else {
|
||||
gfx_blit(x, top, img); /* край экрана — с клипом */
|
||||
gfx_blit_part(dx, dy, img, sx, sy, dw, dh); /* край экрана — с клипом */
|
||||
}
|
||||
}
|
||||
gfx_w0_unmap();
|
||||
@@ -339,64 +379,134 @@ static void draw_right_mark(uint16_t dv, int arg1, int row, int col)
|
||||
}
|
||||
|
||||
/* ---- wall_pattern (seg008.c:1928, dungeon-ветка) ------------------- */
|
||||
static void wall_pattern(int row, int col, int which_part)
|
||||
{
|
||||
int xh = COL_XH[col];
|
||||
int dby = 63 * row + 65;
|
||||
unsigned long saved = rnd_seed;
|
||||
uint16_t mid_div, mid_off, bot_div, bot_off;
|
||||
uint8_t bg;
|
||||
/* КЭШ РАСКЛАДКИ КЛАДКИ. Серия prandom для тайла зависит только от
|
||||
* (комната, ряд, колонка) — пока мы в комнате, это КОНСТАНТА. А
|
||||
* wall_pattern зовётся из fore-слоя КАЖДЫЙ кадр, и на Z80 это самая
|
||||
* дорогая вещь в кадре: замер в MAME 2026-07-29 (комната 3) — 18 вызовов
|
||||
* pop_prandom за один fore-проход, ~10 700 тактов каждый (32-битный LCG:
|
||||
* __mullong ~8 000 + __moduint), то есть 193 К из 341 К всего прохода при
|
||||
* бюджете кадра ~430 К. Кэшируем не сид, а ГОТОВЫЕ РЕШЕНИЯ (что рисовать
|
||||
* и с каким смещением) — тогда в кадре не остаётся ни одного prandom.
|
||||
*
|
||||
* Порядок вызовов prandom воспроизведён один в один, включая то, что
|
||||
* значение метки берётся ТОЛЬКО когда сработало её условие: иначе
|
||||
* последовательность разъедется и кладка станет другой. which_part=0
|
||||
* использует префикс той же серии, поэтому кэш общий.
|
||||
*
|
||||
* Упаковка: wp_a = mid_div | mid_off<<1 | bot_div<<4 | bot_off<<5;
|
||||
* wp_b = rndblk | right<<1 | right_val<<2 | left<<4 | left_val<<5.
|
||||
* Индекс — (row+1)*10+col, ряды −1..2. */
|
||||
#define WP_N 40
|
||||
static uint8_t wp_a[WP_N], wp_b[WP_N], wp_ok[WP_N];
|
||||
|
||||
static void wall_pattern_reset(void) /* смена комнаты — сид другой */
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < WP_N; i++) wp_ok[i] = 0;
|
||||
}
|
||||
|
||||
/* Выходы wall_rnd — в файловых статиках: возвращать девять значений
|
||||
* через указатели на Z80 дороже самой функции. */
|
||||
static uint8_t wr_mid_div, wr_mid_off, wr_bot_div, wr_bot_off;
|
||||
static uint8_t wr_rndblk, wr_right, wr_rightv, wr_left, wr_leftv;
|
||||
|
||||
static void wall_rnd(int row, int col)
|
||||
{
|
||||
/* Кэшируем только штатную сетку: колонка вне 0..9 дала бы индекс
|
||||
* соседнего РЯДА и чужую раскладку (тихий баг вместо промаха). */
|
||||
int idx = (col >= 0 && col < 10) ? (row + 1) * 10 + col : -1;
|
||||
uint8_t a, b, bg;
|
||||
unsigned long saved;
|
||||
if (idx >= 0 && idx < WP_N && wp_ok[idx]) {
|
||||
a = wp_a[idx]; b = wp_b[idx];
|
||||
wr_mid_div = (uint8_t)(a & 1); wr_mid_off = (uint8_t)((a >> 1) & 7);
|
||||
wr_bot_div = (uint8_t)((a >> 4) & 1); wr_bot_off = (uint8_t)((a >> 5) & 7);
|
||||
wr_rndblk = (uint8_t)(b & 1);
|
||||
wr_right = (uint8_t)((b >> 1) & 1); wr_rightv = (uint8_t)((b >> 2) & 3);
|
||||
wr_left = (uint8_t)((b >> 4) & 1); wr_leftv = (uint8_t)((b >> 5) & 7);
|
||||
return;
|
||||
}
|
||||
saved = rnd_seed;
|
||||
/* Верхняя полоса (row<0): SDLPoP рисует её как ряд 2 комнаты сверху
|
||||
* (drawn_row=2 для seed, draw_main_y=-1 для позиции) — seed по row 2. */
|
||||
rnd_seed = (unsigned long)(g_room + TBL_LINE[row < 0 ? 2 : row] + col);
|
||||
prandom(1); /* сброс */
|
||||
mid_div = prandom(1);
|
||||
mid_off = prandom(4);
|
||||
bot_div = prandom(1);
|
||||
bot_off = prandom(4);
|
||||
wr_mid_div = (uint8_t)prandom(1);
|
||||
wr_mid_off = (uint8_t)prandom(4);
|
||||
wr_bot_div = (uint8_t)prandom(1);
|
||||
wr_bot_off = (uint8_t)prandom(4);
|
||||
wr_rndblk = wr_right = wr_left = 0;
|
||||
wr_rightv = wr_leftv = 0;
|
||||
bg = wall_modifier(row, col);
|
||||
if (bg == 3) { /* WWW */
|
||||
wr_rndblk = (uint8_t)(prandom(4) == 0);
|
||||
if (prandom(4) == 0) { wr_right = 1; wr_rightv = (uint8_t)prandom(3); }
|
||||
if (prandom(4) == 0) { wr_left = 1; wr_leftv = (uint8_t)prandom(4); }
|
||||
} else if (bg == 0) { /* SWS */
|
||||
if (prandom(6) == 0) { wr_left = 1; wr_leftv = (uint8_t)prandom(1); }
|
||||
} else if (bg == 1) { /* SWW */
|
||||
wr_rndblk = (uint8_t)(prandom(4) == 0);
|
||||
if (prandom(4) == 0) { wr_right = 1; wr_rightv = (uint8_t)prandom(3); }
|
||||
if (prandom(4) == 0) { wr_left = 1; wr_leftv = (uint8_t)prandom(3); }
|
||||
} else { /* WWS (bg==2) */
|
||||
if (prandom(4) == 0) { wr_right = 1; wr_rightv = (uint8_t)(prandom(1) + 2); }
|
||||
if (prandom(4) == 0) { wr_left = 1; wr_leftv = (uint8_t)prandom(4); }
|
||||
}
|
||||
rnd_seed = saved;
|
||||
if (idx >= 0 && idx < WP_N) {
|
||||
wp_a[idx] = (uint8_t)(wr_mid_div | (wr_mid_off << 1) |
|
||||
(wr_bot_div << 4) | (wr_bot_off << 5));
|
||||
wp_b[idx] = (uint8_t)(wr_rndblk | (wr_right << 1) | (wr_rightv << 2) |
|
||||
(wr_left << 4) | (wr_leftv << 5));
|
||||
wp_ok[idx] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- wall_pattern (seg008.c:1928, dungeon-ветка) ------------------- */
|
||||
static void wall_pattern(int row, int col, int which_part)
|
||||
{
|
||||
int xh = COL_XH[col];
|
||||
int dby = 63 * row + 65;
|
||||
uint8_t bg = wall_modifier(row, col);
|
||||
|
||||
wall_rnd(row, col);
|
||||
if (bg == 3) { /* WWW */
|
||||
if (which_part) {
|
||||
if (prandom(4) == 0)
|
||||
if (wr_rndblk)
|
||||
wall_b(RES_WALL_RNDBLOCK, xh * 8, dby - 42);
|
||||
wall_b((uint8_t)(RES_WALL_DIVIDER1 + mid_div), (xh + 1) * 8 + mid_off, dby - 21);
|
||||
wall_b((uint8_t)(RES_WALL_DIVIDER1 + wr_mid_div), (xh + 1) * 8 + wr_mid_off, dby - 21);
|
||||
}
|
||||
wall_b((uint8_t)(RES_WALL_DIVIDER1 + bot_div), xh * 8 + bot_off, dby);
|
||||
wall_b((uint8_t)(RES_WALL_DIVIDER1 + wr_bot_div), xh * 8 + wr_bot_off, dby);
|
||||
if (which_part) {
|
||||
if (prandom(4) == 0)
|
||||
draw_right_mark(prandom(3), mid_off, row, col);
|
||||
if (prandom(4) == 0)
|
||||
draw_left_mark(prandom(4), mid_off - mid_div, bot_off - bot_div, row, col);
|
||||
if (wr_right)
|
||||
draw_right_mark(wr_rightv, wr_mid_off, row, col);
|
||||
if (wr_left)
|
||||
draw_left_mark(wr_leftv, wr_mid_off - wr_mid_div, wr_bot_off - wr_bot_div, row, col);
|
||||
}
|
||||
} else if (bg == 0) { /* SWS */
|
||||
if (which_part) {
|
||||
if (prandom(6) == 0)
|
||||
draw_left_mark(prandom(1), mid_off - mid_div, bot_off - bot_div, row, col);
|
||||
}
|
||||
if (which_part && wr_left)
|
||||
draw_left_mark(wr_leftv, wr_mid_off - wr_mid_div, wr_bot_off - wr_bot_div, row, col);
|
||||
} else if (bg == 1) { /* SWW */
|
||||
if (which_part) {
|
||||
if (prandom(4) == 0)
|
||||
if (wr_rndblk)
|
||||
wall_b(RES_WALL_RNDBLOCK, xh * 8, dby - 42);
|
||||
wall_b((uint8_t)(RES_WALL_DIVIDER1 + mid_div), (xh + 1) * 8 + mid_off, dby - 21);
|
||||
if (prandom(4) == 0)
|
||||
draw_right_mark(prandom(3), mid_off, row, col);
|
||||
if (prandom(4) == 0)
|
||||
draw_left_mark(prandom(3), mid_off - mid_div, bot_off - bot_div, row, col);
|
||||
wall_b((uint8_t)(RES_WALL_DIVIDER1 + wr_mid_div), (xh + 1) * 8 + wr_mid_off, dby - 21);
|
||||
if (wr_right)
|
||||
draw_right_mark(wr_rightv, wr_mid_off, row, col);
|
||||
if (wr_left)
|
||||
draw_left_mark(wr_leftv, wr_mid_off - wr_mid_div, wr_bot_off - wr_bot_div, row, col);
|
||||
}
|
||||
} else { /* WWS (bg==2) */
|
||||
if (which_part)
|
||||
wall_b((uint8_t)(RES_WALL_DIVIDER1 + mid_div), (xh + 1) * 8 + mid_off, dby - 21);
|
||||
wall_b((uint8_t)(RES_WALL_DIVIDER1 + bot_div), xh * 8 + bot_off, dby);
|
||||
wall_b((uint8_t)(RES_WALL_DIVIDER1 + wr_mid_div), (xh + 1) * 8 + wr_mid_off, dby - 21);
|
||||
wall_b((uint8_t)(RES_WALL_DIVIDER1 + wr_bot_div), xh * 8 + wr_bot_off, dby);
|
||||
if (which_part) {
|
||||
if (prandom(4) == 0)
|
||||
draw_right_mark((uint16_t)(prandom(1) + 2), mid_off, row, col);
|
||||
if (prandom(4) == 0)
|
||||
draw_left_mark(prandom(4), mid_off - mid_div, bot_off - bot_div, row, col);
|
||||
if (wr_right)
|
||||
draw_right_mark(wr_rightv, wr_mid_off, row, col);
|
||||
if (wr_left)
|
||||
draw_left_mark(wr_leftv, wr_mid_off - wr_mid_div, wr_bot_off - wr_bot_div, row, col);
|
||||
}
|
||||
}
|
||||
rnd_seed = saved;
|
||||
}
|
||||
|
||||
/* topright тайла снизу-слева (seg008.c:410). */
|
||||
@@ -1088,6 +1198,7 @@ void pop_room_draw(uint8_t room_num,
|
||||
{
|
||||
int row, col;
|
||||
g_room = room_num;
|
||||
wall_pattern_reset(); /* кэш кладки привязан к номеру комнаты */
|
||||
g_fg = fg; g_bg = bg;
|
||||
g_lfg = lcol_fg; g_lbg = lcol_bg;
|
||||
|
||||
@@ -1177,8 +1288,25 @@ static void ceil_over_kid_tile(int col)
|
||||
fore_only_tile(-1, col); /* draw_tile_fore */
|
||||
}
|
||||
|
||||
/* Пересекается ли габарит тайла с окном fore-слоя. Шаг тайла — 32 px
|
||||
* (COL_XH[col]*8 = col*32), куски выходят вправо максимум на +8 (дивайдеры
|
||||
* и метки рисуются в ячейке правого соседа) и вверх на 42+высота кадра.
|
||||
* Даёт отсев ЦЕЛОГО тайла ДО обращения к атласу: спрайт 27..40 px шириной
|
||||
* задевает не все тайлы футпринта, а платили за каждый (atlas_image +
|
||||
* gfx_w0_map + разбор заголовка на КАЖДЫЙ кусок). */
|
||||
static uint8_t tile_in_fclip(int row, int col)
|
||||
{
|
||||
int x0, y0;
|
||||
if (!fclip_on) return 1;
|
||||
x0 = COL_XH[col] * 8;
|
||||
y0 = POP_YOFF + 63 * row;
|
||||
return (uint8_t)(x0 < fclip_x1 && x0 + 40 > fclip_x0 &&
|
||||
y0 - 8 < fclip_y1 && y0 + 70 > fclip_y0);
|
||||
}
|
||||
|
||||
static void fore_tile(int row, int col) /* передний слой одного тайла */
|
||||
{
|
||||
if (!tile_in_fclip(row, col)) return;
|
||||
/* draw_loose (seg008:0A38) — единственный кусок ТАЙЛА, который оригинал
|
||||
* кладёт В ОБЕ таблицы БЕЗУСЛОВНО: нижняя грань loose-плиты идёт и в
|
||||
* backtable, и в foretable. Значит передняя грань плиты рисуется ПОВЕРХ
|
||||
@@ -1211,7 +1339,9 @@ static void climb_overlay_tile(int row, int col, uint8_t fidx)
|
||||
{
|
||||
/* тип — ПОДСТАВЛЕННЫЙ (нажатая кнопка = пол): иначе кромка, за которую
|
||||
* Kid спускается/подтягивается, закрашивается целым тайлом */
|
||||
uint8_t code = tile_code_drawn(row, col);
|
||||
uint8_t code;
|
||||
if (!tile_in_fclip(row, col)) return;
|
||||
code = tile_code_drawn(row, col);
|
||||
int x, dmy, dby;
|
||||
const piece *t;
|
||||
if (tile_code(row, col - 1) != 0) return; /* слева не пусто → не кромка */
|
||||
@@ -1301,8 +1431,9 @@ static void overlay_mid_tile(int row, int col)
|
||||
* сразу), поэтому порядок эмулируется явной проверкой. */
|
||||
static void other_overlay_tile(int row, int col)
|
||||
{
|
||||
uint8_t code = tile_code(row, col);
|
||||
uint8_t left;
|
||||
uint8_t code, left;
|
||||
if (!tile_in_fclip(row, col)) return;
|
||||
code = tile_code(row, col);
|
||||
/* Пустой тайл НЕ окклюдирует: у него нет тела пола/стены, а draw_tile для
|
||||
* него рисует лишь ФОНОВУЮ сетку (BLUELINE «силуэт кладки» — правая грань
|
||||
* пустого соседа). В оригинале она уходит в y-сортируемый midtable и
|
||||
@@ -1374,6 +1505,7 @@ void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
||||
int8_t dir, uint8_t frame, uint8_t action)
|
||||
{
|
||||
int8_t cL, cR, cLraw, rT, rB, rTraw, r, c;
|
||||
fclip_on = 1; /* окно = прямоугольник спрайта */
|
||||
char_footprint(obj_x, obj_y, w, h, dir);
|
||||
cL = fp_cL; cR = fp_cR; cLraw = fp_cLraw;
|
||||
rT = fp_rT; rB = fp_rB; rTraw = fp_rTraw;
|
||||
@@ -1444,6 +1576,7 @@ void pop_fore_over_kid(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
||||
g_clip_top = 0;
|
||||
}
|
||||
gfx_set_bank(GFX_BANK_NORMAL);
|
||||
fclip_on = 0;
|
||||
}
|
||||
|
||||
/* Передние грани тайлов поверх ПРОИЗВОЛЬНОГО персонажа (страж, дальше —
|
||||
@@ -1460,6 +1593,7 @@ void pop_fore_over_char(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
||||
int8_t dir)
|
||||
{
|
||||
int8_t r, c;
|
||||
fclip_on = 1; /* окно = прямоугольник спрайта */
|
||||
char_footprint(obj_x, obj_y, w, h, dir);
|
||||
gfx_set_bank(GFX_BANK_SPRITE);
|
||||
for (r = fp_rT; r <= fp_rB; r++)
|
||||
@@ -1474,4 +1608,5 @@ void pop_fore_over_char(int obj_x, int obj_y, uint16_t w, uint16_t h,
|
||||
g_clip_top = 0;
|
||||
}
|
||||
gfx_set_bank(GFX_BANK_NORMAL);
|
||||
fclip_on = 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user