aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorathrxx2019-04-01 00:55:17 +0200
committerathrxx2019-04-13 18:55:02 +0200
commit0ea6650837cce3007f0820acd17518f9809fd4a7 (patch)
tree507986e06df0d230cc2d1ee64b47efb87546b4e7
parent972f4e201ade5660723f6348480437e2a02fa6de (diff)
downloadscummvm-rg350-0ea6650837cce3007f0820acd17518f9809fd4a7.tar.gz
scummvm-rg350-0ea6650837cce3007f0820acd17518f9809fd4a7.tar.bz2
scummvm-rg350-0ea6650837cce3007f0820acd17518f9809fd4a7.zip
KYRA: (EOB2/Amiga) - implement proper sound file loading
(also fix some sound related bugs)
-rw-r--r--engines/kyra/engine/chargen.cpp6
-rw-r--r--engines/kyra/engine/darkmoon.cpp90
-rw-r--r--engines/kyra/engine/darkmoon.h10
-rw-r--r--engines/kyra/engine/eob.cpp33
-rw-r--r--engines/kyra/engine/eob.h3
-rw-r--r--engines/kyra/engine/eobcommon.cpp6
-rw-r--r--engines/kyra/engine/eobcommon.h7
-rw-r--r--engines/kyra/engine/scene_eob.cpp10
-rw-r--r--engines/kyra/engine/sprites_eob.cpp5
-rw-r--r--engines/kyra/resource/staticres_eob.cpp18
-rw-r--r--engines/kyra/sound/drivers/audiomaster2.cpp111
-rw-r--r--engines/kyra/sound/sound.h5
-rw-r--r--engines/kyra/sound/sound_amiga_eob.cpp74
-rw-r--r--engines/kyra/sound/sound_intern.h9
14 files changed, 285 insertions, 102 deletions
diff --git a/engines/kyra/engine/chargen.cpp b/engines/kyra/engine/chargen.cpp
index 2ae9682ed2..7a4c9672c6 100644
--- a/engines/kyra/engine/chargen.cpp
+++ b/engines/kyra/engine/chargen.cpp
@@ -634,16 +634,20 @@ int CharacterGenerator::alignmentMenu(int cClass) {
}
int CharacterGenerator::getInput(Button *buttonList) {
+ if (_vm->gameFlags().platform == Common::kPlatformAmiga)
+ return _vm->checkInput(buttonList, false, 0);
+
if (_vm->game() == GI_EOB1 && _vm->sound()->checkTrigger()) {
_vm->sound()->resetTrigger();
_vm->snd_playSong(20);
- } else if (_vm->game() == GI_EOB2 && _vm->gameFlags().platform != Common::kPlatformAmiga && !_vm->sound()->isPlaying()) {
+ } else if (_vm->game() == GI_EOB2 && !_vm->sound()->isPlaying()) {
// WORKAROUND for EOB II: The original implements the same sound trigger check as in EOB I.
// However, Westwood seems to have forgotten to set the trigger at the end of the AdLib song,
// so that the music will not loop. We simply check whether the sound driver is still playing.
_vm->delay(3 * _vm->_tickLength);
_vm->snd_playSong(13);
}
+
return _vm->checkInput(buttonList, false, 0);
}
diff --git a/engines/kyra/engine/darkmoon.cpp b/engines/kyra/engine/darkmoon.cpp
index 8d621b9bc9..efe66a4d43 100644
--- a/engines/kyra/engine/darkmoon.cpp
+++ b/engines/kyra/engine/darkmoon.cpp
@@ -37,6 +37,11 @@ DarkMoonEngine::DarkMoonEngine(OSystem *system, const GameFlags &flags) : EoBCor
_utilMenuStrings = _ascii2SjisTables = _ascii2SjisTables2 = 0;
_npcShpData = _dscDoorType5Offs = _hornSounds = 0;
_dreamSteps = 0;
+
+ _amigaSoundMapExtra = _amigaSoundFiles2 = 0;
+ _amigaSoundIndex1 = 0;
+ _amigaSoundIndex2 = 0;
+ _amigaCurSoundIndex = 0;
}
DarkMoonEngine::~DarkMoonEngine() {
@@ -415,6 +420,91 @@ bool DarkMoonEngine::restParty_extraAbortCondition() {
return true;
}
+void DarkMoonEngine::snd_loadAmigaSounds(int level, int sub) {
+ if (_flags.platform != Common::kPlatformAmiga)
+ return;
+
+ int fileNum = _amigaSoundIndex2[level];
+ if (fileNum != _amigaCurSoundFile) {
+ for (int i = 52; i < 68; ++i) {
+ if (_amigaSoundMap[i]) {
+ _sound->unloadSoundFile(_amigaSoundMap[i]);
+ _amigaSoundMap[i] = 0;
+ }
+ }
+
+ _sound->loadSoundFile(_amigaSoundFiles2[fileNum]);
+ _amigaCurSoundFile = fileNum;
+
+ int mapCnt = 0;
+ for (int i = 0; i < fileNum + 1; ) {
+ if (!_amigaSoundMapExtra[mapCnt++][0])
+ i++;
+ }
+
+ for (int i = 52; i < 68; ++i) {
+ if (!_amigaSoundMapExtra[mapCnt][0]) {
+ _amigaSoundMap[i] = 0;
+ break;
+ }
+ _amigaSoundMap[i] = _amigaSoundMapExtra[mapCnt++];
+ }
+ }
+
+ if (level == 10 || (level == 8 && sub))
+ return;
+
+ uint16 sndIndex = 0;
+
+ for (int i = 0; i != level; ) {
+ int8 val = _amigaSoundIndex1[sndIndex++];
+ if (val == -1)
+ i++;
+ }
+
+ if (sub)
+ sndIndex += 4;
+
+ if (_amigaCurSoundIndex) {
+ for (int i = 0; i < 4; ++i) {
+ int8 valCur = _amigaSoundIndex1[_amigaCurSoundIndex + i];
+ int8 valNew = _amigaSoundIndex1[sndIndex + i];
+ if (valCur < 0)
+ continue;
+
+ if (i < 2) {
+ for (int ii = 1; ii < 5; ++ii)
+ _sound->unloadSoundFile(Common::String::format("%s%d", _amigaLevelSoundList2[valCur], ii));
+ } else {
+ if (valCur != valNew)
+ _sound->unloadSoundFile(Common::String::format("%s.SAM", _amigaLevelSoundList1[valCur]));
+ _sound->unloadSoundFile(Common::String::format("%s1", _amigaLevelSoundList2[valCur]));
+ }
+ }
+ }
+
+ for (int i = 0; i < 4; ++i) {
+ int8 valCur = _amigaCurSoundIndex ? _amigaSoundIndex1[_amigaCurSoundIndex + i] : -5;
+ int8 valNew = _amigaSoundIndex1[sndIndex + i];
+
+ if (valNew >= 0 && valNew != valCur) {
+ if (i < 2 && valCur >= 0 && _amigaCurSoundIndex)
+ _sound->unloadSoundFile(Common::String::format("%s.SAM", _amigaLevelSoundList1[_amigaSoundIndex1[_amigaCurSoundIndex]]));
+ _sound->loadSoundFile(Common::String::format("%s.CPS", _amigaLevelSoundList1[valNew]));
+ assert(_amigaLevelSoundList2[valNew]);
+ _amigaSoundMap[36 + i] = _amigaLevelSoundList2[valNew][0] ? _amigaLevelSoundList2[valNew] : 0;
+ } else if (valNew == -2) {
+ _amigaSoundMap[36 + i] = 0;
+ } else if (valNew == -3) {
+ _amigaSoundMap[36 + i] = _amigaSoundMap[35 + i];
+ }
+ }
+
+ _sound->loadSoundFile(Common::String::format(sub ? "LEVEL%da.SAM" : "LEVEL%d.SAM", level));
+
+ _amigaCurSoundIndex = sndIndex;
+}
+
void DarkMoonEngine::useHorn(int charIndex, int weaponSlot) {
int v = _items[_characters[charIndex].inventory[weaponSlot]].value - 1;
_txt->printMessage(_hornStrings[v]);
diff --git a/engines/kyra/engine/darkmoon.h b/engines/kyra/engine/darkmoon.h
index 71bfc75370..b3a69d254a 100644
--- a/engines/kyra/engine/darkmoon.h
+++ b/engines/kyra/engine/darkmoon.h
@@ -115,6 +115,16 @@ private:
void restParty_npc();
bool restParty_extraAbortCondition();
+ // Sound
+ void snd_loadAmigaSounds(int level, int sub);
+
+ const char *const *_amigaSoundFiles2;
+ const char *const *_amigaSoundMapExtra;
+ const int8 *_amigaSoundIndex1;
+ const uint8 *_amigaSoundIndex2;
+
+ int _amigaCurSoundIndex;
+
// misc
void useHorn(int charIndex, int weaponSlot);
bool checkPartyStatusExtra();
diff --git a/engines/kyra/engine/eob.cpp b/engines/kyra/engine/eob.cpp
index f2d06e0a59..dc653fa38e 100644
--- a/engines/kyra/engine/eob.cpp
+++ b/engines/kyra/engine/eob.cpp
@@ -513,6 +513,39 @@ void EoBEngine::turnUndeadAutoHit() {
sparkEffectOffensive();
}
+void EoBEngine::snd_loadAmigaSounds(int level, int) {
+ if (_flags.platform != Common::kPlatformAmiga || level == _amigaCurSoundFile)
+ return;
+
+ if (_amigaCurSoundFile != -1) {
+ _sound->unloadSoundFile(Common::String::format("L%dM1A1", _amigaCurSoundFile));
+ _sound->unloadSoundFile(Common::String::format("L%dM2A1", _amigaCurSoundFile));
+
+ for (int i = 1; i < 5; ++i) {
+ _sound->unloadSoundFile(Common::String::format("L%dM1M%d", _amigaCurSoundFile, i));
+ _sound->unloadSoundFile(Common::String::format("L%dM2M%d", _amigaCurSoundFile, i));
+ }
+
+ for (int i = 0; i < 2; ++i) {
+ if (_amigaLevelSoundList1[_amigaCurSoundFile * 2 + i][0])
+ _sound->unloadSoundFile(_amigaLevelSoundList1[_amigaCurSoundFile * 2 + i]);
+ if (_amigaLevelSoundList2[_amigaCurSoundFile * 2 + i][0])
+ _sound->unloadSoundFile(_amigaLevelSoundList2[_amigaCurSoundFile * 2 + i]);
+ }
+ }
+
+ for (int i = 0; i < 2; ++i) {
+ if (_amigaLevelSoundList1[level * 2 + i][0])
+ _sound->loadSoundFile(Common::String::format("%s.CPS", _amigaLevelSoundList1[level * 2 + i]));
+ if (_amigaLevelSoundList2[level * 2 + i][0])
+ _sound->loadSoundFile(Common::String::format("%s.CPS", _amigaLevelSoundList2[level * 2 + i]));
+ }
+
+ _sound->loadSoundFile(Common::String::format("LEVELSAM%d.CPS", level));
+
+ _amigaCurSoundFile = level;
+}
+
bool EoBEngine::checkPartyStatusExtra() {
_screen->copyPage(0, 10);
int cd = _screen->curDimIndex();
diff --git a/engines/kyra/engine/eob.h b/engines/kyra/engine/eob.h
index de98a91899..efb6c47b30 100644
--- a/engines/kyra/engine/eob.h
+++ b/engines/kyra/engine/eob.h
@@ -109,6 +109,9 @@ private:
const char *const *_turnUndeadString;
+ // Sound
+ void snd_loadAmigaSounds(int level, int);
+
// Misc
bool checkPartyStatusExtra();
int resurrectionSelectDialogue();
diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
index 16f9088945..153d17971f 100644
--- a/engines/kyra/engine/eobcommon.cpp
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -221,6 +221,9 @@ EoBCoreEngine::EoBCoreEngine(OSystem *system, const GameFlags &flags) : KyraRpgE
_mnNumWord = _numSpells = _mageSpellListSize = _spellLevelsMageSize = _spellLevelsClericSize = 0;
_inventorySlotsX = _slotValidationFlags = _encodeMonsterShpTable = 0;
_cgaMappingDefault = _cgaMappingAlt = _cgaMappingInv = _cgaLevelMappingIndex = _cgaMappingItemsL = _cgaMappingItemsS = _cgaMappingThrown = _cgaMappingIcons = _cgaMappingDeco = 0;
+ _amigaLevelSoundList1 = _amigaLevelSoundList2 = 0;
+ _amigaSoundMap = 0;
+ _amigaCurSoundFile = -1;
memset(_cgaMappingLevel, 0, sizeof(_cgaMappingLevel));
memset(_expRequirementTables, 0, sizeof(_expRequirementTables));
memset(_saveThrowTables, 0, sizeof(_saveThrowTables));
@@ -322,6 +325,9 @@ EoBCoreEngine::~EoBCoreEngine() {
delete[] _menuDefs;
_menuDefs = 0;
+ delete[] _amigaSoundMap;
+ _amigaSoundMap = 0;
+
delete _inf;
_inf = 0;
delete _timer;
diff --git a/engines/kyra/engine/eobcommon.h b/engines/kyra/engine/eobcommon.h
index 3566ea4345..c4340a2348 100644
--- a/engines/kyra/engine/eobcommon.h
+++ b/engines/kyra/engine/eobcommon.h
@@ -1180,6 +1180,13 @@ protected:
void snd_playSoundEffect(int id, int volume=0xFF);
void snd_stopSound();
void snd_fadeOut(int speed = 160);
+ virtual void snd_loadAmigaSounds(int level, int sub) = 0;
+
+ const char **_amigaSoundMap;
+ const char *const *_amigaLevelSoundList1;
+ const char *const *_amigaLevelSoundList2;
+
+ int _amigaCurSoundFile;
// keymap
static const char *const kKeymapName;
diff --git a/engines/kyra/engine/scene_eob.cpp b/engines/kyra/engine/scene_eob.cpp
index 7f3c464939..110bf0d12c 100644
--- a/engines/kyra/engine/scene_eob.cpp
+++ b/engines/kyra/engine/scene_eob.cpp
@@ -222,13 +222,15 @@ Common::String EoBCoreEngine::initLevelData(int sub) {
}
}
- if (_flags.gameID == GI_EOB2) {
+ if (_flags.platform == Common::kPlatformAmiga) {
+ delay(3 * _tickLength);
+ snd_loadAmigaSounds(_currentLevel, sub);
+ if (_flags.gameID == GI_EOB2)
+ pos += 13;
+ } else if (_flags.gameID == GI_EOB2) {
delay(3 * _tickLength);
_sound->loadSoundFile((const char *)pos);
pos += 13;
- } else if (_flags.platform == Common::kPlatformAmiga) {
- delay(3 * _tickLength);
- _sound->loadSoundFile(_currentLevel);
}
releaseDoorShapes();
diff --git a/engines/kyra/engine/sprites_eob.cpp b/engines/kyra/engine/sprites_eob.cpp
index f7e65f2133..17a5f555ed 100644
--- a/engines/kyra/engine/sprites_eob.cpp
+++ b/engines/kyra/engine/sprites_eob.cpp
@@ -1038,7 +1038,10 @@ bool EoBCoreEngine::updateMonsterTryDistanceAttack(EoBMonsterInPlay *m) {
if (s < 20) {
monsterSpellCast(m, s);
} else if (s == 20) {
- snd_processEnvironmentalSoundEffect(103, m->block);
+ if (_flags.platform == Common::kPlatformAmiga)
+ snd_processEnvironmentalSoundEffect(39, _currentBlock + 1);
+ else
+ snd_processEnvironmentalSoundEffect(103, m->block);
_txt->printMessage(_monsterSpecAttStrings[0]);
for (int i = 0; i < 6; i++)
statusAttack(i, 4, _monsterSpecAttStrings[1], 1, 5, 9, 1);
diff --git a/engines/kyra/resource/staticres_eob.cpp b/engines/kyra/resource/staticres_eob.cpp
index 90a8b904e4..c0ec2431b6 100644
--- a/engines/kyra/resource/staticres_eob.cpp
+++ b/engines/kyra/resource/staticres_eob.cpp
@@ -468,9 +468,18 @@ void EoBCoreEngine::initStaticResource() {
void *sndInfo_finale = 0;
if (_flags.platform == Common::kPlatformAmiga) {
- const char *const *files = _staticres->loadStrings(kEoBBaseSoundFilesIngame, temp);
const char *const *map = _staticres->loadStrings(kEoBBaseSoundMap, temp2);
- SoundResourceInfo_AmigaEoB ingame(files, temp, map, temp2);
+ _amigaSoundMap = new const char*[temp2];
+ for (int i = 0; i < temp2; ++i) {
+ assert(map[i]);
+ _amigaSoundMap[i] = map[i][0] ? map[i] : 0;
+ }
+
+ _amigaLevelSoundList1 = _staticres->loadStrings(kEoBBaseLevelSounds1, temp);
+ _amigaLevelSoundList2 = _staticres->loadStrings(kEoBBaseLevelSounds2, temp);
+
+ const char *const *files = _staticres->loadStrings(kEoBBaseSoundFilesIngame, temp);
+ SoundResourceInfo_AmigaEoB ingame(files, temp, _amigaSoundMap, temp2);
sndInfo_ingame = &ingame;
files = _staticres->loadStrings(kEoBBaseSoundFilesIntro, temp);
SoundResourceInfo_AmigaEoB intro(files, temp, 0, 0);
@@ -1356,6 +1365,11 @@ void DarkMoonEngine::initStaticResource() {
_monsterAcHitChanceTable1 = _monsterAcHitChanceTbl1;
_monsterAcHitChanceTable2 = _monsterAcHitChanceTbl2;
+ _amigaSoundMapExtra = _staticres->loadStrings(kEoB2SoundMapExtra, temp);
+ _amigaSoundFiles2 = _staticres->loadStrings(kEoB2SoundFilesIngame2, temp);
+ _amigaSoundIndex1 = (const int8*)_staticres->loadRawData(kEoB2SoundIndex1, temp);
+ _amigaSoundIndex2 = _staticres->loadRawData(kEoB2SoundIndex2, temp);
+
static const char *const errorSlotNoNameString[3] = {
" You must specify\r a name for your\r save game!",
" Spielst[nde m]ssen\r einen Namen haben!",
diff --git a/engines/kyra/sound/drivers/audiomaster2.cpp b/engines/kyra/sound/drivers/audiomaster2.cpp
index dbc6f30424..7db98879ad 100644
--- a/engines/kyra/sound/drivers/audiomaster2.cpp
+++ b/engines/kyra/sound/drivers/audiomaster2.cpp
@@ -292,12 +292,13 @@ private:
class AudioMaster2ResourceManager {
public:
- AudioMaster2ResourceManager(AudioMaster2Internal *driver, Common::Mutex *mutex);
+ AudioMaster2ResourceManager(AudioMaster2Internal *driver, Common::Mutex &mutex);
~AudioMaster2ResourceManager();
void loadResourceFile(Common::SeekableReadStream *data);
void initResource(SoundResource *resource);
+ void deinitResource(SoundResource *resource);
void releaseResource(const Common::String &resName);
void stopChain();
@@ -314,12 +315,12 @@ private:
void linkToChain(SoundResource *resource, SoundResource::Mode mode);
SoundResource *_chainPlaying;
- SoundResource *_chainInactive;
+ SoundResource *_chainStorage;
uint16 _masterVolume[3];
AudioMaster2Internal *_driver;
- Common::Mutex *_mutex;
+ Common::Mutex &_mutex;
};
class AudioMaster2IFFLoader : public Common::IFFParser {
@@ -456,11 +457,16 @@ void SoundResource::loadName(Common::ReadStream *stream, uint32 size) {
void SoundResource::open() {
_refCnt++;
+ debugC(8, kDebugLevelSound, "SoundResource::open(): '%s', type '%s', new refCount: '%d'", _name.c_str(), (_type == 1) ? "SMUS" : (_type == 2 ? "INST" : "8SVX"), _refCnt);
}
void SoundResource::close() {
- if (--_refCnt <= 0)
+ _refCnt--;
+ debugC(8, kDebugLevelSound, "SoundResource::close(): '%s', type '%s', new refCount: '%d' %s", _name.c_str(), (_type == 1) ? "SMUS" : (_type == 2 ? "INST" : "8SVX"), _refCnt, _refCnt <= 0 ? "--> RELEASED" : "");
+ if (_refCnt == 0) {
+ _res->deinitResource(this);
release();
+ }
}
const Common::String &SoundResource::getName() const {
@@ -656,6 +662,7 @@ void SoundResourceINST::loadSamples(Common::ReadStream *stream, uint32 size) {
} else {
// This will come up quite often in EOB II. But never with intruments that are actually used. No need to bother the user with a warning here.
debugC(9, kDebugLevelSound, "SoundResourceINST::loadInstrument(): Samples resource '%s' not found for '%s'.", data, _name.c_str());
+ _samplesResource = 0;
}
delete[] data;
@@ -760,11 +767,7 @@ void SoundResourceSMUS::prepare() {
_playFlags = 0;
for (Common::Array<Track*>::iterator trk = _tracks.begin(); trk != _tracks.end(); ++trk) {
(*trk)->_dataCur = (*trk)->_dataStart;
-
- for (Common::Array<SoundResource*>::iterator instr = _instruments.begin(); instr != _instruments.end(); ++instr) {
- (*trk)->setInstrument(*instr);
- break;
- }
+ (*trk)->setInstrument(*_instruments.begin());
if (!(*trk)->_instrument)
error("SoundResourceSMUS::prepare():: Unable to assign default instrument to track (resource files loaded in the wrong order?)");
@@ -864,7 +867,7 @@ const uint16 SoundResourceSMUS::_durationTable[64] = {
0x8700, 0x4380, 0x21c0, 0x10e0, 0x0870, 0x0438, 0x021c, 0x010e
};
-AudioMaster2ResourceManager::AudioMaster2ResourceManager(AudioMaster2Internal *driver, Common::Mutex *mutex) : _driver(driver), _mutex(mutex), _chainPlaying(0), _chainInactive(0) {
+AudioMaster2ResourceManager::AudioMaster2ResourceManager(AudioMaster2Internal *driver, Common::Mutex &mutex) : _driver(driver), _mutex(mutex), _chainPlaying(0), _chainStorage(0) {
memset(_masterVolume, 0, sizeof(_masterVolume));
}
@@ -898,6 +901,36 @@ void AudioMaster2ResourceManager::initResource(SoundResource *resource) {
linkToChain(res, SoundResource::kIdle);
}
+void AudioMaster2ResourceManager::deinitResource(SoundResource *resource) {
+ Common::StackLock lock(_mutex);
+
+ SoundResource *prev = 0;
+ for (SoundResource *cur = _chainPlaying; cur; cur = cur->_next) {
+ if (cur == resource) {
+ if (prev)
+ prev->_next = cur->_next;
+ else
+ _chainPlaying = cur->_next;
+ cur->_next = 0;
+ return;
+ }
+ prev = cur;
+ }
+
+ prev = 0;
+ for (SoundResource *cur = _chainStorage; cur; cur = cur->_next) {
+ if (cur == resource) {
+ if (prev)
+ prev->_next = cur->_next;
+ else
+ _chainStorage = cur->_next;
+ cur->_next = 0;
+ return;
+ }
+ prev = cur;
+ }
+}
+
void AudioMaster2ResourceManager::releaseResource(const Common::String &resName) {
stopChain();
@@ -910,7 +943,7 @@ void AudioMaster2ResourceManager::releaseResource(const Common::String &resName)
}
void AudioMaster2ResourceManager::stopChain() {
- Common::StackLock lock(*_mutex);
+ Common::StackLock lock(_mutex);
SoundResource *cur = _chainPlaying;
while (cur) {
@@ -922,21 +955,19 @@ void AudioMaster2ResourceManager::stopChain() {
}
void AudioMaster2ResourceManager::flush() {
- stopChain();
+ Common::StackLock lock(_mutex);
- Common::StackLock lock(*_mutex);
+ stopChain();
- for (SoundResource *res = _chainPlaying; _chainPlaying; res = _chainPlaying) {
- _chainPlaying = res->_next;
- res->_next = 0;
- res->setPlayStatus(false);
+ while (_chainPlaying) {
+ SoundResource *res = _chainPlaying;
+ deinitResource(res);
res->close();
}
- for (SoundResource *res = _chainInactive; _chainInactive; res = _chainInactive) {
- _chainInactive = res->_next;
- res->_next = 0;
- res->setPlayStatus(false);
+ while (_chainStorage) {
+ SoundResource *res = _chainStorage;
+ deinitResource(res);
res->close();
}
}
@@ -961,7 +992,7 @@ SoundResource *AudioMaster2ResourceManager::getResource(const Common::String &re
void AudioMaster2ResourceManager::setMasterVolume(int type, int volume) {
assert(type == 1 || type == 2 || type == 4);
- Common::StackLock lock(*_mutex);
+ Common::StackLock lock(_mutex);
_masterVolume[type >> 1] = volume & 0xFFFF;
@@ -970,7 +1001,7 @@ void AudioMaster2ResourceManager::setMasterVolume(int type, int volume) {
res->setMasterVolume(volume);
}
- for (SoundResource *res = _chainInactive; res; res = res->_next) {
+ for (SoundResource *res = _chainStorage; res; res = res->_next) {
if (res->getType() == type)
res->setMasterVolume(volume);
}
@@ -988,13 +1019,13 @@ void AudioMaster2ResourceManager::interrupt(AudioMaster2IOManager *io) {
cur = cur->_next;
} else if (prev) {
prev->_next = cur->_next;
- cur->_next = _chainInactive;
- _chainInactive = cur;
+ cur->_next = _chainStorage;
+ _chainStorage = cur;
cur = prev->_next;
} else {
_chainPlaying = cur->_next;
- cur->_next = _chainInactive;
- _chainInactive = cur;
+ cur->_next = _chainStorage;
+ _chainStorage = cur;
cur = _chainPlaying;
}
}
@@ -1012,11 +1043,11 @@ SoundResource *AudioMaster2ResourceManager::retrieveFromChain(const Common::Stri
const char *srchStr = resName.c_str();
uint32 srchDepth = strlen(srchStr);
+ Common::StackLock lock(_mutex);
+
SoundResource *cur = _chainPlaying;
SoundResource *prev = 0;
- Common::StackLock lock(*_mutex);
-
while (cur) {
if (!scumm_strnicmp(cur->getName().c_str(), srchStr, srchDepth)) {
if (prev)
@@ -1030,7 +1061,7 @@ SoundResource *AudioMaster2ResourceManager::retrieveFromChain(const Common::Stri
cur = cur->_next;
}
- cur = _chainInactive;
+ cur = _chainStorage;
prev = 0;
while (cur) {
@@ -1038,7 +1069,7 @@ SoundResource *AudioMaster2ResourceManager::retrieveFromChain(const Common::Stri
if (prev)
prev->_next = cur->_next;
else
- _chainInactive = cur->_next;
+ _chainStorage = cur->_next;
cur->_next = 0;
return cur;
}
@@ -1051,13 +1082,13 @@ SoundResource *AudioMaster2ResourceManager::retrieveFromChain(const Common::Stri
void AudioMaster2ResourceManager::linkToChain(SoundResource *resource, SoundResource::Mode mode) {
+ Common::StackLock lock(_mutex);
+
if (resource->getType() == 1) {
stopChain();
resource->prepare();
}
- Common::StackLock lock(*_mutex);
-
if (mode == SoundResource::kRestart) {
resource->setPlayStatus(true);
resource->_next = _chainPlaying;
@@ -1067,8 +1098,8 @@ void AudioMaster2ResourceManager::linkToChain(SoundResource *resource, SoundReso
_driver->sync(resource);
} else {
- resource->_next = _chainInactive;
- _chainInactive = resource;
+ resource->_next = _chainStorage;
+ _chainStorage = resource;
}
}
@@ -1203,13 +1234,13 @@ bool AudioMaster2Internal::init() {
return true;
_io = new AudioMaster2IOManager();
- _res = new AudioMaster2ResourceManager(this, &_mutex);
+ _res = new AudioMaster2ResourceManager(this, _mutex);
+ startPaula();
+
_mixer->playStream(Audio::Mixer::kPlainSoundType,
&_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
- startPaula();
-
_ready = true;
return true;
@@ -1290,9 +1321,9 @@ void AudioMaster2Internal::sync(SoundResource *res) {
if (res->getType() != 1)
return;
- SoundResourceSMUS *smus = static_cast<SoundResourceSMUS*>(res);
-
Common::StackLock lock(_mutex);
+
+ SoundResourceSMUS *smus = static_cast<SoundResourceSMUS*>(res);
_io->_tempo = smus->getTempo();
smus->setSync(_io->_sync);
}
diff --git a/engines/kyra/sound/sound.h b/engines/kyra/sound/sound.h
index 871263cf65..6c45d8b59b 100644
--- a/engines/kyra/sound/sound.h
+++ b/engines/kyra/sound/sound.h
@@ -161,6 +161,11 @@ public:
virtual void loadSoundFile(Common::String file) = 0;
/**
+ * Unload a specifc sound file that has been loaded before.
+ */
+ virtual void unloadSoundFile(Common::String file) {}
+
+ /**
* Load a sound file for playing sound
* effects from.
*/
diff --git a/engines/kyra/sound/sound_amiga_eob.cpp b/engines/kyra/sound/sound_amiga_eob.cpp
index 444c85995c..f572c11c43 100644
--- a/engines/kyra/sound/sound_amiga_eob.cpp
+++ b/engines/kyra/sound/sound_amiga_eob.cpp
@@ -30,7 +30,7 @@
namespace Kyra {
SoundAmiga_EoB::SoundAmiga_EoB(KyraEngine_v1 *vm, Audio::Mixer *mixer) : Sound(vm, mixer),
- _vm(vm), _driver(0), _currentResourceSet(-1), _currentFile(-1), _levelSoundList1(0), _levelSoundList2(0), _ready(false) {
+ _vm(vm), _driver(0), _currentResourceSet(-1), _ready(false) {
_fileBuffer = new uint8[64000];
memset(_resInfo, 0, sizeof(_resInfo));
}
@@ -51,11 +51,8 @@ bool SoundAmiga_EoB::init() {
if (!_driver->init())
return false;
- int temp = 0;
- _levelSoundList1 = _vm->staticres()->loadStrings(kEoBBaseLevelSounds1, temp);
- _levelSoundList2 = _vm->staticres()->loadStrings(kEoBBaseLevelSounds2, temp);
-
_ready = true;
+
return true;
}
@@ -78,29 +75,12 @@ void SoundAmiga_EoB::selectAudioResourceSet(int set) {
_currentResourceSet = set;
}
-void SoundAmiga_EoB::loadSoundFile(uint file) {
- if (_vm->gameFlags().platform != Common::kPlatformAmiga || _currentResourceSet != kMusicIngame || !_ready)
- return;
-
- unloadLevelSounds();
-
- for (int i = 0; i < 2; ++i) {
- if (_levelSoundList1[file * 2 + i][0])
- loadSoundFile(Common::String::format("%s.CPS", _levelSoundList1[file * 2 + i]));
- if (_levelSoundList2[file * 2 + i][0])
- loadSoundFile(Common::String::format("%s.CPS", _levelSoundList2[file * 2 + i]));
- }
-
- loadSoundFile(Common::String::format("LEVELSAM%d.CPS", file));
-
- _currentFile = file;
-}
-
void SoundAmiga_EoB::loadSoundFile(Common::String file) {
if (!_ready)
return;
Common::SeekableReadStream *in = _vm->resource()->createReadStream(file);
+ debugC(6, kDebugLevelSound, "SoundAmiga_EoB::loadSoundFile(): Attempting to load sound file '%s'...%s", file.c_str(), in ? "SUCCESS" : "FILE NOT FOUND");
if (!in)
return;
@@ -139,6 +119,13 @@ void SoundAmiga_EoB::loadSoundFile(Common::String file) {
delete[] buf;
}
+void SoundAmiga_EoB::unloadSoundFile(Common::String file) {
+ if (!_ready)
+ return;
+ debugC(5, kDebugLevelSound, "SoundAmiga_EoB::unloadSoundFile(): Attempting to free resource '%s'...%s", file.c_str(), _driver->stopSound(file) ? "SUCCESS" : "FAILURE");
+ _driver->flushResource(file);
+}
+
void SoundAmiga_EoB::playTrack(uint8 track) {
if (!_musicEnabled || !_ready)
return;
@@ -191,21 +178,32 @@ void SoundAmiga_EoB::playSoundEffect(uint8 track, uint8 volume) {
if (!_resInfo[_currentResourceSet]->soundList || track >= 120 || !_sfxEnabled)
return;
+ if (_vm->game() == GI_EOB2 && track == 2) {
+ beginFadeOut(60);
+ return;
+ }
+
Common::String newSound = _resInfo[_currentResourceSet]->soundList[track];
+ const char *suffix = (_vm->game() == GI_EOB1) ? "1.SAM" : ((track > 51 && track < 68) ? ".SMUS" : ".SAM");
if (!newSound.empty()) {
if (volume == 255) {
- if (_driver->startSound(newSound + "1.SAM")) {
- _lastSound = newSound + "1.SAM";
+ if (_driver->startSound(newSound + suffix)) {
+ _lastSound = newSound + suffix;
return;
} else {
volume = 1;
}
}
- if (volume > 0 && volume < 5) {
- newSound = Common::String::format("%s%d", newSound.c_str(), volume);
- _driver->startSound(newSound);
+ if (volume > 0 && volume < 5)
+ newSound = Common::String::format("%s%d", newSound.c_str(), volume);
+
+ if (!_driver->startSound(newSound)) {
+ // WORKAROUND for wrongly named resources. This applies to at least 'BLADE' in the EOB II dungeons (instead of 'BLADE1').
+ newSound = _resInfo[_currentResourceSet]->soundList[track];
+ if (_driver->startSound(newSound))
+ debugC(5, kDebugLevelSound, "SoundAmiga_EoB::playSoundEffect(): Triggered workaround for wrongly named resource: '%s'", newSound.c_str());
}
_lastSound = newSound;
@@ -216,6 +214,7 @@ void SoundAmiga_EoB::beginFadeOut(int delay) {
_driver->fadeOut(delay);
while (_driver->isFading() && !_vm->shouldQuit())
_vm->delay(5);
+ haltTrack();
}
void SoundAmiga_EoB::updateVolumeSettings() {
@@ -234,23 +233,4 @@ int SoundAmiga_EoB::checkTrigger() {
return _driver->getPlayDuration();
}
-void SoundAmiga_EoB::unloadLevelSounds() {
- if (_currentFile != -1) {
- _driver->flushResource(Common::String::format("L%dM1A1", _currentFile));
- _driver->flushResource(Common::String::format("L%dM2A1", _currentFile));
-
- for (int i = 1; i < 5; ++i) {
- _driver->flushResource(Common::String::format("L%dM1M%d", _currentFile, i));
- _driver->flushResource(Common::String::format("L%dM2M%d", _currentFile, i));
- }
-
- for (int i = 0; i < 2; ++i) {
- if (_levelSoundList1[_currentFile * 2 + i][0])
- _driver->flushResource(_levelSoundList1[_currentFile * 2 + i]);
- if (_levelSoundList2[_currentFile * 2 + i][0])
- _driver->flushResource(_levelSoundList2[_currentFile * 2 + i]);
- }
- }
-}
-
} // End of namespace Kyra
diff --git a/engines/kyra/sound/sound_intern.h b/engines/kyra/sound/sound_intern.h
index fbf19d742e..57afb26ab5 100644
--- a/engines/kyra/sound/sound_intern.h
+++ b/engines/kyra/sound/sound_intern.h
@@ -417,8 +417,9 @@ public:
void initAudioResourceInfo(int set, void *info);
void selectAudioResourceSet(int set);
bool hasSoundFile(uint file) const { return false; }
- void loadSoundFile(uint file);
+ void loadSoundFile(uint) {}
void loadSoundFile(Common::String file);
+ void unloadSoundFile(Common::String file);
void playTrack(uint8 track);
void haltTrack();
void playSoundEffect(uint8 track, uint8 volume = 0xFF);
@@ -428,8 +429,6 @@ public:
int checkTrigger();
private:
- void unloadLevelSounds();
-
uint8 *_fileBuffer;
KyraEngine_v1 *_vm;
@@ -438,10 +437,6 @@ private:
Common::String _lastSound;
int _currentResourceSet;
- int _currentFile;
-
- const char *const *_levelSoundList1;
- const char *const *_levelSoundList2;
bool _ready;
};