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