Оптимизация: логический кадр уложился в бюджет, цикл 4 растровых кадра -> 3
Главный цикл спейсится тремя gfx_wait_vsync, поэтому работа сверх 430 000 тактов стоит сразу целый лишний растровый кадр. Было 470 964, стало ~425 600 — игра быстрее на треть (16,7 логических кадров/с против 12,5). - pop_y_to_row: цепочка сравнений вместо (y+60)/63%4-1. ВАЖНО: медленный хвост вынесен в ОТДЕЛЬНУЮ функцию — SDCC видит одинаковое выражение в двух ветках и поднимает деление в вершину, быстрые возвраты не спасают. - col_from_x (pop_bg) и get_tile_div_mod (pop_map) — общие резидентные таблицы POP_TILE_DIV/POP_TILE_MOD в pop_tile.c (const банка из чужого банка не читается). - pop_fore_over_char: расширение окна считается арифметикой, а не перебором 10 колонок и 3 рядов (условие монотонно -> границы). Формулы сверены с прежним перебором перебором значений, расхождений нет. - pop_cd_touch: цикл по страницам развёрнут, x+w/y+h считаются один раз. Зовётся с каждого блита фона, стоил 6 846 тактов. - process_trobs: tp/10 и tp%10 у факелов — таблицей. - Пустой слот соперника (стража на сцене нет, на странице ничего не нарисовано) считается «тихим»: ни heal, ни вход в pop_char_draw, ни fore-проход. Приём для поиска делений: брейкпоинт на __divsint/__divuint/__divuchar с печатью адреса возврата (printf "%04X", w@(sp)). Профиль остатка — TASKS_OPEN.md#draw-cost. tests-host: 5/5. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,9 +10,35 @@ const int16_t pop_x_bump[20] = {
|
||||
};
|
||||
const int16_t pop_y_land[5] = {-8, 55, 118, 181, 244};
|
||||
|
||||
#define TILE_SIZEY_OFF 60 /* сдвиг «ряд 0 начинается выше нуля» */
|
||||
|
||||
/* Медленный хвост — ОТДЕЛЬНОЙ функцией. Иначе SDCC видит одно и то же
|
||||
* выражение в двух ветках и поднимает деление в вершину функции: быстрые
|
||||
* возвраты уже не спасают, __divsint зовётся всё равно (проверено —
|
||||
* 5 вызовов за кадр остались после первой переписи). */
|
||||
static int8_t y_row_div(int16_t t)
|
||||
{
|
||||
return (int8_t)(t / TILE_SIZEY % 4 - 1);
|
||||
}
|
||||
|
||||
int8_t pop_y_to_row(int16_t y)
|
||||
{
|
||||
return (int8_t)((y + 60) / TILE_SIZEY % 4 - 1);
|
||||
/* Было `(y + 60) / 63 % 4 - 1` — SDCC разворачивает это в __divsint плюс
|
||||
* __modsint (а тот внутри снова зовёт __divsint): ~5 400 тактов на вызов
|
||||
* по замеру в MAME, при том что полос всего четыре. Цепочка сравнений
|
||||
* повторяет ИМЕННО прежнюю арифметику, включая усечение деления К НУЛЮ
|
||||
* для отрицательных (t в −62..−1 даёт 0, а не −1). */
|
||||
int16_t t = (int16_t)(y + TILE_SIZEY_OFF);
|
||||
if (t >= 0) {
|
||||
if (t < TILE_SIZEY) return -1; /* 0 % 4 - 1 */
|
||||
if (t < 2*TILE_SIZEY) return 0;
|
||||
if (t < 3*TILE_SIZEY) return 1;
|
||||
if (t < 4*TILE_SIZEY) return 2;
|
||||
if (t < 5*TILE_SIZEY) return -1; /* 4 % 4 = 0 */
|
||||
} else if (t > -TILE_SIZEY) {
|
||||
return -1; /* t/63 == 0 -> 0 % 4 - 1 */
|
||||
}
|
||||
return y_row_div(t);
|
||||
}
|
||||
|
||||
/* Уложить значение в диапазон 0..maxv. Вызовы оригинала — prandom(1),
|
||||
|
||||
Reference in New Issue
Block a user