Насколько я понял со слов Майкла и в ходе беглого осмотра кода, там только один фрагмент, повторяющийся 7 раз, может вызывать такую ошибку:
- Код: Выделить всё
DSBBang(BangInd).SetVolume -500
DSBBang(BangInd).SetFrequency Rnd * 5000 + 30000
DSBBang(BangInd).SetCurrentPosition 0
DSBBang(BangInd).Play 0, 0, 0
- Код: Выделить всё
DSBStep(StepInd).SetVolume v
DSBStep(StepInd).SetFrequency Rnd * 5000 + 40000
DSBStep(StepInd).SetCurrentPosition 0
DSBStep(StepInd).Play 0, 0, 0
- Код: Выделить всё
DSBFire(FireInd).SetVolume -700
DSBFire(FireInd).SetFrequency Rnd * 3000 + 20000
DSBFire(FireInd).SetCurrentPosition 0
DSBFire(FireInd).Play 0, 0, 0
- Код: Выделить всё
DSBRub.SetVolume -1000
DSBRub.SetFrequency 32000
DSBRub.SetCurrentPosition 0
DSBRub.Play 0, 0, 0
- Код: Выделить всё
DSBFly.SetVolume -900
DSBFly.SetFrequency 22000
DSBFly.SetCurrentPosition 0
DSBFly.Play 0, 0, 0
- Код: Выделить всё
DSBTNT.SetVolume -700
DSBTNT.SetFrequency 44100
DSBTNT.SetCurrentPosition 0
DSBTNT.Play 0, 0, 0
- Код: Выделить всё
DSBDeath.SetVolume -700
DSBDeath.SetFrequency 44100
DSBDeath.SetCurrentPosition 0
DSBDeath.Play 0, 0, 0
Я окружил эти фрагменты обработкой ошибок, пару раз проходил игру, но ошибку так и не поймал. Тогда я положил на форму таймеры со случайными интервалами в пределах 50—70, которые фигачили звуки с частотой пулемётной очереди, но ошибку тоже словить такой симуляцией не удалось.
Особо много подробностей в случае ловли ошибки мы тоже не получим: только узнаем, на каком методе (один и тот же ли он или всякий раз разный) и на каком объекте (какой-то определённый или всякий раз разный).
Урок же состоит в том, что ошибки от
DirectSound надо обрабатывать и замалчивать либо выводить в какую-то игровую консоль, но не стопить весь процесс.
Как пишет документация, эти методы могут вернуть ошибки с кодами:
- DSERR_CONTROLUNAVAIL
- DSERR_GENERIC
- DSERR_INVALIDPARAM
- DSERR_PRIOLEVELNEEDED
Кроме
SetCurrentPosition, которая не может выбросить ошибку
DSERR_GENERIC.
Если посмотреть на эти константы кодов ошибок, то мы увидим:
- Код: Выделить всё
C:\soft\devtools\vs6\vc6\Include>egrep -r "DSERR_(CONTROLUNAVAIL|GENERIC|INVALIDPARAM|PRIO)" *
DSOUND.H:#define DSERR_CONTROLUNAVAIL MAKE_DSHRESULT(30)
DSOUND.H:#define DSERR_INVALIDPARAM E_INVALIDARG
DSOUND.H:#define DSERR_GENERIC E_FAIL
DSOUND.H:#define DSERR_PRIOLEVELNEEDED MAKE_DSHRESULT(70)
E_FAIL это как раз и есть наш код
0x80004005L.
(Кстати,
The trick, это камень в твой огород — почему в TLB-шке нет этих констант (DSERR_*)?)
В итоге, получается, что у нас ошибка с кодом
DSERR_GENERIC. Один из методов отпадает, остаётся три. Документация даёт вот такое описание для этой ошибки, из которого мало что следует:
MSDN писал(а):DSERR_GENERICAn undetermined error occurred inside the DirectSound subsystem.
Почему не удаётся отловить: я уже подумал, а не поменял ли Mikle код в местах, где вариативность питча достигается путём изменения частоты дискретизации. Посмотрел дизасм оригинального EXE-шника — вроде бы ничего не поменялось, всё соответствует выложенным исходникам.