Убраны три последних /63 %4 в pop_room.c — вызов pop_y_to_row

mob_tick_one (927) и mob_render (976/977) считали `(y+60)/63 % 4 - 1`
вручную, хотя pop_y_to_row — точный эквивалент этой формулы на всём
int16_t (включая усечение деления к нулю для отрицательных).  В asm это
были три пары __divsint+__modsint, ~16 200 тактов (3,8 % кадра) — только
пока кусок плиты в полёте, то есть в самом тяжёлом кадре.

В банке 7 теперь ноль __divsint.  Эквивалентность закреплена тестом
geom_y_to_row_matches_formula: перебор −400..400 против исходной формулы
(вызовы разбросаны по трём банкам, соблазн написать деление «по месту»
возвращается).  tests-host: [geom] 39 -> 840, все 5 наборов прошли.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-10 20:10:52 +03:00
parent ec3cca5e1e
commit 8cac51d592
3 changed files with 30 additions and 3 deletions
+3 -3
View File
@@ -924,7 +924,7 @@ static void mob_tick_one(mob_t *m, uint8_t pg)
* поверх Kid, если его тайл идёт в обходе ПОЗЖЕ тайла Kid, а при
* совпадении тайлов — если он ниже по y. */
{
int8_t mrow = (int8_t)(((m->y + 60) / 63) % 4 - 1); /* y_to_row_mod4 */
int8_t mrow = pop_y_to_row((int16_t)m->y); /* y_to_row_mod4 */
uint8_t over;
if (mrow != pop_bg_obj_row) over = (mrow < pop_bg_obj_row); /* ряды идут 2,1,0 */
else if (m->col != pop_bg_obj_col) over = (m->col > pop_bg_obj_col);
@@ -973,8 +973,8 @@ static void mob_render(mob_t *m, uint8_t pg)
* через пол + перекрыта передняя грань пола.
* Плюс ВТОРОЙ тайл — под ВЕРХОМ куска (ypos-18), пока кусок висит на
* границе рядов. Порт draw_mob (seg007:13E5). */
int8_t r = (int8_t)(((m->y + 60) / 63) % 4 - 1);
int8_t rt = (int8_t)(((m->y - 18 + 60) / 63) % 4 - 1);
int8_t r = pop_y_to_row((int16_t)m->y);
int8_t rt = pop_y_to_row((int16_t)(m->y - 18));
if (r < 0) pop_t_clip_top = POP_YOFF; /* полоса у потолка — только срез */
draw_tile(r, m->col + 1);
pop_t_clip_top = 0;