Files
Sprinter-SDCC/libbgi/Makefile
T
snark13 b9ddce8d34 libbgi: спрайты — кэш адреса кадра, DDA+asm тик, Y-сортировка со слоями
Оптимизации A+B (профиль rpgwalk-15: активная часть кадра 410К → 307К
тактов из 430080; лимит спрайтов 16×16 на стабильные 48.8 fps: 14 → ~21):

- (B) sprite_t.src/stride — готовый адрес кадра: считают только
  sprite_frame (теперь функция, одно умножение на СМЕНУ кадра) и тикер
  (±an_step БАЙТ инкрементально); блит-ядра принимают src+stride,
  img/sx/sy из сигнатуры ушли.  Блит 177К → 146К на кадр.
- (A) тик 100К → 37.7К: tween переформулирован Брезенхэм → беззнаковый
  DDA (mv_rem/mv_acc, «приехали» = rem==0 — без знаковых 16-бит
  сравнений), tick_move и tick_anim — ручной asm (SDCC спиллит такие
  функции в IX-фрейм ~100 обращений; C-реструктуризации не помогали —
  проверено кодогеном).  Биты an_flags переименованы по категориям
  (_SPR_STRIP_HORZ, _SPR_PP_BACK).

Y-сортировка (gfx_sprite_ysort, идеи пользователя — 8-бит ключ,
персистентность):

- painter's algorithm по ключу {layer:8, clamp_y:8}; поле
  sprite_t.layer (в КОНЦЕ структуры — asm-офсеты не сдвигает): слои
  сцены в одном массиве/одном sprite_update;
- ПЕРСИСТЕНТНАЯ asm-таблица {key16, ptr16}: resort порядка прошлого
  кадра (почти линейно), rebuild при смене arr/count; массив
  приложения не трогается; ~28К/15 спрайтов (с нуля было 44К);
- компоненты YSORT_Y/YSORT_LAYER отключаемы независимо масками ключа
  (без ветвлений в сортировщике); ВНИМАНИЕ: mode=1 значит Y-only,
  полный порядок = YSORT_Y|YSORT_LAYER;
- funcptr-DCE: выключено = код и таблица не линкуются (rpgwalk −190 Б);
- ПРАВИЛО в sprite.h: два sprite_update на страницу запрещены (heal
  второй группы стирает спрайты первой — ОЗУ-копия чистая).

Попутные фиксы:

- libbgi/Makefile: .rel зависят от заголовков (HDRS) — stale .rel со
  старой раскладкой sprite_t молча ломал рантайм;
- rpgprof: --memory small (перерос tiny: BSS вылезал за W2 → мгновенный
  «Unexpected application termination»; mkexe это пока не ловит);
- tests/spranim: проверки переведены на кэш src, добавлены T6 (reframe
  после тикера) и T7 (Y-сортировка: порядок, слои, персистентный
  resort, LAYER-only) — 7/7 PASS в MAME.

Доки: §9д — новый бюджет (19.5К/спрайт), §9е — ПЛАН FPS-делителя
(frame pacing, gfx_set_fps_div); TODO — дизайн цепочки irq-обработчиков.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 17:19:24 +03:00

