f66fd0e1b6
Watchpoint на pop_mus_req поймал виновника: заявку ставил pop_sfx_play с
id 27, а звал его loose_shake — звук дрожащей плиты.
Классический sdcc_z80_cmp_store_a_bug. Было:
do { id = prandom(...) + 20; } while (id == last_loose_snd);
last_loose_snd = id; pop_sfx_play(id);
собиралось как
ld a, e / add a, #0x14 ; A = 20..22 — номер сэмпла
sub a, (hl) ; A = РАЗНОСТЬ, номер потерян
ld (_last_loose_snd), a ; сохраняем разность
jp _pop_sfx_play ; играем разность
То есть в звук уходил не сэмпл тряски, а id минус предыдущий id. Пока
такие «номера» попадали в пустые слоты набора, это молчало; с приходом
музыки мусор вида 22-251 = 27 стал запускать ТРЕК — отсюда музыка на
прыжке с уступа и на падающей плите.
Обход тот же, что в pop_status и pop_cdraw: записать ДО сравнения и играть
перечитанное из памяти. Проверено по сгенерированному asm.
Вторая линия обороны: pop_sfx_play принимает музыкальную заявку только в
диапазоне оригинала (24..43). Случайный мусорный id теперь молчит, а не
играет минуту музыки.
Проверено в MAME: тем же бегом, что раньше ловил заявку 27, watchpoint
больше не срабатывает. Host-тесты: 15 наборов.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>