Замер P2 и P6: главные статьи — физика двух Char и луч видимости

Синяя фаза (286 518) разложена зондами на 12 участков, process_trobs
(89 784) — на три.

Гипотеза, с которой я входил в замер, ОТВЕРГНУТА.  Я ждал, что дорого
обходятся банковые трамплины на спецсобытиях уровней — по аналогии с
pop_clip_char_top, где трамплин ради одной проверки стоит 8 892.  На деле
три спецсобытия (skel, mouse, killed_shadow) вместе стоят 1 650: они
гейтятся внутри и на уровне 11 выходят сразу.

Настоящие статьи синей:

  физика двух Char        105 246  (61 266 Кид + 43 980 страж)
  heal двух Char           67 734
  луч видимости стража  до 37 032  (вместе с frame_timers)
  pop_ctrl_tick            18 648
  логика стража            19 932

Физика съедает 13,7 % работы кадра при том, что ОБА персонажа стоят и кадр
позы не меняется.  Цена измерена, причина нет — это отдельная позиция P2a.
Луч видимости считается каждый кадр, хотя никто не двигался: гейт по смене
позиции/комнаты — позиция P2b, ждём −30 000.  heal отдельной правки не
требует, он уйдёт вместе с P1/P3.

process_trobs: префетч кодов тайлов с маппингом окна 0 — 11 058, обход
самих trob'ов ~43 000 (pop_trob_modif зовётся банковым вызовом на КАЖДЫЙ
trob, хотя комната одна), два факела ~36 000.  Цена одного pop_pot_b
измерена отдельно: 17 346, и это единственная группа в распределении —
значит в кадре его зовут только факелы.  Пиксели пламени 16x18 — 1 716,
то есть 10 % цены.

Заодно посчитано, достижим ли период 3 растра: снять надо 338 000, а сумма
ВСЕХ известных позиций даёт 357 000, из которых 160 000 держатся на одной
(P1).  Цель достижима, но без запаса.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-19 11:05:58 +03:00
parent 6d7c1c8b6b
commit f81b30eb68
4 changed files with 101 additions and 14 deletions
+2
View File
@@ -633,6 +633,8 @@ void pop_process_trobs(uint8_t cur_room) __banked
pop_level_access_end();
}
pop_dbg_m8(); /* ЗАМЕР: префетч кодов тайлов сделан */
for (i = 0; i < trobs_count; i++) {
uint8_t room = trobs[i].room;
uint8_t tp = trobs[i].tilepos;
+10
View File
@@ -361,35 +361,45 @@ int main(void)
back = dbuf ? (uint8_t)(gfx_get_visible_page() ^ 1) : 0;
gfx_set_draw_page(back);
}
pop_dbg_m13(); /* ЗАМЕР: ввод и читы разобраны */
pop_check_skel(); /* спецсобытие ур.3: скелет встаёт */
pop_check_mouse(); /* спецсобытие ур.8: мышь жмёт кнопку */
pop_check_killed_shadow(); /* спецсобытие ур.12: смерть тени = смерть Кида */
pop_dbg_b6(); /* ЗАМЕР: три спецсобытия уровней сделаны */
pop_frame_timers(); /* timers (seg003:0735): вспышка слияния */
pop_check_can_guard_see_kid(); /* луч видимости — ДО логики персонажей */
pop_dbg_m14(); /* ЗАМЕР: спецсобытия + луч видимости */
pop_ctrl_tick(); /* ввод -> control(): смена seq */
/* Кто в этом кадре не изменился с прошлой отрисовки ЭТОЙ страницы —
* тот на ней уже нарисован правильно: ни стирать, ни рисовать заново
* не надо (DRAW-COST, контракт в pop_cdraw.h). Решение
* перепроверяется перед самой отрисовкой — тик ещё впереди. */
pop_dbg_m15(); /* ЗАМЕР: pop_ctrl_tick сделан */
skip = pop_char_skip_mask();
if (!(skip & 1)) pop_char_heal(POP_CH_KID); /* стереть прошлый кадр ЭТОЙ страницы */
if (!(skip & 2)) pop_char_heal(POP_CH_OPP); /* и прошлый кадр соперника */
/* Отражение в зеркале — свой heal: у него нет слота pop_cd и в
* skip-маске он не участвует (рисуется/стирается безусловно, живёт
* только пока Кид стоит на тайле зеркала). */
pop_dbg_m16(); /* ЗАМЕР: heal обоих персонажей сделан */
pop_mirror_heal();
pop_fore_heal(); /* + следы оверлея (шире прямоугольника Kid) */
PROF(2); /* логика (тот же синий) */
pop_dbg_m1(); /* ЗАМЕР: начало логики */
kid_tick(); /* play_seq: следующий кадр */
pop_dbg_b1(); /* ЗАМЕР: kid_tick сделан */
pop_phys_tick(); /* K3: падение/приземление/стена */
pop_dbg_b2(); /* ЗАМЕР: pop_phys_tick сделан */
pop_guard_tick(); /* логика стража — В БАНКЕ (guards.c) */
pop_dbg_b3(); /* ЗАМЕР: pop_guard_tick сделан */
pop_guard_phys_tick(); /* и его физика — та же, что у Кида (play_guard_frame) */
/* Боёвка, порядок как в play_frame (seg000:872): сначала пометить
* попадания с обеих сторон, потом применить, потом свести HP. */
pop_dbg_b4(); /* ЗАМЕР: pop_guard_phys_tick сделан */
pop_check_sword_hurting();
pop_check_sword_hurt();
pop_do_delta_hp();
pop_dbg_b5(); /* ЗАМЕР: боёвка сделана */
pop_guard_fallout(); /* страж провалился ниже комнаты — убрать (seg002:241) */
if (pop_fell_out) { /* Kid пересёк нижнюю границу комнаты */
uint8_t down = pop_room_link(cur_room, LINK_DOWN);