Инвентаризация делений по .asm: убраны три, остальные разобраны
Обход всех сгенерированных .asm (awk по `call __div/__mod/__mul` с привязкой к строке исходника) нашёл 31 вызов в 9 модулях. Три из них были в горячем пути: - pop_cdraw.c calc_screen_x_coord: `x * 8 / 7` -> __divsint, 2 400 тактов на ПЕРСОНАЖА КАЖДЫЙ КАДР (два вызова при живом сопернике). Заменено тождеством 8x/7 == x + x/7 плюс таблица DIV7[256] в банке 4 — резидент не тронут, обычный диапазон (obj_x 0..252 при x_bump 58..184) покрыт целиком, деление осталось только хвостом для шва (render_dx = ∓140). - pop_guard.c guard_col_from_x: /14 и %14 звались БЕЗУСЛОВНО, мимо POP_TILE_DIV — единственное 16-битное деление без подключённой таблицы. - pop_trob.c animate_chomper: `tp / 10` на чомпера каждый кадр, при том что TP_ROW/TP_COL лежали в этом же файле, но ниже по тексту. Таблицы подняты выше чомперов. Остальные 25 оставлены осознанно и расписаны в TASKS_OPEN.md: хвосты за таблицей (x вне 0..255 = персонаж в соседней комнате), намеренный медленный хвост pop_y_to_row, недостижимая ветка pop_rnd_fit и холодные места (вход стража, старт уровня, читы, имя файла, отладочный HUD). В банках 4, 6, 7 теперь ноль __div*. Тождество 8x/7 закреплено тестом geom_mul8div7_identity (перебор −420..700), таблица DIV7 сверена с x//7. tests-host: [geom] 840 -> 1961, все 5 наборов прошли. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -110,6 +110,46 @@ void pop_guard_free(void) __banked
|
||||
g_ok = 0;
|
||||
}
|
||||
|
||||
/* ---- calc_screen_x_coord (seg008:2602) БЕЗ деления ------------------- *
|
||||
*
|
||||
* Логическая X (280 шир = 28px/тайл) -> экранная (320 = 32px/тайл): ×8/7.
|
||||
* SDLPoP пишет это как `logical_x*320/280`, у нас SDCC разворачивал в
|
||||
* `__divsint` — 2 400 тактов на вызов, и зовётся оно на КАЖДОГО персонажа
|
||||
* КАЖДЫЙ кадр (последнее деление, остававшееся в горячем пути).
|
||||
*
|
||||
* Тождество: 8x/7 == x + x/7. Оно ТОЧНОЕ в целых, потому что 7x делится
|
||||
* нацело: floor((7x+x)/7) = x + floor(x/7); для отрицательных с усечением
|
||||
* к нулю — тоже (проверено перебором в tests-host).
|
||||
*
|
||||
* Таблица кроет 0..255 — это ВЕСЬ обычный случай, а не «частый»:
|
||||
* x_bump[5..14] = 58..184, то есть у персонажа в отрисованной комнате
|
||||
* obj_x = 2*fwd − 116 лежит в 0..252. Медленный хвост остаётся для шва,
|
||||
* где render_dx уводит X на ∓140. */
|
||||
static const uint8_t DIV7[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2,
|
||||
2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
|
||||
4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6,
|
||||
6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 9,
|
||||
9, 9, 9, 9, 9, 9,10,10,10,10,10,10,10,11,11,11,
|
||||
11,11,11,11,12,12,12,12,12,12,12,13,13,13,13,13,
|
||||
13,13,14,14,14,14,14,14,14,15,15,15,15,15,15,15,
|
||||
16,16,16,16,16,16,16,17,17,17,17,17,17,17,18,18,
|
||||
18,18,18,18,18,19,19,19,19,19,19,19,20,20,20,20,
|
||||
20,20,20,21,21,21,21,21,21,21,22,22,22,22,22,22,
|
||||
22,23,23,23,23,23,23,23,24,24,24,24,24,24,24,25,
|
||||
25,25,25,25,25,25,26,26,26,26,26,26,26,27,27,27,
|
||||
27,27,27,27,28,28,28,28,28,28,28,29,29,29,29,29,
|
||||
29,29,30,30,30,30,30,30,30,31,31,31,31,31,31,31,
|
||||
32,32,32,32,32,32,32,33,33,33,33,33,33,33,34,34,
|
||||
34,34,34,34,34,35,35,35,35,35,35,35,36,36,36,36,
|
||||
};
|
||||
|
||||
static int scr_x(int x)
|
||||
{
|
||||
if ((unsigned int)x < 256u) return x + DIV7[x];
|
||||
return x * 8 / 7;
|
||||
}
|
||||
|
||||
/* Добавить накладной спрайт (клинок / брызги) в overlay-прямоугольник
|
||||
* страницы. Оба мелкие и в одном кадре встречаются редко — их объединение
|
||||
* дешевле третьего heal-слота. */
|
||||
@@ -314,7 +354,7 @@ static void cd_splash(pop_cdraw_t *s, uint8_t who, const atlas_t *pages,
|
||||
} else {
|
||||
qy -= (who == POP_CH_KID) ? 15 : 11;
|
||||
}
|
||||
qx = (qx + fw) * 8 / 7; /* calc_screen_x_coord */
|
||||
qx = scr_x(qx + fw); /* calc_screen_x_coord */
|
||||
img = (const uint8_t *)atlas_image(ap, aidx);
|
||||
gfx_w0_map(ap->page);
|
||||
w = (uint16_t)(img[0] | ((uint16_t)img[1] << 8));
|
||||
@@ -395,8 +435,9 @@ void pop_char_draw(uint8_t who) __banked
|
||||
s->fpx = fp_x; s->fpy = obj_y;
|
||||
/* seg008 calc_screen_x_coord: логическая X (280 шир = 28px/тайл) ->
|
||||
* экран (320 шир = 32px/тайл), ×320/280 = ×8/7. БЕЗ этого персонаж
|
||||
* уезжает влево от тайлов тем сильнее, чем правее. */
|
||||
obj_x = obj_x * 8 / 7;
|
||||
* уезжает влево от тайлов тем сильнее, чем правее. Через scr_x —
|
||||
* таблицей, без __divsint (см. шапку DIV7). */
|
||||
obj_x = scr_x(obj_x);
|
||||
|
||||
page = (uint8_t)(fr->image >> 3);
|
||||
idx = (uint8_t)(fr->image & 7);
|
||||
|
||||
Reference in New Issue
Block a user