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:
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* gfx_blit_cols_part_noclip — блит спрайта column-major БЕЗ клипа по экрану,
|
||||
* с обрезкой сверху (как gfx_blit_cols_part). Пара к gfx_blit_cols_part
|
||||
* ровно так же, как gfx_blit_part_noclip — к gfx_blit_part.
|
||||
*
|
||||
* Зачем: у персонажей PoP спрайт почти всегда целиком на экране, а общий
|
||||
* gfx_blit_cols_part платит за проверку четырёх границ, пересчёт w/h/cx/sy и
|
||||
* 16-битную арифметику независимо от того, вылезает край или нет — замер в
|
||||
* MAME (roomtest, страж + клинок): 5 622 такта подготовки против 13 596 на
|
||||
* сам accel-проход. Здесь та же колонка уходит в _bgi_blit_cols_raw без
|
||||
* подготовки.
|
||||
*
|
||||
* Требования (проверяет ВЫЗЫВАЮЩИЙ, кода проверок здесь нет):
|
||||
* - прямоугольник назначения целиком на экране;
|
||||
* - ширина и высота кадра <= 255, y <= 255;
|
||||
* - skip < высоты кадра.
|
||||
* Не выполняется — зовите gfx_blit_cols_part.
|
||||
*
|
||||
* Флип, как и в gfx_blit_cols_part, бесплатный: подаём src с последней
|
||||
* колонки и отрицательный страйд — accel сам кладёт её в левый x.
|
||||
*
|
||||
* W3-скобка ставится ЗДЕСЬ (код libbgi живёт в W1): из приложения,
|
||||
* собранного с --w3, её вызывать нельзя — после _bgi_begin окно W3 занято
|
||||
* видеобанком и код вызывающего исчезает из адресного пространства.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include "../_bgi.h"
|
||||
|
||||
void gfx_blit_cols_part_noclip(int x, int y, const void *img, uint8_t flip,
|
||||
uint8_t skip, uint8_t rows)
|
||||
{
|
||||
const uint8_t *p = (const uint8_t *)img;
|
||||
uint8_t w = p[0]; /* ширина кадра (< 256) */
|
||||
uint8_t fh = p[2]; /* высота кадра (< 256) */
|
||||
const uint8_t *src = p + 4;
|
||||
uint8_t h;
|
||||
|
||||
if (w == 0 || fh == 0 || skip >= fh) return;
|
||||
h = (uint8_t)(fh - skip);
|
||||
if (rows && rows < h) h = rows;
|
||||
|
||||
if (flip) src += (uint16_t)(w - 1) * fh; /* последняя колонка -> левый x */
|
||||
src += skip;
|
||||
|
||||
_bgi_begin();
|
||||
_bgi_blit_cols_raw(src, (uint8_t *)(_gfx_addr_base + (uint16_t)x),
|
||||
w, h, flip ? -(int)fh : (int)fh, (uint8_t)y);
|
||||
_bgi_end();
|
||||
}
|
||||
Reference in New Issue
Block a user