Оптимизация: логический кадр уложился в бюджет, цикл 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:
@@ -72,6 +72,54 @@ const piece pop_tile_table[31] = {
|
||||
{ 97, 1, 0, 98, 1, 2, 0, 0, 43,100, 0, 0}, /* 1E debris w/torch */
|
||||
};
|
||||
|
||||
/* Деление координаты на ширину тайла ТАБЛИЦЕЙ (tile_div_tbl/tile_mod_tbl,
|
||||
* seg006:702/23A6) — как в оригинале. Живут в резиденте, потому что нужны
|
||||
* и карте (банк 3, колонка персонажа), и слою фона (банк 2, футпринт), а
|
||||
* const-таблицу чужого банка не прочитать.
|
||||
*
|
||||
* Почему не деление: SDCC разворачивает / и % в __divsint + __modsint,
|
||||
* причём __modsint внутри снова зовёт __divsint — замер в MAME дал 5 400
|
||||
* тактов на один вызов при 13+ вызовах за кадр. Индекс — координата как
|
||||
* есть (0..255), смещение -58 уже внутри значений: POP_TILE_DIV[x] =
|
||||
* floor((x - 58) / 14), POP_TILE_MOD[x] — остаток. Сверено с SDLPoP
|
||||
* побайтно. */
|
||||
const int8_t POP_TILE_DIV[256] = {
|
||||
-5, -5, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4,
|
||||
-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -2, -2,
|
||||
-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
|
||||
10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
|
||||
11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14,
|
||||
};
|
||||
const uint8_t POP_TILE_MOD[256] = {
|
||||
12,13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13, 0, 1,
|
||||
2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13, 0, 1, 2, 3,
|
||||
4, 5, 6, 7, 8, 9,10,11,12,13, 0, 1, 2, 3, 4, 5,
|
||||
6, 7, 8, 9,10,11,12,13, 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9,10,11,12,13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
10,11,12,13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,
|
||||
12,13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13, 0, 1,
|
||||
2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13, 0, 1, 2, 3,
|
||||
4, 5, 6, 7, 8, 9,10,11,12,13, 0, 1, 2, 3, 4, 5,
|
||||
6, 7, 8, 9,10,11,12,13, 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9,10,11,12,13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
10,11,12,13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,
|
||||
12,13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13, 0, 1,
|
||||
};
|
||||
|
||||
const uint8_t POP_COL_XH[10] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36};
|
||||
const uint8_t POP_WALL_FRAM_BOTTOM[4] = {7, 9, 5, 3};
|
||||
const uint8_t POP_WALL_FRAM_MAIN[4] = {8, 10, 6, 4};
|
||||
@@ -107,19 +155,32 @@ uint8_t pop_loose_frame(uint8_t m)
|
||||
uint8_t pop_cd_dirty;
|
||||
int pop_cd_dx0[2], pop_cd_dy0[2], pop_cd_dx1[2], pop_cd_dy1[2];
|
||||
|
||||
/* Цикл по страницам развёрнут, а x+w / y+h посчитаны один раз. Не
|
||||
* вкусовщина: индекс-переменная заставляла SDCC считать адрес каждой из
|
||||
* восьми ячеек сложением, а `x + w` в условии и в присваивании считались
|
||||
* дважды — замер в MAME дал 6 846 тактов на вызов, а зовётся он с КАЖДОГО
|
||||
* блита фона (два факела в комнате — уже 13 700 за кадр). */
|
||||
void pop_cd_touch(int x, int y, int w, int h)
|
||||
{
|
||||
uint8_t p;
|
||||
for (p = 0; p < 2; p++) {
|
||||
if (!(pop_cd_dirty & (1 << p))) {
|
||||
pop_cd_dx0[p] = x; pop_cd_dy0[p] = y;
|
||||
pop_cd_dx1[p] = x + w; pop_cd_dy1[p] = y + h;
|
||||
} else {
|
||||
if (x < pop_cd_dx0[p]) pop_cd_dx0[p] = x;
|
||||
if (y < pop_cd_dy0[p]) pop_cd_dy0[p] = y;
|
||||
if (x + w > pop_cd_dx1[p]) pop_cd_dx1[p] = x + w;
|
||||
if (y + h > pop_cd_dy1[p]) pop_cd_dy1[p] = y + h;
|
||||
}
|
||||
int x1 = x + w, y1 = y + h;
|
||||
uint8_t d = pop_cd_dirty;
|
||||
if (!(d & 1)) {
|
||||
pop_cd_dx0[0] = x; pop_cd_dy0[0] = y;
|
||||
pop_cd_dx1[0] = x1; pop_cd_dy1[0] = y1;
|
||||
} else {
|
||||
if (x < pop_cd_dx0[0]) pop_cd_dx0[0] = x;
|
||||
if (y < pop_cd_dy0[0]) pop_cd_dy0[0] = y;
|
||||
if (x1 > pop_cd_dx1[0]) pop_cd_dx1[0] = x1;
|
||||
if (y1 > pop_cd_dy1[0]) pop_cd_dy1[0] = y1;
|
||||
}
|
||||
if (!(d & 2)) {
|
||||
pop_cd_dx0[1] = x; pop_cd_dy0[1] = y;
|
||||
pop_cd_dx1[1] = x1; pop_cd_dy1[1] = y1;
|
||||
} else {
|
||||
if (x < pop_cd_dx0[1]) pop_cd_dx0[1] = x;
|
||||
if (y < pop_cd_dy0[1]) pop_cd_dy0[1] = y;
|
||||
if (x1 > pop_cd_dx1[1]) pop_cd_dx1[1] = x1;
|
||||
if (y1 > pop_cd_dy1[1]) pop_cd_dy1[1] = y1;
|
||||
}
|
||||
pop_cd_dirty = 3;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user