cd_quiet: сравнение снимка без построения структуры — минус 8 016
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 <noreply@anthropic.com>
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
/* Запас вокруг габарита соседа: за кадр персонаж проходит заметно меньше
|
||||
|
||||
Reference in New Issue
Block a user