diff options
-rw-r--r-- | engines/dm/dm.cpp | 2 | ||||
-rw-r--r-- | engines/dm/dm.h | 29 | ||||
-rw-r--r-- | engines/dm/sounds.cpp | 123 |
3 files changed, 134 insertions, 20 deletions
diff --git a/engines/dm/dm.cpp b/engines/dm/dm.cpp index e825ead2c2..0381f34067 100644 --- a/engines/dm/dm.cpp +++ b/engines/dm/dm.cpp @@ -396,7 +396,7 @@ void DMEngine::f2_gameloop() { } } // F0363_COMMAND_HighlightBoxDisable(); - // F0065_SOUND_PlayPendingSound_CPSD(); + f65_playPendingSound(); _championMan->f320_applyAndDrawPendingDamageAndWounds(); if (_championMan->_g303_partyDead) break; diff --git a/engines/dm/dm.h b/engines/dm/dm.h index 02def018d1..1c187020f1 100644 --- a/engines/dm/dm.h +++ b/engines/dm/dm.h @@ -205,7 +205,25 @@ public: SoundData(): _byteCount(0), _firstSample(nullptr), _sampleCount(0) {} }; // @ SOUND_DATA - +class Sound { +public: + int16 _graphicIndex; + byte _period; + byte _priority; + byte _loudDistance; + byte _softDistance; + Sound(int16 index, byte period, byte priority, byte loudDist, byte softDist) : + _graphicIndex(index), _period(period), _priority(priority), _loudDistance(loudDist), _softDistance(softDist) {} +}; // @ Sound + +class PendingSound { +public: + uint8 _leftVolume; + uint8 _rightVolume; + int16 _soundIndex; + PendingSound(uint8 leftVolume, uint8 rightVolume, int16 soundIndex): + _leftVolume(leftVolume), _rightVolume(rightVolume), _soundIndex(soundIndex) {} +}; class DMEngine : public Engine { void f462_startGame(); // @ F0462_START_StartGame_CPSF @@ -236,9 +254,11 @@ public: void f441_processEntrance(); // @ F0441_STARTEND_ProcessEntrance void f444_endGame(bool doNotDrawCreditsOnly); // @ F0444_STARTEND_Endgame - void f064_SOUND_RequestPlay_CPSD(uint16 P0088_ui_SoundIndex, int16 P0089_i_MapX, int16 P0090_i_MapY, uint16 P0091_ui_Mode) { warning(true, "STUB: f064_SOUND_RequestPlay_CPSD"); } - void f060_SOUND_Play(uint16 P0921_ui_SoundIndex, uint16 P0085_i_Period, uint8 leftVol, uint8 rightVol); - void f438_STARTEND_OpenEntranceDoors() { warning(true, "STUB: f438_STARTEND_OpenEntranceDoors"); } + void f064_SOUND_RequestPlay_CPSD(uint16 P0088_ui_SoundIndex, int16 P0089_i_MapX, int16 P0090_i_MapY, uint16 P0091_ui_Mode); // @ F0064_SOUND_RequestPlay_CPSD + void f060_SOUND_Play(uint16 P0921_ui_SoundIndex, uint16 P0085_i_Period, uint8 leftVol, uint8 rightVol); // @ F0060_SOUND_Play + void f65_playPendingSound(); // @ F0065_SOUND_PlayPendingSound_CPSD + bool f505_soundGetVolume(int16 mapX, int16 mapY, uint8 *leftVolume, uint8 *rightVolume); // @ F0505_SOUND_GetVolume + void f438_STARTEND_OpenEntranceDoors() { warning(true, "STUB: f438_STARTEND_OpenEntranceDoors"); } // @ F0438_STARTEND_OpenEntranceDoors private: int16 _g528_saveFormat; // @ G0528_i_Format @@ -249,6 +269,7 @@ private: byte *_g564_interfaceCredits; // @ G0564_puc_Graphic5_InterfaceCredits Common::RandomSource *_rnd; SoundData _gK24_soundData[k34_D13_soundCount]; // @ K0024_as_SoundData + Common::Queue<PendingSound> _pendingSounds; public: DisplayMan *_displayMan; DungeonMan *_dungeonMan; diff --git a/engines/dm/sounds.cpp b/engines/dm/sounds.cpp index cdbed462a3..b44e97b2bf 100644 --- a/engines/dm/sounds.cpp +++ b/engines/dm/sounds.cpp @@ -31,23 +31,15 @@ #include "dm.h" #include "gfx.h" #include <audio/mixer.h> +#include "timeline.h" +#include "dungeonman.h" namespace DM { -class Sound { -public: - int16 _graphicIndex; - byte _period; - byte _priority; - byte _loudDistance; - byte _softDistance; - Sound(int16 index, byte period, byte priority, byte loudDist, byte softDist) : - _graphicIndex(index), _period(period), _priority(priority), _loudDistance(loudDist), _softDistance(softDist) {} -}; // @ Sound -Sound G0060_as_Graphic562_Sounds[k34_D13_soundCount] = { +Sound g60_sounds[k34_D13_soundCount] = { Sound(533, 112, 11, 3, 6), /* k00_soundMETALLIC_THUD 0 */ Sound(534, 112, 15, 0, 3), /* k01_soundSWITCH 1 */ Sound(535, 112, 72, 3, 6), /* k02_soundDOOR_RATTLE 2 */ @@ -87,7 +79,7 @@ void DMEngine::f503_loadSounds() { for (uint16 soundIndex = 0; soundIndex < k34_D13_soundCount; ++soundIndex) { SoundData *soundData = _gK24_soundData + soundIndex; - uint16 graphicIndex = G0060_as_Graphic562_Sounds[soundIndex]._graphicIndex; + uint16 graphicIndex = g60_sounds[soundIndex]._graphicIndex; soundData->_byteCount = _displayMan->getCompressedDataSize(graphicIndex) - 2; // the header is 2 bytes long soundData->_firstSample = new byte[soundData->_byteCount]; @@ -98,14 +90,115 @@ void DMEngine::f503_loadSounds() { } void DMEngine::f060_SOUND_Play(uint16 soundIndex, uint16 period, uint8 leftVolume, uint8 rightVolume) { - byte soundFlags = Audio::FLAG_STEREO; SoundData *sound = &_gK24_soundData[soundIndex]; - Audio::AudioStream *stream = Audio::makeRawStream(sound->_firstSample, sound->_byteCount, 72800 / period, soundFlags, DisposeAfterUse::NO); + Audio::AudioStream *stream = Audio::makeRawStream(sound->_firstSample, sound->_byteCount, (72800 / period) * 8, 0, DisposeAfterUse::NO); signed char balance = ((int16)rightVolume - (int16)leftVolume) / 2; Audio::SoundHandle handle; - _mixer->playStream(Audio::Mixer::kSFXSoundType, &handle, stream, - 1, 127, balance); + _mixer->playStream(Audio::Mixer::kSFXSoundType, &handle, stream, -1, 127, balance); +} + +void DMEngine::f65_playPendingSound() { + while (!_pendingSounds.empty()) { + PendingSound pendingSound = _pendingSounds.pop(); + f060_SOUND_Play(pendingSound._soundIndex, g60_sounds[pendingSound._soundIndex]._period, pendingSound._leftVolume, pendingSound._rightVolume); + } +} + +bool DMEngine::f505_soundGetVolume(int16 mapX, int16 mapY, uint8* leftVolume, uint8* rightVolume) { + static byte K0030_aauc_DistanceToSoundVolume[25][25] = { + {1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4}, + {1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 5, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 4, 4, 4}, + {1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 4, 5, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4}, + {1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 4, 5, 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 4}, + {1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 4, 5, 8, 8, 7, 7, 7, 7, 6, 6, 6, 5, 5, 5, 4}, + {1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 4, 6, 9, 9, 8, 8, 8, 7, 7, 6, 6, 6, 5, 5, 5}, + {1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 4, 6, 10, 10, 10, 9, 8, 8, 7, 7, 6, 6, 5, 5, 5}, + {1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 4, 7, 12, 12, 11, 10, 9, 9, 8, 7, 7, 6, 6, 5, 5}, + {1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4, 7, 15, 14, 13, 12, 11, 9, 8, 8, 7, 6, 6, 5, 5}, + {1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4, 8, 20, 19, 16, 14, 12, 10, 9, 8, 7, 7, 6, 6, 5}, + {1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4, 8, 29, 26, 21, 16, 13, 11, 10, 8, 7, 7, 6, 6, 5}, + {1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4, 8, 58, 41, 26, 19, 14, 12, 10, 9, 8, 7, 6, 6, 5}, + {1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 6, 64, 58, 29, 20, 15, 12, 10, 9, 8, 7, 6, 6, 5}, + {0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 3, 6, 41, 29, 19, 13, 10, 8, 7, 6, 6, 5, 5, 4, 4}, + {0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 3, 6, 21, 19, 15, 12, 10, 8, 7, 6, 5, 5, 4, 4, 4}, + {0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 3, 6, 14, 13, 12, 10, 9, 7, 7, 6, 5, 5, 4, 4, 4}, + {0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 5, 11, 10, 10, 9, 8, 7, 6, 6, 5, 5, 4, 4, 4}, + {0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 5, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 4, 4}, + {0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 5, 7, 7, 7, 7, 6, 6, 5, 5, 5, 4, 4, 4, 4}, + {0, 1, 1, 1, 1, 1, 1, 2, 2, 1, 3, 4, 6, 6, 6, 6, 6, 5, 5, 5, 4, 4, 4, 4, 3}, + {1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4, 6, 6, 5, 5, 5, 5, 5, 4, 4, 4, 4, 3, 3}, + {1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 3, 3, 3}, + {1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 5, 5, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3}, + {1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3}, + {1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3}}; + + int16 L1678_i_RightVolumeColumnIndex = 0; + int16 L1679_i_LineIndex = 0; + int16 L1680_i_LeftVolumeColumnIndex = 0; + + + switch (_dungeonMan->_g308_partyDir) { + case kDirNorth: + L1678_i_RightVolumeColumnIndex = mapX - _dungeonMan->_g306_partyMapX; + L1679_i_LineIndex = mapY - _dungeonMan->_g307_partyMapY; + break; + case kDirEast: + L1678_i_RightVolumeColumnIndex = mapY - _dungeonMan->_g307_partyMapY; + L1679_i_LineIndex = -(mapX - _dungeonMan->_g306_partyMapX); + break; + case kDirSouth: + L1678_i_RightVolumeColumnIndex = -(mapX - _dungeonMan->_g306_partyMapX); + L1679_i_LineIndex = -(mapY - _dungeonMan->_g307_partyMapY); + break; + case kDirWest: + L1678_i_RightVolumeColumnIndex = -(mapY - _dungeonMan->_g307_partyMapY); + L1679_i_LineIndex = mapX - _dungeonMan->_g306_partyMapX; + break; + } + if ((L1678_i_RightVolumeColumnIndex < -12) || (L1678_i_RightVolumeColumnIndex > 12)) { /* Sound is not audible if source is more than 12 squares away from the party */ + return false; + } + if ((L1679_i_LineIndex < -12) || (L1679_i_LineIndex > 12)) { /* Sound is not audible if source is more than 12 squares away from the party */ + return false; + } + L1680_i_LeftVolumeColumnIndex = -L1678_i_RightVolumeColumnIndex + 12; + L1678_i_RightVolumeColumnIndex += 12; + L1679_i_LineIndex += 12; + *rightVolume = K0030_aauc_DistanceToSoundVolume[L1679_i_LineIndex][L1678_i_RightVolumeColumnIndex]; + *leftVolume = K0030_aauc_DistanceToSoundVolume[L1679_i_LineIndex][L1680_i_LeftVolumeColumnIndex]; + return true; +} + +void DMEngine::f064_SOUND_RequestPlay_CPSD(uint16 soundIndex, int16 mapX, int16 mapY, uint16 mode) { + Sound* sound; + uint8 leftVolume, rightVolume; + + if (mode && (_dungeonMan->_g272_currMapIndex != _dungeonMan->_g309_partyMapIndex)) + return; + + sound = &g60_sounds[soundIndex]; + if (mode > k1_soundModePlayIfPrioritized) { /* Add an event in the timeline to play the sound (mode - 1) ticks later */ + TimelineEvent event; + M33_setMapAndTime(event._mapTime, _dungeonMan->_g272_currMapIndex, _g313_gameTime + mode - 1); + event._type = k20_TMEventTypePlaySound; + event._priority = sound->_priority; + event._C._soundIndex = soundIndex; + event._B._location._mapX = mapX; + event._B._location._mapY = mapY; + _timeline->f238_addEventGetEventIndex(&event); + return; + } + + if (!f505_soundGetVolume(mapX, mapY, &leftVolume, &rightVolume)) { + return; + } + if (!mode) { /* Play the sound immediately */ + f060_SOUND_Play(soundIndex, sound->_period, leftVolume, rightVolume); + return; + } + _pendingSounds.push(PendingSound(leftVolume, rightVolume, soundIndex)); } } |