diff options
author | Robert Göffringmann | 2003-07-04 20:14:11 +0000 |
---|---|---|
committer | Robert Göffringmann | 2003-07-04 20:14:11 +0000 |
commit | 484d0a84c56652d0dba314b0583c9b2fc74cb872 (patch) | |
tree | ebb476ad75086a2e32fc1e08ce4798fbc3edd8c9 | |
parent | 3aa048d710dce762c3f79167b04a48cc450056f9 (diff) | |
download | scummvm-rg350-484d0a84c56652d0dba314b0583c9b2fc74cb872.tar.gz scummvm-rg350-484d0a84c56652d0dba314b0583c9b2fc74cb872.tar.bz2 scummvm-rg350-484d0a84c56652d0dba314b0583c9b2fc74cb872.zip |
SFX is working correctly now. also implemented queued fx and fx saving.
The bass version is now included in the savegames, too.
svn-id: r8747
-rw-r--r-- | sky/control.cpp | 30 | ||||
-rw-r--r-- | sky/control.h | 5 | ||||
-rw-r--r-- | sky/intro.cpp | 4 | ||||
-rw-r--r-- | sky/logic.cpp | 3 | ||||
-rw-r--r-- | sky/sky.cpp | 3 | ||||
-rw-r--r-- | sky/sound.cpp | 120 | ||||
-rw-r--r-- | sky/sound.h | 27 |
7 files changed, 144 insertions, 48 deletions
diff --git a/sky/control.cpp b/sky/control.cpp index fd8dc17b14..f9f069db31 100644 --- a/sky/control.cpp +++ b/sky/control.cpp @@ -115,7 +115,7 @@ void SkyTextResource::drawToScreen(bool doMask) { _system->copy_rect(_screen + _y * GAME_SCREEN_WIDTH + _x, GAME_SCREEN_WIDTH, _x, _y, cpWidth, PAN_CHAR_HEIGHT); } -SkyControl::SkyControl(SkyScreen *screen, SkyDisk *disk, SkyMouse *mouse, SkyText *text, SkyMusicBase *music, SkyLogic *logic, OSystem *system, const char *savePath) { +SkyControl::SkyControl(SkyScreen *screen, SkyDisk *disk, SkyMouse *mouse, SkyText *text, SkyMusicBase *music, SkyLogic *logic, SkySound *sound, OSystem *system, const char *savePath) { _skyScreen = screen; _skyDisk = disk; @@ -123,6 +123,7 @@ SkyControl::SkyControl(SkyScreen *screen, SkyDisk *disk, SkyMouse *mouse, SkyTex _skyText = text; _skyMusic = music; _skyLogic = logic; + _skySound = sound; _system = system; _savePath = savePath; _memListRoot = NULL; @@ -993,9 +994,11 @@ uint32 SkyControl::prepareSaveData(uint8 *destBuf) { uint8 *destPos = destBuf + 4; STOSD(destPos, SAVE_FILE_REVISION); - STOSD(destPos, _skyMusic->giveCurrentMusic()); + STOSD(destPos, SkyState::_systemVars.gameVersion); + STOSW(destPos, _skySound->_saveSounds[0]); + STOSW(destPos, _skySound->_saveSounds[1]); - //TODO: save queued sfx + STOSD(destPos, _skyMusic->giveCurrentMusic()); STOSD(destPos, _skyText->giveCurrentCharSet()); STOSD(destPos, _savedMouse); STOSD(destPos, SkyState::_systemVars.currentPalette); @@ -1174,7 +1177,19 @@ uint16 SkyControl::parseSaveData(uint8 *srcBuf) { freeMemList(); // memory from last restore isn't needed anymore - uint32 music, charSet, mouseType, palette; + uint32 music, charSet, mouseType, palette, gameVersion; + + if (saveRev >= 3) { + LODSD(srcPos, gameVersion); + if (gameVersion != SkyState::_systemVars.gameVersion) { + printf("This savegame was created by Beneath a Steel Sky V.0.0%03d\n",gameVersion); + printf("It cannot be loaded by this version (%0.0%3d)\n",SkyState::_systemVars.gameVersion); + return RESTORE_FAILED; + } + LODSW(srcPos, _skySound->_saveSounds[0]); + LODSW(srcPos, _skySound->_saveSounds[1]); + _skySound->restoreSfx(); + } LODSD(srcPos, music); LODSD(srcPos, charSet); LODSD(srcPos, mouseType); @@ -1315,9 +1330,12 @@ void SkyControl::showGameQuitMsg(bool useScreen) { uint8 *textBuf2 = (uint8*)malloc(GAME_SCREEN_WIDTH * 14 + sizeof(dataFileHeader)); uint8 textNum; uint8 *screenData; - if (useScreen) + if (useScreen) { + if (_skyScreen->sequenceRunning()) + _skyScreen->stopSequence(); + screenData = _skyScreen->giveCurrent(); - else + } else screenData = _screenBuf; switch (SkyState::_systemVars.language) { case DE_DEU: textNum = 1; break; diff --git a/sky/control.h b/sky/control.h index 40590828d7..f96bafcf64 100644 --- a/sky/control.h +++ b/sky/control.h @@ -106,7 +106,7 @@ class SkyMouse; #define SAVE_GRAFX 32 #define SAVE_TURNP 64 -#define SAVE_FILE_REVISION 2 +#define SAVE_FILE_REVISION 3 struct AllocedMem { uint16 *mem; @@ -145,7 +145,7 @@ private: class SkyControl { public: - SkyControl(SkyScreen *screen, SkyDisk *disk, SkyMouse *mouse, SkyText *text, SkyMusicBase *music, SkyLogic *logic, OSystem *system, const char *savePath); + SkyControl(SkyScreen *screen, SkyDisk *disk, SkyMouse *mouse, SkyText *text, SkyMusicBase *music, SkyLogic *logic, SkySound *sound, OSystem *system, const char *savePath); void doControlPanel(void); void doLoadSavePanel(void); void restartGame(void); @@ -205,6 +205,7 @@ private: SkyText *_skyText; SkyMusicBase *_skyMusic; SkyLogic *_skyLogic; + SkySound *_skySound; OSystem *_system; int _mouseX, _mouseY; bool _mouseClicked; diff --git a/sky/intro.cpp b/sky/intro.cpp index d4fb32ebcc..44105fcfea 100644 --- a/sky/intro.cpp +++ b/sky/intro.cpp @@ -492,7 +492,7 @@ void SkyState::removeText(uint32 *&cmdPtr) { void SkyState::introFx(uint32 *&cmdPtr) { _mixer->stopAll(); - _skySound->playSound((uint16)cmdPtr[2], (uint16)cmdPtr[3]); + _skySound->playSound((uint16)cmdPtr[2], (uint16)cmdPtr[3], 0); cmdPtr += 4; } @@ -501,6 +501,6 @@ void SkyState::introVol(uint32 *&cmdPtr) { // HACK: for some reason, the mixer will only stop playing // looping sounds if you do it using SoundMixer::stopAll(); _mixer->stopAll(); - _skySound->playSound(1, (uint16)(cmdPtr[2] & 0x7F)); + _skySound->playSound(1, (uint16)(cmdPtr[2] & 0x7F), 0); cmdPtr += 3; } diff --git a/sky/logic.cpp b/sky/logic.cpp index f2f0efc4c0..7a3607a3d5 100644 --- a/sky/logic.cpp +++ b/sky/logic.cpp @@ -2373,7 +2373,8 @@ bool SkyLogic::fnSetFont(uint32 font, uint32 b, uint32 c) { } bool SkyLogic::fnStartFx(uint32 sound, uint32 b, uint32 c) { - return _skySound->fnStartFx(sound); + _skySound->fnStartFx(sound, (uint8)(b & 1)); + return true; } bool SkyLogic::fnStopFx(uint32 a, uint32 b, uint32 c) { diff --git a/sky/sky.cpp b/sky/sky.cpp index 0c709f8d55..b7a07ef335 100644 --- a/sky/sky.cpp +++ b/sky/sky.cpp @@ -149,6 +149,7 @@ void SkyState::go() { /*if ((_key_pressed == 27) && (!_systemVars.pastIntro)) _skyControl->restartGame();*/ + _skySound->checkFxQueue(); _skyMouse->mouseEngine((uint16)_sdl_mouse_x, (uint16)_sdl_mouse_y); _skyLogic->engine(); if (!_skyLogic->checkProtection()) { // don't let copy prot. screen flash up @@ -202,7 +203,7 @@ void SkyState::initialise(void) { _timer = Engine::_timer; // initialize timer *after* _skyScreen has been initialized. _timer->installProcedure(&timerHandler, 1000000 / 50); //call 50 times per second - _skyControl = new SkyControl(_skyScreen, _skyDisk, _skyMouse, _skyText, _skyMusic, _skyLogic, _system, getSavePath()); + _skyControl = new SkyControl(_skyScreen, _skyDisk, _skyMouse, _skyText, _skyMusic, _skyLogic, _skySound, _system, getSavePath()); _skyLogic->useControlInstance(_skyControl); if (_systemVars.gameVersion == 288) diff --git a/sky/sound.cpp b/sky/sound.cpp index be8f22ff60..c174e2f05b 100644 --- a/sky/sound.cpp +++ b/sky/sound.cpp @@ -1005,6 +1005,13 @@ static Sfx *musicList[] = { &fx_25_weld // 394 my anchor weld bodge }; +SfxQueue SkySound::_sfxQueue[MAX_QUEUED_FX] = { + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0}, + { 0, 0, 0, 0} +}; + SkySound::SkySound(SoundMixer *mixer, SkyDisk *pDisk) { _skyDisk = pDisk; _soundData = NULL; @@ -1012,9 +1019,10 @@ SkySound::SkySound(SoundMixer *mixer, SkyDisk *pDisk) { _voiceHandle = 0; _effectHandle = 0; _bgSoundHandle = 0; - _ingameSound = 0; _ingameSpeech = 0; - _sfxPaused = false; + _ingameSound0 = _ingameSound1 = 0; + _slot0 = _slot1 = -1; + _saveSounds[0] = _saveSounds[1] = 0xFFFF; } SkySound::~SkySound(void) { @@ -1048,8 +1056,8 @@ int SkySound::playSound(byte *sound, uint32 size, PlayingSoundHandle *handle) { void SkySound::loadSection(uint8 pSection) { - if (_ingameSound) _mixer->stop(_ingameSound - 1); - _ingameSound = 0; + fnStopFx(); + if (_soundData) free(_soundData); _soundData = _skyDisk->loadFile(pSection * 4 + SOUND_FILE_BASE, NULL); if ((_soundData[0x7E] != 0x3C) || (_soundData[0xA5] != 0x8D) || (_soundData[0xA6] != 0x1E) || @@ -1060,9 +1068,23 @@ void SkySound::loadSection(uint8 pSection) { _sfxBaseOfs = (_soundData[0xB0] << 8) | _soundData[0xAF]; _sampleRates = _soundData + sRateTabOfs; _sfxInfo = _soundData + _sfxBaseOfs; + for (uint8 cnt = 0; cnt < 4; cnt++) + _sfxQueue[cnt].count = 0; } -void SkySound::playSound(uint16 sound, uint16 volume) { +void SkySound::playSound(uint16 sound, uint16 volume, uint8 channel) { + + if (channel == 0) { + if (_slot0 >= 0) { + _mixer->stop(_slot0); + _slot0 = -1; + } + } else { + if (_slot1 >= 0) { + _mixer->stop(_slot1); + _slot1 = -1; + } + } if (!_soundData) { warning("SkySound::playSound(%04X, %04X) called with a section having been loaded.\n", sound, volume); @@ -1070,8 +1092,7 @@ void SkySound::playSound(uint16 sound, uint16 volume) { } if (sound > _soundsTotal) { - if (sound & 0x80) warning("SkySound::playSound(%04X, %04X) not implemented.\n", sound, volume); - else warning("SkySound::playSound(%04X, %04X) ignored.\n", sound, volume); + debug(5, "SkySound::playSound %d ignored, only %d sfx in file.\n", sound, _soundsTotal); return ; } @@ -1080,30 +1101,28 @@ void SkySound::playSound(uint16 sound, uint16 volume) { // note: all those tables are big endian. Don't ask me why. *sigh* uint16 sampleRate = (_sampleRates[sound << 2] << 8) | _sampleRates[(sound << 2) | 1]; - uint16 dataOfs = ((_sfxInfo[sound << 3] << 8) | _sfxInfo[(sound << 3) | 1]) << 4; + uint32 dataOfs = ((_sfxInfo[sound << 3] << 8) | _sfxInfo[(sound << 3) | 1]) << 4; dataOfs += _sfxBaseOfs; uint16 dataSize = (_sfxInfo[(sound << 3) | 2] << 8) | _sfxInfo[(sound << 3) | 3]; uint16 dataLoop = (_sfxInfo[(sound << 3) | 6] << 8) | _sfxInfo[(sound << 3) | 7]; byte flags = SoundMixer::FLAG_UNSIGNED; - if (dataSize == dataLoop) { - //flags |= SoundMixer::FLAG_LOOP; - } + + if (dataSize == dataLoop) + flags |= SoundMixer::FLAG_LOOP; - if (_ingameSound > 0) _mixer->stop(_ingameSound - 1); _mixer->setVolume(volume); - _mixer->playRaw(&_ingameSound, _soundData + dataOfs, dataSize, sampleRate, flags); + if (channel == 0) + _slot0 = _mixer->playRaw(&_ingameSound0, _soundData + dataOfs, dataSize, sampleRate, flags); + else + _slot1 = _mixer->playRaw(&_ingameSound1, _soundData + dataOfs, dataSize, sampleRate, flags); } -void SkySound::fnPauseFx(void) { +void SkySound::fnStartFx(uint32 sound, uint8 channel) { - if (_ingameSound) _mixer->stop(_ingameSound - 1); - _sfxPaused = true; -} - -bool SkySound::fnStartFx(uint32 sound) { - if (sound < 256 || sound > MAX_FX_NUMBER || _sfxPaused || (SkyState::_systemVars.systemFlags & SF_FX_OFF)) - return true; + _saveSounds[channel] = 0xFFFF; + if (sound < 256 || sound > MAX_FX_NUMBER || (SkyState::_systemVars.systemFlags & SF_FX_OFF)) + return; uint8 screen = (uint8)(SkyLogic::_scriptVariables[SCREEN] & 0xff); if (sound == 278 && screen == 25) // is this weld in room 25 @@ -1119,7 +1138,7 @@ bool SkySound::fnStartFx(uint32 sound) { while (roomList[i].room != screen) { // check rooms i++; if (roomList[i].room == 0xff) - return true; + return; } // get fx volume @@ -1137,14 +1156,59 @@ bool SkySound::fnStartFx(uint32 sound) { // Check the flags, the sound may come on after a delay. if (sfx->flags & SFXF_START_DELAY) { - // queue sound + for (uint8 cnt = 0; cnt < MAX_QUEUED_FX; cnt++) { + if (_sfxQueue[cnt].count == 0) { + _sfxQueue[cnt].chan = channel; + _sfxQueue[cnt].fxNo = sfx->soundNo; + _sfxQueue[cnt].vol = volume; + _sfxQueue[cnt].count = sfx->flags & 0x7F; + return; + } + } + return; // ignore sound if it can't be queued } - //if (sfx->flags & SFXF_SAVE) - // save_fx_0[stfx_cur_chn] = sound; + if (sfx->flags & SFXF_SAVE) + _saveSounds[channel] = sfx->soundNo | (volume << 8); - playSound(sfx->soundNo, volume); - return true; + playSound(sfx->soundNo, volume, channel); +} + +void SkySound::checkFxQueue(void) { + for (uint8 cnt = 0; cnt < MAX_QUEUED_FX; cnt++) { + if (_sfxQueue[cnt].count) { + _sfxQueue[cnt].count--; + if (_sfxQueue[cnt].count == 0) + playSound(_sfxQueue[cnt].fxNo, _sfxQueue[cnt].vol, _sfxQueue[cnt].chan); + } + } +} + +void SkySound::restoreSfx(void) { + + // queue sfx, so they will be started when the player exits the control panel + memset(_sfxQueue, 0, sizeof(_sfxQueue)); + uint8 queueSlot = 0; + if (_saveSounds[0] != 0xFFFF) { + _sfxQueue[queueSlot].fxNo = (uint8)_saveSounds[0]; + _sfxQueue[queueSlot].vol = (uint8)(_saveSounds[0] >> 8); + _sfxQueue[queueSlot].chan = 0; + _sfxQueue[queueSlot].count = 1; + queueSlot++; + } + if (_saveSounds[1] != 0xFFFF) { + _sfxQueue[queueSlot].fxNo = (uint8)_saveSounds[1]; + _sfxQueue[queueSlot].vol = (uint8)(_saveSounds[1] >> 8); + _sfxQueue[queueSlot].chan = 1; + _sfxQueue[queueSlot].count = 1; + } +} + +void SkySound::fnStopFx(void) { + if (_slot0 >= 0) _mixer->stop(_slot0); + if (_slot1 >= 0) _mixer->stop(_slot1); + _slot0 = _slot1 = -1; + _saveSounds[0] = _saveSounds[1] = 0xFFFF; } bool SkySound::startSpeech(uint16 textNum) { @@ -1168,6 +1232,6 @@ bool SkySound::startSpeech(uint16 textNum) { // TODO: implement pre_after_table_area to find and prefetch file for next speech - _mixer->playRaw(&_ingameSpeech, playBuffer, speechSize - 64, 11025, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE); + int slt = _mixer->playRaw(&_ingameSpeech, playBuffer, speechSize - 64, 11025, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE); return true; } diff --git a/sky/sound.h b/sky/sound.h index 93e6cd9e26..8a64655589 100644 --- a/sky/sound.h +++ b/sky/sound.h @@ -26,6 +26,12 @@ #include "sky/disk.h" #include "common/engine.h" +struct SfxQueue { + uint8 count, fxNo, chan, vol; +}; + +#define MAX_QUEUED_FX 4 + class SkySound { protected: @@ -35,7 +41,9 @@ public: PlayingSoundHandle _voiceHandle; PlayingSoundHandle _effectHandle; PlayingSoundHandle _bgSoundHandle; - PlayingSoundHandle _ingameSound, _ingameSpeech; + PlayingSoundHandle _ingameSound0, _ingameSound1, _ingameSpeech; + + uint16 _saveSounds[2]; protected: @@ -48,23 +56,26 @@ public: int playBgSound(byte *sound, uint32 size); void loadSection(uint8 pSection); - void playSound(uint16 sound, uint16 volume); - bool fnStartFx(uint32 sound); + void playSound(uint16 sound, uint16 volume, uint8 channel); + void fnStartFx(uint32 sound, uint8 channel); bool startSpeech(uint16 textNum); bool speechFinished(void) { return _ingameSpeech == 0; }; - void fnPauseFx(void); - void fnUnPauseFx(void) { _sfxPaused = false; }; - void fnStopFx(void) { if (_ingameSound) _mixer->stop(_ingameSound - 1); }; + void fnPauseFx(void) { _mixer->pause(true); }; + void fnUnPauseFx(void) { _mixer->pause(false); }; + void fnStopFx(void); + void checkFxQueue(void); + void restoreSfx(void); + uint8 _soundsTotal; private: SkyDisk *_skyDisk; - uint8 _soundsTotal; uint16 _sfxBaseOfs; uint8 *_soundData; uint8 *_sampleRates, *_sfxInfo; - bool _sfxPaused; + int _slot0, _slot1; static uint16 _speechConvertTable[8]; + static SfxQueue _sfxQueue[MAX_QUEUED_FX]; }; #endif |