6673279cef
Скелет (L3-SKEL, ассеты + механика): - pop_pack_guard.py получил параметр набора (GUARD/SKEL): атлас скелета poc/res/skel/g0..g3.atl (28 кадров), палитра — из его res750.pal (на ур. 3 curr_guard_color = 0, оригинал палитру не подменяет); - pop_guard_load выбирает набор по tbl_guard_type и перезагружается ПРИ СМЕНЕ УРОВНЯ (load_lev_spr, seg000:1092) — без этого скелет рисовался атласом стража и был невидим; - load_frame: charid_4_skeleton идёт по таблице стража (seg006:529), тень — только в кадрах 150..189. Пока ветка была одна (charid_2_guard), скелет получал image из таблицы Кида (180 при 28 спрайтах) и не рисовался; - check_skel (seg002:1042), ветка charid_4 в enter_guard, возрождение в комнате 3 при падении (seg002:252), autocontrol_skeleton; - leveldoor_open (seg007:456) — новый флаг, сбрасывается стартом уровня. Цвета стражей (BUG-GUARD-COLOR-1, закрыт): - все 7 палитр res10.bin -> pop_guard_pal.h, заливка 16 слотов по guards_color комнаты перед отрисовкой (set_chtab_palette, seg003:257). Проверено в MAME: ур. 2 комн. 11 = цвет 1, комн. 7 = цвет 3, полоса HP меняется вместе со стражем. Грабля: gfx_pal_load отдаёт указатель в BIOS, а тот читает только #4000-#BFFF — таблицу из банка копируем в стек. Кэш соседних комнат (BUG-SWORD-GHOST-1, закрыт): - pop_map кэширует fg соседей слева/справа ЦЕЛИКОМ и резолвит col -10..19. Было -2..11, дальше мнимая стена: луч видимости упирался в неё (страж после follow_guard в col 12), Кид прятал меч посреди боя и не мог достать обратно. +48 байт W2. Окклюзия соперника: - pop_fore_over_char получил проход other_overlay_tile (порядок midtable, seg008:1B06) и расширение перебора объединённым прямоугольником «персонаж + клинок + брызги» — падающий скелет больше не рисуется поверх кладки и верхней грани пола; - клип полем 192 строк (reset_obj_clip, seg006:0507) для спрайта, клинка (общий pop_sword_draw) и брызг — спрайт не залезает на полосу HP; - ROOMNAV после смерти Кида делает честный pop_start_level: телепорт «оживлял» мёртвого мимо старта уровня, оставляя живого скелета рядом с вернувшейся кучей костей. Ассеты чомпера (под L3-CHOMP): весь набор кадров в атласе явным списком (101-105 низ, 111-113 верх, 106-110 фронт, 114-123 кровь mono-силуэтом) — render_room анимированные тайлы пропускает, и в атласе не было ни одного. Число EMM-страниц не изменилось. Тесты: tests-host все 5 наборов зелёные, t_char вырос до 65 проверок (резолв колонок за краем комнаты, возрождение скелета); в testkit добавлен гард «код наехал на данные» (DATA_LOC). Доски: TASKS.md разнесён на TASKS_OPEN/TASKS_CLOSED, закрытые баги с разбором корней — в bug_closed.md; заведены DRAW-CHAR (отрисовка одна на всех Char, как физика после GUARD-PHYS) и L3-COLOR (зелёная кладка уровня 3: level_var_palettes = ресурс 20, есть в MSDOS/PRINCE.DAT). В roomtest.c временно оставлен автостоп на падении соперника (отладка падений скелета) — помечен ВРЕМЕННО. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
108 lines
5.8 KiB
Makefile
108 lines
5.8 KiB
Makefile
# ----------------------------------------------------------------------
|
||
# host-tests.mk — общие правила модульных тестов, исполняемых под ucsim_z80.
|
||
#
|
||
# Сама обвязка (crt0_ucsim.s, tcheck.*, run_ucsim.py) лежит в testkit/ и ни
|
||
# к какому подпроекту не привязана: тестировать так можно и libc, и логику
|
||
# приложений — всё, что на plain C и не трогает железо.
|
||
#
|
||
# Подключается из каталога с наборами t_*.c:
|
||
#
|
||
# TESTKIT := $(abspath ../../../../testkit)
|
||
# ENGINE_DIR := $(abspath ..) # где лежат модули под тестом
|
||
# OBJS_geom := build/eng_pop_geom.rel # что доложить в этот набор
|
||
# include $(TESTKIT)/host-tests.mk
|
||
#
|
||
# Набор t_<имя>.c подхватывается wildcard'ом, регистрировать не надо.
|
||
# ----------------------------------------------------------------------
|
||
|
||
ifndef TESTKIT
|
||
$(error перед include надо задать TESTKIT — путь к каталогу testkit/)
|
||
endif
|
||
|
||
PROJ_ROOT ?= $(abspath $(TESTKIT)/..)
|
||
SDCC := $(PROJ_ROOT)/third_party/sdcc/bin/sdcc
|
||
SDASZ80 := $(PROJ_ROOT)/third_party/sdcc/bin/sdasz80
|
||
UCSIM := $(PROJ_ROOT)/third_party/sdcc/bin/ucsim_z80
|
||
RUNNER := $(TESTKIT)/run_ucsim.py
|
||
|
||
BUILD := build
|
||
|
||
# --code-loc: стартовый код занимает 13 байт по 0x0000, код с 0x0200.
|
||
# --data-loc 0x8000: данные заведомо выше кода.
|
||
#
|
||
# CODE_LOC переопределяется набором, если ему нужна нижняя память под
|
||
# данные: так делает t_phys в roomtest — он кладёт по 0x100 страницу
|
||
# таблиц анимации, которую на устройстве туда приводит маппинг W0.
|
||
# EXTRA_INC — заголовки, которых нет ни в testkit, ни в ENGINE_DIR
|
||
# (например libc/libbgi, когда модуль под тестом их включает).
|
||
# DATA_LOC — та же история сверху: набор, чей код перерос 0x8000, обязан
|
||
# отодвинуть данные, иначе линкер молча кладёт хвост кода (_HOME, деления
|
||
# из libsdcc) ПОВЕРХ _DATA — тест ведёт себя как «зациклился», хотя логика
|
||
# ни при чём. Проверку наложения делает check-overlap ниже.
|
||
CODE_LOC ?= 0x0200
|
||
DATA_LOC ?= 0x8000
|
||
EXTRA_INC ?=
|
||
CFLAGS := -mz80 --no-std-crt0 --std-c99 --opt-code-size -I$(TESTKIT) \
|
||
$(if $(ENGINE_DIR),-I$(ENGINE_DIR)) $(EXTRA_INC) $(EXTRA_CFLAGS)
|
||
LDFLAGS := -mz80 --no-std-crt0 --code-loc $(CODE_LOC) --data-loc $(DATA_LOC)
|
||
|
||
SUITES := $(patsubst t_%.c,%,$(notdir $(wildcard t_*.c)))
|
||
COMMON := $(BUILD)/crt0_ucsim.rel $(BUILD)/tcheck.rel
|
||
|
||
.PHONY: all clean $(addprefix t_,$(SUITES))
|
||
# Иначе make считает .rel/.ihx промежуточными и удаляет их после прогона —
|
||
# следующий `make` пересобирал бы всё заново.
|
||
.SECONDARY:
|
||
# OBJS_<набор> подставляется в правило по имени цели — нужен второй проход
|
||
# раскрытия, иначе модуль не попадёт в зависимости и не соберётся.
|
||
.SECONDEXPANSION:
|
||
|
||
# Ярлык каталога в отчёте — с родителем: «tests-host» само по себе
|
||
# неоднозначно, когда таких каталогов несколько.
|
||
LABEL := $(notdir $(patsubst %/,%,$(dir $(CURDIR))))/$(notdir $(CURDIR))
|
||
|
||
all: $(addprefix run-,$(SUITES))
|
||
@echo "$(LABEL): все наборы прошли ($(words $(SUITES)))"
|
||
|
||
# Прогон одного набора. Раннер сам разбирает tc_result и возвращает код.
|
||
# Наложение кода на данные линкер sdld НЕ считает ошибкой: код просто
|
||
# ложится поверх _DATA, и тест виснет/врёт без единого предупреждения.
|
||
# Ловим сами — конец _CODE (CODE_LOC + l__CODE) против DATA_LOC.
|
||
define CHECK_OVERLAP
|
||
@python3 -c "import sys; \
|
||
d={p[1]:int(p[2],16) for p in (l.split() for l in open('$(1)')) if len(p)==3 and p[0]=='DEF'}; \
|
||
end=$(CODE_LOC)+d.get('l__CODE',0); \
|
||
sys.exit(0) if end<=$(DATA_LOC) else sys.exit('%s: КОД НАЕХАЛ НА ДАННЫЕ — _CODE кончается на 0x%04X, а DATA_LOC = 0x%04X.\n Поднять DATA_LOC в Makefile набора (стек в crt0_ucsim — 0xFEF0).' % ('$(1)', end, $(DATA_LOC)))"
|
||
endef
|
||
|
||
run-%: $(BUILD)/%.ihx
|
||
$(call CHECK_OVERLAP,$(BUILD)/$*.noi)
|
||
@python3 $(RUNNER) $(UCSIM) $(BUILD)/$*.ihx $(BUILD)/$*.noi
|
||
|
||
# Удобный псевдоним: `make t_geom` вместо `make run-geom`.
|
||
t_%: run-% ;
|
||
|
||
$(BUILD)/%.ihx: $(BUILD)/%.rel $(COMMON) $$(OBJS_$$*)
|
||
@$(SDCC) $(LDFLAGS) -o $@ $(COMMON) $(BUILD)/$*.rel $(OBJS_$*)
|
||
|
||
$(BUILD)/%.rel: t_%.c $(TESTKIT)/tcheck.h | $(BUILD)
|
||
@$(SDCC) $(CFLAGS) -c -o $@ $<
|
||
|
||
# Модули под тестом собираются ТЕМ ЖЕ компилятором и с той же семантикой,
|
||
# что и продукт, — включая модули с inline-asm, которые хостовой сборкой
|
||
# не проверить в принципе.
|
||
$(BUILD)/eng_%.rel: $(ENGINE_DIR)/%.c | $(BUILD)
|
||
@$(SDCC) $(CFLAGS) -c -o $@ $<
|
||
|
||
$(BUILD)/tcheck.rel: $(TESTKIT)/tcheck.c $(TESTKIT)/tcheck.h | $(BUILD)
|
||
@$(SDCC) $(CFLAGS) -c -o $@ $<
|
||
|
||
$(BUILD)/crt0_ucsim.rel: $(TESTKIT)/crt0_ucsim.s | $(BUILD)
|
||
@$(SDASZ80) -plosgff $@ $<
|
||
|
||
$(BUILD):
|
||
@mkdir -p $(BUILD)
|
||
|
||
clean:
|
||
@rm -rf $(BUILD)
|