106 lines
4.7 KiB
Makefile
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Build lib/bgi256.lib + lib/bgi256_safe.lib — Sprinter BGI graphics driver (320×256×256).
#
# libbgi/ — самостоятельная графическая библиотека, отделённая от libc.
# Две driver-библиотеки собираются из одной исходной базы:
# bgi256.lib = common/*.rel + bgi256/*.rel (fast, без bounds-check)
# bgi256_safe.lib = common/*.rel + bgi256/*.rel (safe, с bounds-check)
# common/ — mode-agnostic: .rel компилируется в ОБЕ версии параллельно.
# bgi256/ — mode-specific leaf'ы.
#
# Каждый .c — отдельный .rel в архиве (1 публичная функция = 1 модуль);
# линкер тянет только нужные .rel → DCE на уровне файлов.
#
# make build lib/bgi256.lib + lib/bgi256_safe.lib (обе)
# make fast build только lib/bgi256.lib
# make safe build только lib/bgi256_safe.lib
# make BUILD_SAFE=1 build только lib/bgi256_safe.lib (legacy)
# make clean remove build/ + обе библиотеки
#
PROJ_ROOT := $(abspath $(CURDIR)/..)
SDCC_BIN := $(PROJ_ROOT)/third_party/sdcc/bin
SDCC := $(SDCC_BIN)/sdcc
SDAR := $(SDCC_BIN)/sdar
INC := -I$(CURDIR)/include -I$(PROJ_ROOT)/libc/include
BUILD := $(CURDIR)/build
COMMON_C := $(wildcard $(CURDIR)/common/*.c)
BGI256_C := $(wildcard $(CURDIR)/bgi256/*.c)
# Заголовки либы: любой .rel зависит от всех — правка _bgi.h/sprite.h/…
# пересобирает модули (иначе stale .rel со СТАРОЙ раскладкой sprite_t
# молча ломает рантайм — кусало 2026-07-14: sprite_moveto писал флаги
# по старому офсету, T4/T5 spranim FAIL).
HDRS := $(wildcard $(CURDIR)/*.h $(CURDIR)/include/*.h)
COMMON_FAST_RELS := $(patsubst $(CURDIR)/common/%.c,$(BUILD)/fast/common/%.rel,$(COMMON_C))
BGI256_FAST_RELS := $(patsubst $(CURDIR)/bgi256/%.c,$(BUILD)/fast/bgi256/%.rel,$(BGI256_C))
COMMON_SAFE_RELS := $(patsubst $(CURDIR)/common/%.c,$(BUILD)/safe/common/%.rel,$(COMMON_C))
BGI256_SAFE_RELS := $(patsubst $(CURDIR)/bgi256/%.c,$(BUILD)/safe/bgi256/%.rel,$(BGI256_C))
LIB_DIR := $(PROJ_ROOT)/lib
LIB_FAST := $(LIB_DIR)/bgi256.lib
LIB_SAFE := $(LIB_DIR)/bgi256_safe.lib
all: fast safe
fast: $(LIB_FAST)
safe: $(LIB_SAFE)
# --- Fast version: -DGFX_NOCHECK (guard'и выключены) ---
$(BUILD)/fast/common/%.rel: $(CURDIR)/common/%.c $(HDRS)
@mkdir -p $(dir $@)
$(SDCC) -mz80 --no-std-crt0 --std-c99 --opt-code-size -DGFX_NOCHECK --max-allocs-per-node 100000 $(INC) -c -o $@ $<
$(BUILD)/fast/bgi256/%.rel: $(CURDIR)/bgi256/%.c $(HDRS)
@mkdir -p $(dir $@)
$(SDCC) -mz80 --no-std-crt0 --std-c99 --opt-code-size -DGFX_NOCHECK --max-allocs-per-node 100000 $(INC) -c -o $@ $<
# --- Safe version: guard'и включены (по умолчанию) ---
$(BUILD)/safe/common/%.rel: $(CURDIR)/common/%.c $(HDRS)
@mkdir -p $(dir $@)
$(SDCC) -mz80 --no-std-crt0 --std-c99 --opt-code-size $(INC) -c -o $@ $<
$(BUILD)/safe/bgi256/%.rel: $(CURDIR)/bgi256/%.c $(HDRS)
@mkdir -p $(dir $@)
$(SDCC) -mz80 --no-std-crt0 --std-c99 --opt-code-size $(INC) -c -o $@ $<
# --- Archive: fast ---
$(BUILD)/fast/.have: $(COMMON_FAST_RELS) $(BGI256_FAST_RELS)
@find $(BUILD)/fast -name '*.rel' -print | sort > $@ 2>/dev/null || true
@printf '%s\n' $(COMMON_FAST_RELS) $(BGI256_FAST_RELS) | sort > $(BUILD)/fast/.want
@comm -23 $(BUILD)/fast/.have $(BUILD)/fast/.want | while read f; do \
echo " stale: $$f — rm"; \
rm -f "$$f" "$${f%.rel}.asm" "$${f%.rel}.lst" "$${f%.rel}.sym"; \
done
$(LIB_FAST): $(COMMON_FAST_RELS) $(BGI256_FAST_RELS) $(BUILD)/fast/.have
rm -f $@
$(SDAR) -rcs $@ $(COMMON_FAST_RELS) $(BGI256_FAST_RELS)
@echo " Built $@ with $$(( $$(echo "$(words $(COMMON_FAST_RELS))") + $$(echo "$(words $(BGI256_FAST_RELS))") )) modules."
# --- Archive: safe ---
$(BUILD)/safe/.have: $(COMMON_SAFE_RELS) $(BGI256_SAFE_RELS)
@find $(BUILD)/safe -name '*.rel' -print | sort > $@ 2>/dev/null || true
@printf '%s\n' $(COMMON_SAFE_RELS) $(BGI256_SAFE_RELS) | sort > $(BUILD)/safe/.want
@comm -23 $(BUILD)/safe/.have $(BUILD)/safe/.want | while read f; do \
echo " stale: $$f — rm"; \
rm -f "$$f" "$${f%.rel}.asm" "$${f%.rel}.lst" "$${f%.rel}.sym"; \
done
$(LIB_SAFE): $(COMMON_SAFE_RELS) $(BGI256_SAFE_RELS) $(BUILD)/safe/.have
rm -f $@
$(SDAR) -rcs $@ $(COMMON_SAFE_RELS) $(BGI256_SAFE_RELS)
@echo " Built $@ with $$(( $$(echo "$(words $(COMMON_SAFE_RELS))") + $$(echo "$(words $(BGI256_SAFE_RELS))") )) modules."
clean:
rm -rf $(BUILD) $(LIB_FAST) $(LIB_SAFE)
.PHONY: all fast safe clean