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:
@@ -81,7 +81,12 @@ uint8_t pop_sword_draw(const pop_char_t *ch, const kframe *fr,
|
||||
top = obj_y + (int)SWORD_DY[sf] - (int)h + 1;
|
||||
if (flip) bx -= (int)w;
|
||||
gfx_set_bank(GFX_BANK_SPRITE);
|
||||
gfx_blit_cols_part(bx, top + POP_YOFF, simg, flip, 0, 0);
|
||||
/* Клинок почти всегда целиком на экране — noclip-путь (см. gfx.h:
|
||||
* подготовка клипающего варианта стоит ~5.6 К тактов на вызов). */
|
||||
if (pop_onscreen_cols(bx, top + POP_YOFF, w, h))
|
||||
gfx_blit_cols_part_noclip(bx, top + POP_YOFF, simg, flip, 0, 0);
|
||||
else
|
||||
gfx_blit_cols_part(bx, top + POP_YOFF, simg, flip, 0, 0);
|
||||
gfx_set_bank(GFX_BANK_NORMAL);
|
||||
*rx = bx; *ry = top; *rw = w; *rh = h;
|
||||
return 1;
|
||||
@@ -512,7 +517,10 @@ void kid_draw_splash(void)
|
||||
int top = obj_y - (int)h + 1;
|
||||
if (flip) bx -= (int)w;
|
||||
gfx_set_bank(GFX_BANK_SPRITE);
|
||||
gfx_blit_cols(bx, top + POP_YOFF, img, flip);
|
||||
if (pop_onscreen_cols(bx, top + POP_YOFF, w, h))
|
||||
gfx_blit_cols_part_noclip(bx, top + POP_YOFF, img, flip, 0, 0);
|
||||
else
|
||||
gfx_blit_cols(bx, top + POP_YOFF, img, flip);
|
||||
gfx_set_bank(GFX_BANK_NORMAL);
|
||||
pop_clip_sprite(bx, w, top + POP_YOFF, (int)h);
|
||||
/* Брызги — накладной спрайт: свой прямоугольник heal (см.
|
||||
@@ -593,8 +601,14 @@ void kid_draw(void)
|
||||
if (skip >= (int)h) skip = (int)h; /* обрезан целиком */
|
||||
}
|
||||
gfx_set_bank(GFX_BANK_SPRITE); /* видео-ОЗУ, без теневой копии */
|
||||
if (skip < (int)h) /* +YOFF: центрирование */
|
||||
gfx_blit_cols_part(bx, top + skip + POP_YOFF, img, flip, skip, 0);
|
||||
if (skip < (int)h) { /* +YOFF: центрирование */
|
||||
if (pop_onscreen_cols(bx, top + skip + POP_YOFF, w,
|
||||
(uint16_t)((int)h - skip)))
|
||||
gfx_blit_cols_part_noclip(bx, top + skip + POP_YOFF, img, flip,
|
||||
(uint8_t)skip, 0);
|
||||
else
|
||||
gfx_blit_cols_part(bx, top + skip + POP_YOFF, img, flip, skip, 0);
|
||||
}
|
||||
gfx_set_bank(GFX_BANK_NORMAL);
|
||||
/* клип СВОЕГО выхода за поле (падение ниже поля / верхний борт) —
|
||||
* узко, только по прямоугольнику Кида и только при выходе. */
|
||||
|
||||
Reference in New Issue
Block a user