PoP roomtest: fore-слой — окно клипа, кэш кладки; кадр 2.5 -> 0.78 периода
Жалоба: стойка неподвижных Кида и стража занимала больше полутора
кадровых периодов. Гипотеза «виноват __banked» ЗАМЕРОМ НЕ
ПОДТВЕРДИЛАСЬ: весь банковый вызов (трамплин + смена страницы + тело
pop_guard_tick + возврат) стоит 654 такта при бюджете кадра 430 000.
Как мерил (выборка PC бесполезна — мост MAME отвечает из фреймового
колбэка, все сэмплы падают в обработчик прерывания): breakpoint'ы MAME с
действием {printf totalcycles; g} на входах фаз главного цикла, разности
соседних меток = стоимость фазы. Плюс профилирование полосами бордюра
(make PROF=1, макрос PROF() в roomtest.c) для быстрого взгляда.
Замер комнаты 3 (Kid + страж), такты, кадр = 430 000:
fore поверх стража 431 964
fore поверх Kid 402 816 -> 78 % всей работы кадра
остальное 241 956
ИТОГО 1 076 736 = 2.5 кадра
Две причины, обе устранены:
1. Fore-слой рисовал ЦЕЛЫЕ тайлы, хотя существует ровно для того, чтобы
вернуть куски поверх спрайта — за его прямоугольником в видеопамяти и
так правильный фон. Введено ОКНО клипа (pop_fore_set_clip): спрайт
сообщает свой итоговый габарит (у Kid — с клинком, брызгами и
обрезкой clip_char), fore-проход режет по нему. Отсев трёхступенчатый:
тайл целиком (tile_in_fclip, до обращения к атласу), кусок по грубому
габариту (до gfx_w0_map — w/h лежат в EMM-странице), и точный клип в
blit_b. Для последнего добавлен libbgi-примитив
gfx_blit_part_noclip — пара к gfx_blit_noclip, но под-прямоугольник.
2. Оставшиеся 341 К после клипа оказались НЕ пикселями: 18 вызовов
pop_prandom за проход, ~10 700 тактов каждый (32-битный LCG:
__mullong ~8 000 + __moduint). Раскладка кладки тайла — чистая
функция (комната, ряд, колонка), то есть константа комнаты, а
wall_pattern пересчитывал её каждый кадр. Теперь кэшируются готовые
РЕШЕНИЯ (что рисовать и с каким смещением), 3 байта на тайл, сброс в
pop_room_draw. Порядок вызовов prandom воспроизведён один в один,
включая то, что значение метки берётся только при сработавшем условии.
Итог того же замера: fore поверх стража 37 464, поверх Kid 46 464,
кадр целиком 334 716 = 0.78 периода (было 2.5). Ускорение 3.2x, сами
fore-проходы — 10x.
Проверка отсутствия регрессии: попиксельная разность скриншотов комнат
1/2/3 до и после — отличаются ТОЛЬКО языки пламени факелов (анимация),
кладка и метки совпадают байт в байт.
Побочно: sprinter-cc научился пробрасывать -DNAME в sdcc.
Память: куча W2 1245 -> 996 Б (кэш кладки 120 Б), резидент W3 12 819 ->
14 512 (свободно 1872 Б — становится тесно), банк 1 236/16384.
ВНИМАНИЕ: make size-check показывает рост 7 программ, но эталон
docs/size_baseline.tsv отстал (последний раз принят в 484b18d, libbgi
менялась в 95c22be/c127a4b/64ce633) — к этой правке рост отношения не
имеет: новый модуль библиотеки в чужие программы не линкуется.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* gfx_blit_part_noclip — блит ПОД-ПРЯМОУГОЛЬНИКА картинки getimage-формата
|
||||
* БЕЗ клипа по экрану, в ТЕКУЩЕМ банке (gfx_set_bank). Пара к
|
||||
* gfx_blit_noclip ровно так же, как gfx_blit_part — к gfx_blit.
|
||||
*
|
||||
* Зачем: тайловому движку часто нужно положить поверх спрайта не весь
|
||||
* тайл, а только ту его часть, что перекрывает спрайт. Через
|
||||
* gfx_blit_part это идёт общим ядром _gfx_blit_full (16-битная
|
||||
* арифметика, клип, нарезка полос) — ~13 К тактов накладных на вызов
|
||||
* независимо от размера; здесь тот же под-прямоугольник рисуется линейным
|
||||
* спрайтовым ядром (~4.6 К на 32×3). Замер PoP roomtest 2026-07-29:
|
||||
* fore-слой поверх персонажа рисовал 9 целых тайлов за 432 К тактов
|
||||
* (стена = блок 64×63); с обрезкой по прямоугольнику спрайта тех же
|
||||
* пикселей остаётся втрое меньше.
|
||||
*
|
||||
* Требования (проверяет ВЫЗЫВАЮЩИЙ, кода проверок здесь нет):
|
||||
* - под-прямоугольник (sx,sy,w,h) лежит внутри картинки;
|
||||
* - прямоугольник назначения целиком на экране;
|
||||
* - w,h <= 255, y <= 255.
|
||||
* Не выполняется — зовите gfx_blit_part.
|
||||
*
|
||||
* W3-скобка ставится ЗДЕСЬ (код libbgi живёт в W1): из приложения,
|
||||
* собранного с --w3, её вызывать нельзя — после _bgi_begin окно W3 занято
|
||||
* видеобанком и код вызывающего исчезает из адресного пространства.
|
||||
*/
|
||||
#include "../_bgi.h"
|
||||
|
||||
void gfx_blit_part_noclip(int x, int y, const void *img,
|
||||
uint8_t sx, uint8_t sy, uint8_t w, uint8_t h)
|
||||
{
|
||||
const uint8_t *p = (const uint8_t *)img;
|
||||
uint16_t stride = (uint16_t)(p[0] | (p[1] << 8));
|
||||
const uint8_t *src = p + 4 + (uint16_t)sy * stride + sx;
|
||||
|
||||
_bgi_begin();
|
||||
_gfx_blit_sprite_noclip(x, y, src, stride, w, h);
|
||||
_bgi_end();
|
||||
}
|
||||
Reference in New Issue
Block a user