SprPoP: музыка без перелинковки — длины и длительности уехали на диск
Часть I плана music_runtime_index_plan.md (MI0..MI5). gen/pop_music_tbl.h и gen/pop_music_ticks.h УДАЛЕНЫ: длины треков и длительности реплик читаются из MUS/mus.idx (формат PMI1, tools/pop_idx.py, тесты в make test-tools). Один и тот же sprpop.exe работает с любым из четырёх наборов записей — sha256 бинарника при смене MUSIC_FMT не меняется. ГДЕ ЖИВЁТ ИНДЕКС. 228 байт таблицы в W2 не положить (свободной кучи там порядка двух сотен), поэтому индекс лежит в одной странице EMM, а в резиденте от него два байта. Данные в странице — со смещения 0x100: gfx_w0_page_prepare пишет в неё стабы прерываний (0x38 и 0x66), и с нуля они попали бы прямо в записи id 10 и 21. Со смещением работает штатная защита, а не запрет прерываний (тот же приём, что CFG_BASE в pop_config.c). Число страниц в индексе не хранится — считается из blocks, чтобы не разъехалось. ПАУЗА КОНЦА УРОВНЯ — СОСТОЯНИЕМ, А НЕ СЧЁТЧИКОМ. pop_endmus_left и POP_MUS_TICKS_32/41 удалены; главный цикл ждёт pop_music_active() — «заявка лежит, идёт загрузка или трек звучит». Одного busy мало: между заявкой и первой нотой 190-230 мс (замер в sound_plan §9). Прежний счётчик закрывал эту щель ценой зависимости EXE от набора и жёсткого делителя /4, который врал в режимах FAST/FASTEST (там логический кадр 3 кадра луча, а не 4). Побочно исправилось расхождение с SDLPoP: при выключенном звуке заявка не кладётся, и уровень меняется сразу, как в оригинале (seg006:651 + seg003:387) — раньше игра держала пройденный уровень лишние 12 секунд в тишине. PV-СЦЕНА — на четырёх якорях (8 байт статики), которые считаются из индекса при входе в сцену; прежние выражения шкалы не изменились. План предлагал протащить структуру времён через пять функций — для сцены, которая идёт раз за запуск, это того не стоит. ПАМЯТЬ. За обе фазы резидент не вырос, а освободился: _CODE 23865 -> 23544, куча 239 -> 256 Б. Банк 9 похудел на 118 Б (ушла pop_mus_tbl из rodata), банк 11 — на длительности реплик. ПРОВЕРЕНО В MAME: exe побайтово одинаков для flac и mt32; все 22 трека в индексах различаются, и контрольные значения совпали с предсказанными планом (m41 732->685, m50 831->867, m53 985->1044, m56 9865->10462 блоков, 78->82 страницы); на mt32 PV-сцена проходит целиком по его длительностям; без mus.idx музыки нет, эффекты работают, игра проходима. НЕ ПРОВЕРЕНО: потоковый m56 на 82 страницах — до финала надо дойти в игре. Единственный оставшийся пункт приёмки, отмечен в sound_plan §11.5. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011MsUsEFAQfsjjQpJ7RtKVY
This commit is contained in:
@@ -223,7 +223,7 @@ DISK := README_E.TXT README_R.TXT \
|
||||
KID/kid.arc KID/kid.pal KID/kid.ani \
|
||||
GUARD/guard.arc SKEL/skel.arc VIZIER/vizier.arc SHADOW/shadow.arc \
|
||||
SND/snd.arc SND/snd.idx \
|
||||
$(foreach i,$(MUS_IDS),MUS/m$(i).bin) \
|
||||
$(foreach i,$(MUS_IDS),MUS/m$(i).bin) MUS/mus.idx \
|
||||
FONT/font.atl \
|
||||
TITLE/title.arc TITLE/title.pal \
|
||||
PV/pv.arc PV/story.pal PV/pv.pal \
|
||||
@@ -236,9 +236,11 @@ GEN_ARC_H := bg_arc.h kid_arc.h guard_arc.h skel_arc.h vizier_arc.h \
|
||||
# pop_sound_tbl.h здесь БОЛЬШЕ НЕТ: раскладка эффектов уехала на диск
|
||||
# (SND/snd.idx), и EXE от звукового набора не зависит — пару
|
||||
# snd.idx + snd.arc можно менять без перекомпиляции.
|
||||
# Ни звукового, ни музыкальных заголовков здесь БОЛЬШЕ НЕТ: раскладка
|
||||
# эффектов и длины треков уехали на диск (SND/snd.idx, MUS/mus.idx), и EXE
|
||||
# не зависит ни от звукового набора, ни от набора записей.
|
||||
GEN_H := $(addprefix gen/,$(GEN_ARC_H) pop_bg_atlas.h kid_data.h \
|
||||
pop_guard_pal.h pop_shadow_atlas.h \
|
||||
pop_music_tbl.h pop_music_ticks.h pop_font.h)
|
||||
pop_guard_pal.h pop_shadow_atlas.h pop_font.h)
|
||||
|
||||
PACKED_FILES := $(addprefix $(PACKED)/,$(DISK))
|
||||
STAGED := $(addprefix $(BUILD_DIR)/,$(DISK))
|
||||
@@ -406,7 +408,7 @@ $(STAMP)/sound-$(SND_SRC): $(TOOLS)/pop_pack_sound.py $(TOOLS)/pop_idx.py \
|
||||
$(ARC) $(PACKED)/SND/snd.arc $$(ls $(ATL)/sound/s*.bin | sort -V)
|
||||
@cp $(ATL)/sound/snd.idx $(PACKED)/SND/snd.idx
|
||||
@touch $@
|
||||
$(eval $(call stamp_rule,music-$(MUSIC_FMT),$(TOOLS)/pop_pack_music.py $(TOOLS)/paths.py $(STAMP)/music.variant,pop_pack_music.py --format $(MUSIC_FMT) $(MUS_IDS)))
|
||||
$(eval $(call stamp_rule,music-$(MUSIC_FMT),$(TOOLS)/pop_pack_music.py $(TOOLS)/pop_idx.py $(TOOLS)/paths.py $(STAMP)/music.variant,pop_pack_music.py --format $(MUSIC_FMT) $(MUS_IDS)))
|
||||
$(eval $(call stamp_rule,font,$(TOOLS)/pop_extract_font.py $(TOOLS)/paths.py,pop_extract_font.py))
|
||||
$(eval $(call stamp_rule,title,$(TOOLS)/pop_pack_title.py $(TOOLS)/paths.py,pop_pack_title.py))
|
||||
$(eval $(call stamp_rule,pv,$(TOOLS)/pop_pack_intro.py $(TOOLS)/paths.py,pop_pack_intro.py))
|
||||
@@ -426,7 +428,7 @@ $(eval $(call from_stamp,$(GUARD_ATL) gen/pop_guard_pal.h,guard))
|
||||
$(eval $(call from_stamp,$(SKEL_ATL),skel))
|
||||
$(eval $(call from_stamp,$(VIZIER_ATL),vizier))
|
||||
$(eval $(call from_stamp,$(SHADOW_ATL) gen/pop_shadow_atlas.h,shadow))
|
||||
$(eval $(call from_stamp,$(foreach i,$(MUS_IDS),$(ATL)/music/m$(i).bin) gen/pop_music_tbl.h gen/pop_music_ticks.h,music-$(MUSIC_FMT)))
|
||||
$(eval $(call from_stamp,$(foreach i,$(MUS_IDS),$(ATL)/music/m$(i).bin) $(ATL)/music/mus.idx,music-$(MUSIC_FMT)))
|
||||
$(eval $(call from_stamp,$(ATL)/font/font.atl gen/pop_font.h,font))
|
||||
$(eval $(call from_stamp,$(TITLE_ATL) $(ATL)/title/title.pal,title))
|
||||
$(eval $(call from_stamp,$(PV_ATL) $(ATL)/pv/story.pal $(ATL)/pv/pv.pal,pv))
|
||||
@@ -475,6 +477,7 @@ $(eval $(call copy_rule,TITLE/title.pal,$(ATL)/title/title.pal))
|
||||
$(eval $(call copy_rule,PV/story.pal,$(ATL)/pv/story.pal))
|
||||
$(eval $(call copy_rule,PV/pv.pal,$(ATL)/pv/pv.pal))
|
||||
$(foreach i,$(MUS_IDS),$(eval $(call copy_rule,MUS/m$(i).bin,$(ATL)/music/m$(i).bin)))
|
||||
$(eval $(call copy_rule,MUS/mus.idx,$(ATL)/music/mus.idx))
|
||||
# Уровни идут на диск ПРЯМО из оригинала: формат res20xx.bin наш загрузчик
|
||||
# читает как есть, упаковщика для них нет. check-orig здесь тоже order-only —
|
||||
# без оригиналов взять уровни неоткуда, и сказать об этом надо внятно.
|
||||
@@ -509,7 +512,7 @@ resources-kid: $(PACKED)/KID/kid.arc $(PACKED)/KID/kid.pal $(PACKED)/KID/kid.
|
||||
resources-actors: $(PACKED)/GUARD/guard.arc $(PACKED)/SKEL/skel.arc \
|
||||
$(PACKED)/VIZIER/vizier.arc $(PACKED)/SHADOW/shadow.arc
|
||||
resources-sound: $(PACKED)/SND/snd.arc $(PACKED)/SND/snd.idx
|
||||
resources-music: $(foreach i,$(MUS_IDS),$(PACKED)/MUS/m$(i).bin)
|
||||
resources-music: $(foreach i,$(MUS_IDS),$(PACKED)/MUS/m$(i).bin) $(PACKED)/MUS/mus.idx
|
||||
resources-font: $(PACKED)/FONT/font.atl
|
||||
resources-title: $(PACKED)/TITLE/title.arc $(PACKED)/TITLE/title.pal
|
||||
resources-pv: $(PACKED)/PV/pv.arc $(PACKED)/PV/story.pal $(PACKED)/PV/pv.pal
|
||||
|
||||
Reference in New Issue
Block a user