Оптимизация: логический кадр уложился в бюджет, цикл 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:
@@ -21,6 +21,7 @@
|
||||
#include "pop_map.h"
|
||||
#include "pop_ctrl.h" /* pop_ctrl_shift_held() — для check_grab */
|
||||
#include "pop_geom.h" /* общая геометрия (x_bump/y_land/y_to_row) */
|
||||
#include "pop_tile.h" /* POP_TILE_DIV/MOD — деление на ширину тайла таблицей */
|
||||
#include "pop_redraw.h" /* пометки перерисовки (порт set_redraw_*) */
|
||||
/* pop_bg нужен ТОЛЬКО падающему куску (mob): spawn/tick/pos — это движущийся
|
||||
* ОБЪЕКТ, а не перерисовка тайла (в оригинале он и живёт отдельно: mobs +
|
||||
@@ -387,64 +388,15 @@ static int char_dx_forward(int8_t dx)
|
||||
return (int)Char.x + d;
|
||||
}
|
||||
|
||||
/* tile_div_tbl (data:22A6). Оригинал делит xpos на 14 ТАБЛИЦЕЙ, а не
|
||||
* арифметикой — и это оказалось не мелочью: `/14` и `%` 14 SDCC разворачивает
|
||||
* в __divsint + __modsint, причём __modsint внутри зовёт __divsint ещё раз.
|
||||
* Замер в MAME (стоящий Кид, комната 1.1): один вызов get_tile_div_mod —
|
||||
* ~5 400 тактов, 13 вызовов за кадр = ~70 000 = 16 % кадрового периода
|
||||
* на одно только «в какой колонке точка».
|
||||
*
|
||||
* Таблица сверена с SDLPoP seg006:702 побайтно. Индекс — xpos как есть,
|
||||
* смещение -58 уже внутри значений. Вне 0..255 (у нас xpos - int, у
|
||||
/* Деление на ширину тайла — таблицами POP_TILE_DIV/POP_TILE_MOD (резидент,
|
||||
* pop_tile.c: их же читает слой фона). Вне 0..255 (у нас xpos — int, у
|
||||
* DOS-оригинала байт) остаётся честная арифметика: путь редкий. */
|
||||
static const int8_t tile_div_tbl[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,
|
||||
};
|
||||
|
||||
/* tile_mod_tbl (data:23A6) — остаток от того же деления. Сначала я считал
|
||||
* его из xh тремя сдвигами, чтобы сэкономить 256 байт; SDCC развернул это в
|
||||
* десяток команд со спиллами через IY. Вторая таблица и дешевле, и это
|
||||
* ровно то, что делает оригинал. */
|
||||
static const uint8_t tile_mod_tbl[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,
|
||||
};
|
||||
|
||||
/* col = (xpos-58)/14 округл. вниз; g_obj_xl = позиция в тайле (0..13). */
|
||||
static int8_t get_tile_div_mod(int xpos)
|
||||
{
|
||||
if ((unsigned int)xpos < 256u) {
|
||||
g_obj_xl = tile_mod_tbl[xpos];
|
||||
return tile_div_tbl[xpos];
|
||||
g_obj_xl = POP_TILE_MOD[xpos];
|
||||
return POP_TILE_DIV[xpos];
|
||||
} else {
|
||||
int x = xpos - SCREENSPACE_X;
|
||||
int xh = x / TILE_SIZEX;
|
||||
|
||||
Reference in New Issue
Block a user