From a9f4521ffd22368c1f5265d0f6ae74464def27d6 Mon Sep 17 00:00:00 2001 From: Alexander Petrov Date: Mon, 10 Aug 2026 10:55:01 +0300 Subject: [PATCH] =?UTF-8?q?fore-=D0=BF=D1=80=D0=BE=D1=85=D0=BE=D0=B4:=20?= =?UTF-8?q?=D1=80=D0=B0=D0=BD=D0=BD=D0=B8=D0=B9=20=D0=B2=D1=8B=D1=85=D0=BE?= =?UTF-8?q?=D0=B4=20=D0=BF=D0=BE=20=D0=BA=D0=BE=D0=B4=D1=83=20=D1=82=D0=B0?= =?UTF-8?q?=D0=B9=D0=BB=D0=B0=20+=20=D0=BA=D0=BE=D0=BD=D1=82=D0=B5=D0=BA?= =?UTF-8?q?=D1=81=D1=82=20=D1=82=D0=B0=D0=B9=D0=BB=D0=B0=20=D0=BE=D0=B4?= =?UTF-8?q?=D0=B8=D0=BD=20=D1=80=D0=B0=D0=B7=20(=D1=8D=D1=84=D1=84=D0=B5?= =?UTF-8?q?=D0=BA=D1=82=20=D0=BD=D1=83=D0=BB=D0=B5=D0=B2=D0=BE=D0=B9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Сближение с SDLPoP, замером НЕ подтвердилось — фиксирую как есть. - FORE_ANY[32]: есть ли у кода тайла хоть что-то в переднем слое. Порт ранней проверки оригинала `if (tile_table[curr_tile].fore_id == 0) return;` из начала ветки default в draw_tile_fore (seg008:0D15), расширенной нашими спецслучаями (стена 20, пики 2, чомпер 0x12, нижняя грань loose 11 — они рисуются мимо fore_id). Была в самом конце цепочки сравнений. - ft_code/ft_x/ft_dmy: контекст тайла считается один раз на тайл, как глобалы curr_tile/draw_xh/draw_main_y у load_curr_and_left_tile. Код тайла читался дважды (fore_tile и снова fore_only_tile), координаты — в каждом листе. Замер (Кид на 2,4 в щебне, MAME): pop_fore_over_char 58 764 -> 58 866, то есть в пределах шума. Ранний выход не срабатывает — в футпринте Кида тайлы почти всегда С передним слоем; снятое второе чтение кода съедено проверкой FORE_ANY и записью контекста. Отрисовка не изменилась: щебёнка блитится теми же параметрами (x=150 y=208 sx=22 w=10 h=2). Где время на самом деле: ~16 000 тактов фиксированных накладных на КАЖДЫЙ блит фона независимо от размера (atlas_image + gfx_w0_map + чтение w/h через окно 0 + арифметика клипа + unmap). Блит щебёнки 10×2 обходится в 21 168, факел 16×22 — в 31 000 при самом gfx_blit_noclip 8 706. Co-Authored-By: Claude Opus 5 --- applications/PoP/roomtest/pop_bg.c | 51 ++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/applications/PoP/roomtest/pop_bg.c b/applications/PoP/roomtest/pop_bg.c index 234c1ca..c6c40a5 100644 --- a/applications/PoP/roomtest/pop_bg.c +++ b/applications/PoP/roomtest/pop_bg.c @@ -318,15 +318,46 @@ static int8_t col_from_x(int xpos) /* get_tile_div_mod: колонка ( #define y_to_row(y) pop_y_to_row((int16_t)(y)) /* общий (pop_geom) */ +/* Контекст ТЕКУЩЕГО тайла прохода: код, левый край, база Y. Порт глобалов + * оригинала (curr_tile / draw_xh / draw_main_y, которые load_curr_and_left_tile + * ставит ОДИН раз на тайл, seg008 redraw_needed_tiles) — все рисовальщики + * читают их, а не считают заново. У нас код тайла читался дважды за тайл + * (в fore_tile и снова тут), а координаты — в каждом листе. */ +static uint8_t ft_code; +static int ft_x, ft_dmy; + +/* Есть ли у кода тайла ХОТЬ ЧТО-ТО в переднем слое. Порт ранней проверки + * оригинала — `id = tile_table[curr_tile].fore_id; if (id == 0) return;` + * в начале ветки default у draw_tile_fore (seg008:0D15), — расширенной + * нашими спецслучаями: стена (20), пики (2), чомпер (0x12) и нижняя грань + * loose (11) рисуются мимо fore_id. + * + * Была в самом КОНЦЕ цепочки: до неё успевали отработать чтение кода тайла + * и все сравнения спецслучаев. Замер в MAME: fore-проход стоил 58 764 такта + * ради одного блита 10×2, а в позиции без переднего слоя — 112 758 тактов + * и ноль блитов. */ +static const uint8_t FORE_ANY[32] = { +/* 00 empty */ 0, /* 01 floor */ 0, /* 02 spike */ 1, /* 03 pillar */ 1, +/* 04 gate */ 1, /* 05 stuck */ 0, /* 06 closebtn */ 0, /* 07 doortopf */ 1, +/* 08 bpbot */ 1, /* 09 bptop */ 1, /* 0A potion */ 1, /* 0B loose */ 1, +/* 0C dtop */ 1, /* 0D mirror */ 1, /* 0E debris */ 1, /* 0F openbtn */ 0, +/* 10 ldL */ 0, /* 11 ldR */ 0, /* 12 chomper */ 1, /* 13 torch */ 0, +/* 14 wall */ 1, /* 15 skeleton */ 0, /* 16 sword */ 0, /* 17 balcL */ 0, +/* 18 balcR */ 0, /* 19 lattpil */ 1, /* 1A lattdown */ 1, /* 1B lattsm */ 1, +/* 1C lattl */ 1, /* 1D lattr */ 1, /* 1E debristo */ 1, /* 1F — */ 0 +}; + +/* Контекст ft_* обязан быть проставлен вызывающим. */ static void fore_only_tile(int row, int col) { - /* Нажатая кнопка → пол/stuck (get_tile_to_draw), иначе поверх Kid лезет - * передняя грань КНОПКИ. */ - uint8_t code = pop_tile_code_drawn(row, col); + /* Нажатая кнопка → пол/stuck (get_tile_to_draw) — это уже учтено в ft_code + * (его ставит pop_tile_code_drawn), иначе поверх Kid лезет передняя грань + * КНОПКИ. */ + uint8_t code = ft_code; const piece *t; + int x = ft_x, dmy = ft_dmy; + if (!FORE_ANY[code]) return; /* ранний выход, как в оригинале */ t = &pop_tile_table[code]; - int x = POP_COL_XH[col] * 8; - int dmy = 63 * row + 62; if (code == 20) { pop_wall_b(POP_WALL_FRAM_MAIN[pop_wall_modifier(row, col)], x, dmy); wall_pattern(row, col, 1); @@ -375,6 +406,8 @@ static void ceil_over_kid_tile(int col) } if (code == 11) /* draw_loose(1): плита-потолок */ pop_env_b(POP_LOOSE_FRAM_BOTTOM[pop_loose_frame(pop_ceil_modif[col])], x, dby); + ft_code = pop_tile_code_drawn(-1, col); /* контекст тайла для листа */ + ft_x = x; ft_dmy = 63 * (-1) + 62; fore_only_tile(-1, col); /* draw_tile_fore */ } @@ -405,9 +438,13 @@ static void fore_tile(int row, int col) /* передний слой одно * висящего/подтягивающегося Kid видны НАД плитой, а тело уходит ЗА неё. * Без этого Kid лез на плиту «с переднего края» (комната 12: вис на * кромке loose над дырой от соседней упавшей плиты). */ - if (row >= 0 && pop_tile_code_drawn(row, col) == 11) + ft_code = pop_tile_code_drawn(row, col); /* код тайла — ОДИН раз на тайл */ + if (!FORE_ANY[ft_code]) return; /* нечего класть в передний слой */ + ft_x = POP_COL_XH[col] * 8; + ft_dmy = 63 * row + 62; + if (row >= 0 && ft_code == 11) pop_env_b(POP_LOOSE_FRAM_BOTTOM[pop_loose_frame(pop_loose_modif[row * 10 + col])], - POP_COL_XH[col] * 8, 63 * row + 65); + ft_x, ft_dmy + 3); /* draw_tile_fore (seg008:690) — ТОЛЬКО add_foretable-часть. Раньше здесь * рисовалась ещё и передняя кромка пола (bottom_id) «чтобы перекрывала * Kid», но в оригинале bottom идёт через draw_tile_bottom в backtable