From 379c5130875be8c373d7a1a9e02f835d6956f7dc Mon Sep 17 00:00:00 2001 From: Alexander Petrov Date: Wed, 19 Aug 2026 16:33:31 +0300 Subject: [PATCH] =?UTF-8?q?cd=5Fquiet:=20=D1=81=D1=80=D0=B0=D0=B2=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=D0=BD=D0=B8=D0=BC=D0=BA=D0=B0?= =?UTF-8?q?=20=D0=B1=D0=B5=D0=B7=20=D0=BF=D0=BE=D1=81=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=82?= =?UTF-8?q?=D1=83=D1=80=D1=8B=20=E2=80=94=20=D0=BC=D0=B8=D0=BD=D1=83=D1=81?= =?UTF-8?q?=208=20016?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cd_sig_make СТРОИТ структуру из тринадцати полей в стековом кадре (то есть через -n(ix)), и только потом шёл побайтовый цикл сравнения. А зовётся проверка четыре раза за кадр: pop_char_skip_mask дважды, и в ней по два слота. Новый cd_sig_same сравнивает поля прямо с источником, с ранним выходом на первом расхождении — у двигающегося персонажа это обычно первое же поле. cd_sig_make остался: он нужен pop_char_draw, чтобы снимок записать. Замер 11/15, лёгкая позиция: участок «mob_draw + guard_over_kid + skip_mask» 47 883 -> 43 875, циан 59 265 -> 55 257, синяя 223 902 -> 219 753, работа кадра 464 796 -> 456 780. Co-Authored-By: Claude Opus 5 --- applications/PoP/roomtest/pop_cdraw.c | 37 +++++++++++++++++++++------ 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/applications/PoP/roomtest/pop_cdraw.c b/applications/PoP/roomtest/pop_cdraw.c index 8db6b05..ff6bf55 100644 --- a/applications/PoP/roomtest/pop_cdraw.c +++ b/applications/PoP/roomtest/pop_cdraw.c @@ -344,6 +344,34 @@ static void cd_sig_make(uint8_t who, cd_sig_t *g) g->dx = pop_cd[who].render_dx; } +/* Совпадает ли снимок страницы с ТЕКУЩИМ состоянием персонажа. + * + * Отдельно от cd_sig_make намеренно: тот СТРОИТ структуру, и для проверки + * это лишняя работа — тринадцать записей в стековый кадр (а значит через + * `-n(ix)`), после которых идёт побайтовый цикл сравнения. А зовут проверку + * четыре раза за кадр: pop_char_skip_mask дважды, и в ней по два слота. + * Здесь сравниваем поля прямо с источником, и первое же расхождение + * заканчивает работу — у ДВИГАЮЩЕГОСЯ персонажа это обычно первое поле. */ +static uint8_t cd_sig_same(uint8_t who, uint8_t p) +{ + const pop_char_t *ch = (who == POP_CH_KID) ? &Kid : &Guard; + const cd_sig_t *g = &cd_sig[who][p]; + if (g->frame != ch->frame) return 0; + if (g->x != ch->x) return 0; + if (g->y != ch->y) return 0; + if (g->dir != ch->direction) return 0; + if (g->action != ch->action) return 0; + if (g->ccol != ch->curr_col) return 0; + if (g->crow != ch->curr_row) return 0; + if (g->sword != ch->sword) return 0; + if (g->charid != ch->charid) return 0; + if (g->room != ch->room) return 0; + if (g->hurt != (uint8_t)((who == POP_CH_KID) ? pop_kid_hurt : pop_guard_hurt)) + return 0; + if (g->dx != pop_cd[who].render_dx) return 0; + return 1; +} + /* Габарит слота на странице: спрайт + накладные (клинок/брызги). y — * КОМНАТНЫЙ (как в pop_cd), перевод в экранный делает вызывающий. */ static void cd_bbox(uint8_t who, uint8_t p, int *x0, int *y0, int *x1, int *y1) @@ -366,9 +394,6 @@ static void cd_bbox(uint8_t who, uint8_t p, int *x0, int *y0, int *x1, int *y1) * ни перепроверяй за кадр. */ static uint8_t cd_quiet(uint8_t who, uint8_t p) { - cd_sig_t g; - const uint8_t *a, *b; - uint8_t i; /* Соперника на сцене нет и на ЭТОЙ странице от него ничего не осталось — * стирать и рисовать нечего, слот «тихий». Без этого пустой слот каждый * кадр честно проходил heal + вход в pop_char_draw + fore-проход и стоил @@ -401,11 +426,7 @@ static uint8_t cd_quiet(uint8_t who, uint8_t p) return 0; } } - cd_sig_make(who, &g); - a = (const uint8_t *)&g; b = (const uint8_t *)&cd_sig[who][p]; - for (i = 0; i < sizeof(cd_sig_t); i++) - if (*a++ != *b++) return 0; - return 1; + return cd_sig_same(who, p); } /* Запас вокруг габарита соседа: за кадр персонаж проходит заметно меньше