aboutsummaryrefslogtreecommitdiff
path: root/engines/queen/sound.cpp
diff options
context:
space:
mode:
authorGregory Montoir2007-02-21 20:27:48 +0000
committerGregory Montoir2007-02-21 20:27:48 +0000
commit948630c3b452cdfd480c7f6fe9398bcda57501d7 (patch)
tree2c8de196552036b81861c91bbcec4fe86ca2cbac /engines/queen/sound.cpp
parent098bcc2fe88220f6ff656d6f42beabc55b2bf8d9 (diff)
downloadscummvm-rg350-948630c3b452cdfd480c7f6fe9398bcda57501d7.tar.gz
scummvm-rg350-948630c3b452cdfd480c7f6fe9398bcda57501d7.tar.bz2
scummvm-rg350-948630c3b452cdfd480c7f6fe9398bcda57501d7.zip
added initial support for FOTAQ amiga versions
svn-id: r25769
Diffstat (limited to 'engines/queen/sound.cpp')
-rw-r--r--engines/queen/sound.cpp643
1 files changed, 507 insertions, 136 deletions
diff --git a/engines/queen/sound.cpp b/engines/queen/sound.cpp
index 917351f3da..e228d6a1dd 100644
--- a/engines/queen/sound.cpp
+++ b/engines/queen/sound.cpp
@@ -21,45 +21,47 @@
*/
#include "common/stdafx.h"
+#include "common/config-manager.h"
#include "common/endian.h"
+#include "common/stream.h"
#include "queen/sound.h"
-
#include "queen/input.h"
+#include "queen/logic.h"
#include "queen/music.h"
#include "queen/queen.h"
#include "queen/resource.h"
#include "sound/flac.h"
+#include "sound/mididrv.h"
#include "sound/mp3.h"
#include "sound/vorbis.h"
#define SB_HEADER_SIZE_V104 110
#define SB_HEADER_SIZE_V110 122
-#define STOP_MUSIC -1
namespace Queen {
-class SilentSound : public Sound {
+class SilentSound : public PCSound {
public:
- SilentSound(Audio::Mixer *mixer, QueenEngine *vm) : Sound(mixer, vm) {}
+ SilentSound(Audio::Mixer *mixer, QueenEngine *vm) : PCSound(mixer, vm) {}
protected:
void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) {
// Do nothing
}
};
-class SBSound : public Sound {
+class SBSound : public PCSound {
public:
- SBSound(Audio::Mixer *mixer, QueenEngine *vm) : Sound(mixer, vm) {}
+ SBSound(Audio::Mixer *mixer, QueenEngine *vm) : PCSound(mixer, vm) {}
protected:
void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle);
};
#ifdef USE_MAD
-class MP3Sound : public Sound {
+class MP3Sound : public PCSound {
public:
- MP3Sound(Audio::Mixer *mixer, QueenEngine *vm) : Sound(mixer, vm) {}
+ MP3Sound(Audio::Mixer *mixer, QueenEngine *vm) : PCSound(mixer, vm) {}
protected:
void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) {
_mixer->playInputStream(Audio::Mixer::kSFXSoundType, soundHandle, Audio::makeMP3Stream(f, size));
@@ -68,9 +70,9 @@ protected:
#endif
#ifdef USE_VORBIS
-class OGGSound : public Sound {
+class OGGSound : public PCSound {
public:
- OGGSound(Audio::Mixer *mixer, QueenEngine *vm) : Sound(mixer, vm) {}
+ OGGSound(Audio::Mixer *mixer, QueenEngine *vm) : PCSound(mixer, vm) {}
protected:
void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) {
_mixer->playInputStream(Audio::Mixer::kSFXSoundType, soundHandle, Audio::makeVorbisStream(f, size));
@@ -79,9 +81,9 @@ protected:
#endif
#ifdef USE_FLAC
-class FLACSound : public Sound {
+class FLACSound : public PCSound {
public:
- FLACSound(Audio::Mixer *mixer, QueenEngine *vm) : Sound(mixer, vm) {};
+ FLACSound(Audio::Mixer *mixer, QueenEngine *vm) : PCSound(mixer, vm) {};
protected:
void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) {
_mixer->playInputStream(Audio::Mixer::kSFXSoundType, soundHandle, Audio::makeFlacStream(f, size));
@@ -90,15 +92,13 @@ protected:
#endif // #ifdef USE_FLAC
Sound::Sound(Audio::Mixer *mixer, QueenEngine *vm) :
- _mixer(mixer), _vm(vm), _sfxToggle(true), _speechToggle(true), _musicToggle(true), _lastOverride(0) {
-#ifdef ENABLE_AMIGA_MUSIC
- _lastModuleOverride = -1;
-#endif
+ _mixer(mixer), _vm(vm), _sfxToggle(true), _speechToggle(true), _musicToggle(true),
+ _speechSfxExists(false), _lastOverride(0), _masterVolume(0) {
}
Sound *Sound::makeSoundInstance(Audio::Mixer *mixer, QueenEngine *vm, uint8 compression) {
- if (!mixer->isReady())
- return new SilentSound(mixer, vm);
+ if (vm->resource()->getPlatform() == Common::kPlatformAmiga)
+ return new AmigaSound(mixer, vm);
switch (compression) {
case COMPRESSION_NONE:
@@ -130,135 +130,52 @@ Sound *Sound::makeSoundInstance(Audio::Mixer *mixer, QueenEngine *vm, uint8 comp
}
}
-void Sound::waitFinished(bool isSpeech) {
- while (_mixer->isSoundHandleActive(isSpeech ? _speechHandle : _sfxHandle))
- _vm->input()->delay(10);
-}
-
-void Sound::playSfx(uint16 sfx) {
- if (sfxOn() && sfx != 0) {
-#ifndef PALMOS_68K
- playSound(_sfxName[sfx - 1], false);
-#else
- playSound(_sfxName + 10 * (sfx - 1), false); // saved as 8char + /0/0
-#endif
- }
-}
-
-void Sound::playSpeech(const char *base) {
- if (speechOn()) {
- playSound(base, true);
- }
+void Sound::saveState(byte *&ptr) {
+ WRITE_BE_UINT16(ptr, _lastOverride); ptr += 2;
}
-void Sound::playSound(const char *base, bool isSpeech) {
- char name[13];
- strcpy(name, base);
- // alter filename to add zeros and append ".SB"
- for (int i = 0; i < 8; i++) {
- if (name[i] == ' ')
- name[i] = '0';
- }
- strcat(name, ".SB");
- waitFinished(isSpeech);
- uint32 size;
- Common::File *f = _vm->resource()->findSound(name, &size);
- if (f) {
- playSoundData(f, size, isSpeech ? &_speechHandle : &_sfxHandle);
- _speechSfxExists = isSpeech;
- } else {
- _speechSfxExists = false;
- }
+void Sound::loadState(uint32 ver, byte *&ptr) {
+ _lastOverride = (int16)READ_BE_INT16(ptr); ptr += 2;
}
-#ifdef ENABLE_AMIGA_MUSIC
-
-static struct {
- const char *name;
- uint8 songNum;
- uint8 remapSongNumTable[6];
-} amigaMusicData[] = {
- { "HOTEL", 1, { 1, 2, 39, 0 } },
- { "HOTEL", 2, { 20, 30, 34, 0 } },
- { "HOTEL", 3, { 19, 0 } },
- { "HOTEL", 4, { 29, 35, 36, 0 } },
- { "JUNG", 1, { 40, 0 } },
- { "JUNG", 2, { 3, 38, 89, 0 } },
- { "TEMPLE", 1, { 54, 0 } },
- { "TEMPLE", 2, { 12, 0 } },
- { "TEMPLE", 3, { 7, 9, 10, 11, 0 } },
- { "TEMPLE", 4, { 31, 0 } },
- { "FLODA", 1, { 16, 0 } },
- { "FLODA", 2, { 17, 0 } },
- { "FLODA", 3, { 13, 0 } },
- { "FLODA", 4, { 41, 0 } },
- { "FLODA", 5, { 30, 43, 0 } },
- { "TITLE", 1, { 67, 88, 203, 0 } },
- { "AWESTRUK", 1, { 37, 52, 90, 196, 0 } },
- { "'JUNGLE'", 1, { 91, 0 } },
- { "FRANK", 1, { 46, 0 } },
- { "BOB", 1, { 6, 0 } },
- { "AZURA", 1, { 44, 53, 204, 0 } },
- { "FORT", 1, { 21, 0 } },
- { "ROCKET", 1, { 32, 194, 195, 0 } },
- { "ROBOT", 1, { 92, 0 } }
-};
-
-void Sound::playSong(int16 songNum) {
- debug(2, "Sound::playSong %d override %d/%d", songNum, _lastModuleOverride, _lastOverride);
+PCSound::PCSound(Audio::Mixer *mixer, QueenEngine *vm)
+ : Sound(mixer, vm) {
- const char *moduleName = 0;
- for (int i = 0; i < ARRAYSIZE(amigaMusicData) && !moduleName; ++i) {
- for (int j = 0; amigaMusicData[i].remapSongNumTable[j] != 0; ++j) {
- if (amigaMusicData[i].remapSongNumTable[j] == songNum) {
- moduleName = amigaMusicData[i].name;
- songNum = amigaMusicData[i].songNum;
+ int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
+ bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32"));
- if (_lastModuleOverride == i && _lastOverride == songNum)
- return;
+ MidiDriver *driver = MidiDriver::createMidi(midiDriver);
+ if (native_mt32)
+ driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
- _lastModuleOverride = i;
- _lastOverride = songNum;
- break;
- }
- }
- }
- if (!moduleName)
- return;
-
- _mixer->stopHandle(_musicHandle);
-
- debug(1, "playAmigaSong name '%s' subsong %d", moduleName, songNum);
-
- char buf[16];
- sprintf(buf, "%s.SNG", moduleName);
- Common::File fsng;
- if (!fsng.open(buf))
- return;
-
- sprintf(buf, "%s.INS", moduleName);
- Common::File fins;
- if (!fins.open(buf))
- return;
+ _music = new Music(driver, vm);
+ _music->hasNativeMT32(native_mt32);
+}
- Audio::AudioStream *rjp1Stream = Audio::makeRjp1Stream(&fsng, &fins, songNum);
- if (rjp1Stream) {
- _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, rjp1Stream);
- }
+PCSound::~PCSound() {
+ delete _music;
}
+void PCSound::playSfx(uint16 sfx) {
+ if (sfxOn() && sfx != 0) {
+#ifndef PALMOS_68K
+ playSound(_sfxName[sfx - 1], false);
#else
+ playSound(_sfxName + 10 * (sfx - 1), false); // saved as 8char + /0/0
+#endif
+ }
+}
-void Sound::playSong(int16 songNum) {
+void PCSound::playSong(int16 songNum) {
if (songNum <= 0) {
- _vm->music()->stopSong();
+ _music->stopSong();
return;
}
int16 newTune;
if (_vm->resource()->isDemo()) {
if (songNum == 17) {
- _vm->music()->stopSong();
+ _music->stopSong();
return;
}
newTune = _songDemo[songNum - 1].tuneList[0] - 1;
@@ -281,25 +198,58 @@ void Sound::playSong(int16 songNum) {
break;
// Alter song settings (such as volume) and exit
case 2:
- _vm->music()->toggleVChange();
+ _music->toggleVChange();
default:
return;
}
_lastOverride = songNum;
- _vm->music()->queueTuneList(newTune);
- _vm->music()->playMusic();
+ _music->queueTuneList(newTune);
+ _music->playMusic();
}
-#endif // ENABLE_AMIGA_MUSIC
+void PCSound::stopSong() {
+ _music->stopSong();
+}
-void Sound::saveState(byte *&ptr) {
- WRITE_BE_UINT16(ptr, _lastOverride); ptr += 2;
+void PCSound::playSpeech(const char *base) {
+ if (speechOn()) {
+ playSound(base, true);
+ }
}
-void Sound::loadState(uint32 ver, byte *&ptr) {
- _lastOverride = (int16)READ_BE_INT16(ptr); ptr += 2;
+void PCSound::setVolume(int vol) {
+ _music->setVolume(vol);
+}
+
+int PCSound::volume() {
+ return _music->volume();
+}
+
+void PCSound::waitFinished(bool isSpeech) {
+ while (_mixer->isSoundHandleActive(isSpeech ? _speechHandle : _sfxHandle))
+ _vm->input()->delay(10);
+}
+
+void PCSound::playSound(const char *base, bool isSpeech) {
+ char name[13];
+ strcpy(name, base);
+ // alter filename to add zeros and append ".SB"
+ for (int i = 0; i < 8; i++) {
+ if (name[i] == ' ')
+ name[i] = '0';
+ }
+ strcat(name, ".SB");
+ waitFinished(isSpeech);
+ uint32 size;
+ Common::File *f = _vm->resource()->findSound(name, &size);
+ if (f) {
+ playSoundData(f, size, isSpeech ? &_speechHandle : &_sfxHandle);
+ _speechSfxExists = isSpeech;
+ } else {
+ _speechSfxExists = false;
+ }
}
void SBSound::playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) {
@@ -328,4 +278,425 @@ void SBSound::playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *so
}
}
+AmigaSound::AmigaSound(Audio::Mixer *mixer, QueenEngine *vm)
+ : Sound(mixer, vm), _fanfareRestore(0), _fanfareCount(0), _fluteCount(0) {
+}
+
+void AmigaSound::playSfx(uint16 sfx) {
+ if (_vm->logic()->currentRoom() == 111) {
+ // lightning sound
+ playSound("88SSSSSS");
+ }
+}
+
+void AmigaSound::playSong(int16 song) {
+ debug(2, "Sound::playSong %d override %d", song, _lastOverride);
+
+ if (song < 0) {
+ stopSong();
+ return;
+ }
+
+ // remap song numbers for the Amiga
+ switch (song)
+ {
+ case 1:
+ case 2:
+ song = 39;
+ break;
+ case 37:
+ case 52:
+ case 196:
+ song = 90;
+ break;
+ case 38:
+ case 89:
+ song = 3;
+ break;
+ case 24:
+ case 158:
+ song = 117;
+ break;
+ case 71:
+ case 72:
+ case 73:
+ case 75:
+ song = 133;
+ break;
+ case 203:
+ song = 67;
+ break;
+ case 145:
+ song = 140;
+ break;
+ case 53:
+ case 204:
+ song = 44;
+ break;
+ case 136:
+ case 142:
+ case 179:
+ song = 86;
+ break;
+ case 101:
+ case 102:
+ case 143:
+ song = 188;
+ break;
+ case 65:
+ case 62:
+ song = 69;
+ break;
+ case 118:
+ case 119:
+ song = 137;
+ break;
+ case 130:
+ case 131:
+ song = 59;
+ break;
+ case 174:
+ case 175:
+ song = 57;
+ break;
+ case 171:
+ case 121:
+ song = 137;
+ break;
+ case 138:
+ case 170:
+ case 149:
+ song = 28;
+ break;
+ case 122:
+ case 180:
+ case 83:
+ case 98:
+ song = 83;
+ break;
+ case 20:
+ case 33:
+ song = 34;
+ break;
+ case 29:
+ case 35:
+ song = 36;
+ break;
+ case 7:
+ case 9:
+ case 10:
+ song = 11;
+ break;
+ case 110:
+ song = 94;
+ break;
+ case 111:
+ song = 95;
+ break;
+ case 30:
+ song = 43;
+ break;
+ case 76:
+ song = 27;
+ break;
+ case 194:
+ case 195:
+ song = 32;
+ break;
+ }
+
+ if (_lastOverride != 32 && _lastOverride != 44) {
+ if (playSpecialSfx(song)) {
+ return;
+ }
+ }
+
+ if (_lastOverride == song && _mixer->isSoundHandleActive(_modHandle)) {
+ return;
+ }
+ switch (song) {
+ // hotel
+ case 39:
+ playModule("HOTEL", 1);
+ break;
+ case 19:
+ playModule("HOTEL", 3);
+ break;
+ case 34:
+ playModule("HOTEL", 2);
+ break;
+ case 36:
+ playModule("HOTEL", 4);
+ _fanfareRestore = _lastOverride;
+ _fanfareCount = 60;
+ break;
+ // jungle
+ case 40:
+ playModule("JUNG", 1);
+ _fanfareRestore = _lastOverride;
+ _fanfareCount = 80;
+ _fluteCount = 100;
+ break;
+ case 3:
+ playModule("JUNG", 2);
+ _fluteCount = 100;
+ break;
+ // temple
+ case 54:
+ playModule("TEMPLE", 1);
+ break;
+ case 12:
+ playModule("TEMPLE", 2);
+ break;
+ case 11:
+ playModule("TEMPLE", 3);
+ break;
+ case 31:
+ playModule("TEMPLE", 4);
+ _fanfareRestore = _lastOverride;
+ _fanfareCount = 80;
+ break;
+ // floda
+ case 41:
+ playModule("FLODA", 4);
+ _fanfareRestore = _lastOverride;
+ _fanfareCount = 60;
+ break;
+ case 13:
+ playModule("FLODA", 3);
+ break;
+ case 16:
+ playModule("FLODA", 1);
+ break;
+ case 17:
+ playModule("FLODA", 2);
+ break;
+ case 43:
+ playModule("FLODA", 5);
+ break;
+ // end credits
+ case 67:
+ playModule("TITLE", 1);
+ break;
+ // intro credits
+ case 88:
+ playModule("TITLE", 1);
+ break;
+ // valley
+ case 90:
+ playModule("AWESTRUK", 1);
+ break;
+ // confrontation
+ case 91:
+ playModule("'JUNGLE'", 1);
+ break;
+ // Frank
+ case 46:
+ playModule("FRANK", 1);
+ break;
+ // trader bob
+ case 6:
+ playModule("BOB", 1);
+ break;
+ // azura
+ case 44:
+ playModule("AZURA", 1);
+ break;
+ // amazon fortress
+ case 21:
+ playModule("FORT", 1);
+ break;
+ // rocket
+ case 32:
+ playModule("ROCKET", 1);
+ break;
+ // robot
+ case 92:
+ playModule("ROBOT", 1);
+ break;
+ default:
+ // song not available in the amiga version
+ return;
+ }
+ _lastOverride = song;
+}
+
+void AmigaSound::stopSfx() {
+ _mixer->stopHandle(_sfxHandle);
+}
+
+void AmigaSound::stopSong() {
+ _mixer->stopHandle(_modHandle);
+ _fanfareCount = _fluteCount = 0;
+}
+
+void AmigaSound::updateMusic() {
+ if (_fanfareCount > 0) {
+ --_fanfareCount;
+ if (_fanfareCount == 0) {
+ playSong(_fanfareRestore);
+ }
+ }
+ if (_fluteCount > 0 && (_lastOverride == 40 || _lastOverride == 3)) {
+ --_fluteCount;
+ if (_fluteCount == 0) {
+// playPattern(3, 5 + (getRandomNumber() & 7));
+ _fluteCount = 100;
+ }
+ }
+}
+
+void AmigaSound::playSound(const char *base) {
+ char soundName[20];
+ sprintf(soundName, "%s.AMR", base);
+
+ uint32 soundSize;
+ Common::File *f = _vm->resource()->findSound(soundName, &soundSize);
+ if (f) {
+ uint8 *soundData = (uint8 *)malloc(soundSize);
+ if (soundData) {
+ f->read(soundData, soundSize);
+ byte flags = Audio::Mixer::FLAG_AUTOFREE;
+ _mixer->playRaw(Audio::Mixer::kSFXSoundType, &_sfxHandle, soundData, soundSize, 11025, flags);
+ }
+ }
+}
+
+void AmigaSound::playModule(const char *base, int song) {
+ char name[20];
+
+ // load song/pattern data
+ uint32 sngDataSize;
+ sprintf(name, "%s.SNG", base);
+ uint8 *sngData = _vm->resource()->loadFile(name, 0, &sngDataSize);
+ Common::MemoryReadStream sngStr(sngData, sngDataSize);
+
+ // load instruments/wave data
+ uint32 insDataSize;
+ sprintf(name, "%s.INS", base);
+ uint8 *insData = _vm->resource()->loadFile(name, 0, &insDataSize);
+ Common::MemoryReadStream insStr(insData, insDataSize);
+
+ _mixer->stopHandle(_modHandle);
+ Audio::AudioStream *stream = Audio::makeRjp1Stream(&sngStr, &insStr, song, _mixer->getOutputRate());
+ if (stream) {
+ _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_modHandle, stream);
+ }
+
+ delete[] sngData;
+ delete[] insData;
+
+ _fanfareCount = 0;
+}
+
+bool AmigaSound::playSpecialSfx(int16 sfx) {
+ switch (sfx) {
+ case 5: // normal volume
+ break;
+ case 15: // soft volume
+ break;
+ case 14: // medium volume
+ break;
+ case 25: // open door
+ playSound("116BSSSS");
+ break;
+ case 26: // close door
+ playSound("105ASSSS");
+ break;
+ case 56: // light switch
+ playSound("27SSSSSS");
+ break;
+ case 57: // hydraulic doors open
+ playSound("96SSSSSS");
+ break;
+ case 58: // hydraulic doors close
+ playSound("97SSSSSS");
+ break;
+ case 59: // metallic door slams
+ playSound("105SSSSS");
+ break;
+ case 63: // oracle rezzes in
+ playSound("132SSSSS");
+ break;
+ case 27: // cloth slide 1
+ playSound("135SSSSS");
+ break;
+ case 83: // splash
+ playSound("18SSSSSS");
+ break;
+ case 85: // agression enhancer
+ playSound("138BSSSS");
+ break;
+ case 68: // dino ray
+ playSound("138SSSSS");
+ break;
+ case 140: // dino transformation
+ playSound("55BSSSSS");
+ break;
+ case 141: // experimental laser
+ playSound("55SSSSSS");
+ break;
+ case 94: // plane hatch open
+ playSound("3SSSSSSS");
+ break;
+ case 95: // plane hatch close
+ playSound("4SSSSSSS");
+ break;
+ case 117: // oracle rezzes out
+ playSound("70SSSSSS");
+ break;
+ case 124: // dino horn
+ playSound("103SSSSS");
+ break;
+ case 127: // punch
+ playSound("128SSSSS");
+ break;
+ case 128: // body hits ground
+ playSound("129SSSSS");
+ break;
+ case 137: // explosion
+ playSound("88SSSSSS");
+ break;
+ case 86: // stone door grind 1
+ playSound("1001SSSS");
+ break;
+ case 188: // stone door grind 2
+ playSound("1002SSSS");
+ break;
+ case 28: // cloth slide 2
+ playSound("1005SSSS");
+ break;
+ case 151: // rattle bars
+ playSound("115SSSSS");
+ break;
+ case 152: // door dissolves
+ playSound("56SSSSSS");
+ break;
+ case 153: // altar slides
+ playSound("85SSSSSS");
+ break;
+ case 166 : // pull lever
+ playSound("1008SSSS");
+ break;
+ case 182: // zap Frank
+ playSound("1023SSSS");
+ break;
+ case 69: // splorch
+ playSound("137ASSSS");
+ break;
+ case 70: // robot laser
+ playSound("61SSSSSS");
+ break;
+ case 133: // pick hits stone
+ playSound("71SSSSSS");
+ break;
+ case 165: // press button
+ playSound("1007SSSS");
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
} //End of namespace Queen