PoP/libbgi: убрана 32-бит арифметика, noclip для column-major, быстрый PRNG
Ревью на 32-бит сделан ПО ASM, а не по коду (искали и безымянные
временные): во всём приложении был ровно ОДИН 32-битный вызов —
__mullong в pop_prandom. Замер в MAME: 8 430 тактов на вызов, два
вызова за кадр. Прочие библиотечные вызовы 16-битные (__divsint 16,
__modsint 12, __moduchar 8, __divuchar 5).
1. pop_prandom. Состояние 32-бит -> две 16-битные половины. Два
генератора, выбор через POP_PRANDOM_EXACT:
- 0 (по умолчанию) — xorshift16 + шаг Вейля, без единого умножения;
- 1 — LCG оригинала бит-в-бит, посчитанный половинами (для сверки
картинки с эталоном).
8-битный RND Apple II (5*x+23 mod 256) НЕ взят: у LCG по модулю 256
вырождены младшие биты (бит 0 просто чередуется), а раскладка кладки
берёт как раз prandom(1) и prandom(4) — вместо шума вышла бы
правильная шахматка. Шаг Вейля ещё и убирает ноль как неподвижную
точку xorshift (сид кладки вполне может быть нулём).
Бит-в-бит эквивалентность half-word версии проверена на хосте:
70 000 сидов x 8 шагов + 7 крайних сидов x 2000 шагов.
Остаток 0..maxv: делитель степень двойки — маска вместо __moduint.
2. libbgi: gfx_blit_cols_part_noclip — column-major блит без клипа
(пара к gfx_blit_cols_part, как gfx_blit_part_noclip к
gfx_blit_part). Клипающий вариант платит ~5 622 такта подготовки на
КАЖДЫЙ вызов независимо от того, вылезает край (замер: подготовка
5 622 против 13 596 на сам accel-проход). Kid, страж и клинок
выбирают путь по pop_onscreen_cols. size-check: роста нет.
Бюджет (175 кадров, комната 3, медиана):
было (после клинка) 416 154 0.968 кадра
стало 397 986 0.926 кадра
Разница между генераторами, замер на одинаковой сборке:
xorshift16 + Вейль 397 986 prandom->torch_draw 7 927
бит-в-бит LCG 403 632 prandom->torch_draw 10 933
то есть точность обходится в 5 646 тактов за кадр (1.3 %).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -354,7 +354,7 @@ static uint8_t wall_modifier(int row, int col)
|
||||
}
|
||||
|
||||
/* ---- PRNG (seg009.c:321, 32-бит LCG) — только на ВХОД в комнату ---- */
|
||||
static unsigned long rnd_seed;
|
||||
static pop_rnd_t rnd_seed;
|
||||
|
||||
#define prandom(maxv) pop_prandom(&rnd_seed, (maxv))
|
||||
|
||||
@@ -417,7 +417,7 @@ static void wall_rnd(int row, int col)
|
||||
* соседнего РЯДА и чужую раскладку (тихий баг вместо промаха). */
|
||||
int idx = (col >= 0 && col < 10) ? (row + 1) * 10 + col : -1;
|
||||
uint8_t a, b, bg;
|
||||
unsigned long saved;
|
||||
pop_rnd_t saved;
|
||||
if (idx >= 0 && idx < WP_N && wp_ok[idx]) {
|
||||
a = wp_a[idx]; b = wp_b[idx];
|
||||
wr_mid_div = (uint8_t)(a & 1); wr_mid_off = (uint8_t)((a >> 1) & 7);
|
||||
@@ -430,7 +430,7 @@ static void wall_rnd(int row, int col)
|
||||
saved = rnd_seed;
|
||||
/* Верхняя полоса (row<0): SDLPoP рисует её как ряд 2 комнаты сверху
|
||||
* (drawn_row=2 для seed, draw_main_y=-1 для позиции) — seed по row 2. */
|
||||
rnd_seed = (unsigned long)(g_room + TBL_LINE[row < 0 ? 2 : row] + col);
|
||||
pop_prandom_set(rnd_seed, g_room + TBL_LINE[row < 0 ? 2 : row] + col);
|
||||
prandom(1); /* сброс */
|
||||
wr_mid_div = (uint8_t)prandom(1);
|
||||
wr_mid_off = (uint8_t)prandom(4);
|
||||
|
||||
Reference in New Issue
Block a user