aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Stewart2018-05-07 16:40:13 -0400
committerEugene Sandulenko2018-08-09 08:37:30 +0200
commitf43c5d468784b72c92e557c83b22c9c34f8ce497 (patch)
tree0f904da33f76476c37763326c2f55c55f061b3f6
parent9c2ed1d9b72036b1d1a052b1a4826cc8402bbb21 (diff)
downloadscummvm-rg350-f43c5d468784b72c92e557c83b22c9c34f8ce497.tar.gz
scummvm-rg350-f43c5d468784b72c92e557c83b22c9c34f8ce497.tar.bz2
scummvm-rg350-f43c5d468784b72c92e557c83b22c9c34f8ce497.zip
STARTREK: Implement CD Audio handling.
-rwxr-xr-xengines/startrek/graphics.cpp1
-rwxr-xr-xengines/startrek/graphics.h1
-rwxr-xr-xengines/startrek/sound.cpp90
-rwxr-xr-xengines/startrek/sound.h17
-rwxr-xr-xengines/startrek/startrek.cpp50
-rwxr-xr-xengines/startrek/startrek.h9
-rw-r--r--engines/startrek/text.cpp38
7 files changed, 164 insertions, 42 deletions
diff --git a/engines/startrek/graphics.cpp b/engines/startrek/graphics.cpp
index 029928d021..ed4113db40 100755
--- a/engines/startrek/graphics.cpp
+++ b/engines/startrek/graphics.cpp
@@ -49,6 +49,7 @@ Graphics::Graphics(StarTrekEngine *vm) : _vm(vm), _egaMode(false) {
_backgroundImage = new Bitmap(_vm->openFile("DEMON0.BMP").get());
_numSprites = 0;
+ _textboxVar1 = 2;
CursorMan.showMouse(true);
}
diff --git a/engines/startrek/graphics.h b/engines/startrek/graphics.h
index 578abdf705..47a0fbfe78 100755
--- a/engines/startrek/graphics.h
+++ b/engines/startrek/graphics.h
@@ -153,7 +153,6 @@ private:
SharedPtr<Menu> _activeMenu;
uint16 _textboxButtonVar4;
- uint16 _word_4B422;
};
}
diff --git a/engines/startrek/sound.cpp b/engines/startrek/sound.cpp
index 436316233b..32b31901b8 100755
--- a/engines/startrek/sound.cpp
+++ b/engines/startrek/sound.cpp
@@ -24,8 +24,10 @@
#include "common/file.h"
#include "common/macresman.h"
-#include "audio/mods/protracker.h"
+#include "audio/audiostream.h"
#include "audio/decoders/raw.h"
+#include "audio/decoders/voc.h"
+#include "audio/mods/protracker.h"
namespace StarTrek {
@@ -59,6 +61,12 @@ Sound::Sound(StarTrekEngine *vm) : _vm(vm) {
for (int i=1; i<8; i++) {
_sfxSlotList.push_back(&_midiSlots[i]);
}
+
+ if (!SearchMan.hasFile("voc/speech.mrk")) {
+ error("Couldn't find 'voc/speech.mrk'. The 'trekcd/voc/' directory must be dumped from the CD");
+ }
+
+ _playingSpeech = false;
}
Sound::~Sound() {
@@ -71,7 +79,7 @@ Sound::~Sound() {
void Sound::playMidiTrack(int track) {
- if (!_vm->_midiAudioEnabled)
+ if (!_vm->_musicEnabled)
return;
/*
if (!_vm->_word_467a8)
@@ -94,7 +102,7 @@ void Sound::playMidiTrack(int track) {
}
// Take the least recently used slot and use that for the sound effect
- MidiSlot *slot = _sfxSlotList.front();
+ MidiPlaybackSlot *slot = _sfxSlotList.front();
_sfxSlotList.pop_front();
_sfxSlotList.push_back(slot);
slot->track = track;
@@ -124,10 +132,75 @@ void Sound::playSoundEffect(const char *baseSoundName) {
playMacSoundEffect(baseSoundName);
else
*/
- error("PC Sound Effects Not Supported");
+ if (scumm_stricmp(baseSoundName+4, "loop") == 0)
+ _loopingAudioName = Common::String(baseSoundName);
+
+ if (!_vm->_sfxEnabled || !_vm->_audioEnabled)
+ return;
+
+ /*
+ if (word_5113a == 0)
+ sub_2aaa3();
+ */
+
+ for (int i=0; i<MAX_SFX_PLAYING; i++) {
+ if (_vm->_system->getMixer()->isSoundHandleActive(_sfxHandles[i]))
+ continue;
+
+ Common::String soundName = Common::String("voc/sfx/") + baseSoundName + ".voc";
+ Common::SeekableReadStream *readStream = SearchMan.createReadStreamForMember(soundName);
+ if (readStream == nullptr)
+ error("Couldn't open '%s'", soundName.c_str());
+
+ Audio::AudioStream *audioStream = Audio::makeVOCStream(readStream, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
+ _vm->_system->getMixer()->playStream(Audio::Mixer::kSFXSoundType, &_sfxHandles[i], audioStream);
+ return;
+ }
}
-// PC Functions
+void Sound::playSpeech(const Common::String &basename) {
+ stopPlayingSpeech();
+
+ Audio::QueuingAudioStream *audioQueue = nullptr;
+ Common::String name = basename;
+
+ // Play a list of comma-separated audio files in sequence (usually there's only one)
+ while (!name.empty()) {
+ uint i = 0;
+ while (i < name.size() && name[i] != ',') {
+ if (name[i] == '\\')
+ name.setChar('/', i);
+ i++;
+ }
+
+ Common::String filename = "voc/" + Common::String(name.c_str(), name.c_str()+i) + ".voc";
+ debug("Playing speech '%s'", filename.c_str());
+ Common::SeekableReadStream *readStream = SearchMan.createReadStreamForMember(filename);
+ if (readStream == nullptr)
+ error("Couldn't open '%s'", filename.c_str());
+
+ Audio::AudioStream *audioStream = Audio::makeVOCStream(readStream, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES);
+ if (audioQueue == nullptr)
+ audioQueue = Audio::makeQueuingAudioStream(audioStream->getRate(), audioStream->isStereo());
+ audioQueue->queueAudioStream(audioStream, DisposeAfterUse::YES);
+
+ name.erase(0,i+1);
+ }
+
+ if (audioQueue != nullptr) {
+ audioQueue->finish();
+ _vm->_system->getMixer()->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, audioQueue);
+ }
+
+ _playingSpeech = true;
+}
+
+void Sound::stopPlayingSpeech() {
+ if (_playingSpeech) {
+ _playingSpeech = false;
+ _vm->_system->getMixer()->stopHandle(_speechHandle);
+ }
+}
// XMIDI or SM sound
@@ -179,10 +252,17 @@ void Sound::clearAllMidiSlots() {
}
}
+// Static callback method
void Sound::midiDriverCallback(void *data) {
Sound *s = (Sound*)data;
for (int i=0; i<8; i++)
s->_midiSlots[i].midiParser->onTimer();
+
+ // TODO: put this somewhere other than the midi callback...
+ if (s->_playingSpeech && !s->_vm->_system->getMixer()->isSoundHandleActive(s->_speechHandle)) {
+ s->stopPlayingSpeech();
+ s->_vm->_finishedPlayingSpeech = true;
+ }
}
diff --git a/engines/startrek/sound.h b/engines/startrek/sound.h
index f314f2c688..a9116627d5 100755
--- a/engines/startrek/sound.h
+++ b/engines/startrek/sound.h
@@ -41,12 +41,16 @@ namespace StarTrek {
class StarTrekEngine;
-struct MidiSlot {
+const int MAX_LOADED_SFX_FILES = 8;
+const int MAX_SFX_PLAYING = 4;
+
+struct MidiPlaybackSlot {
int slot;
int track;
MidiParser *midiParser;
};
+
class Sound {
public:
Sound(StarTrekEngine *vm);
@@ -56,6 +60,8 @@ public:
void loadMusicFile(const char *baseSoundName);
void playSoundEffect(const char *baseSoundName);
+ void playSpeech(const Common::String &basename);
+ void stopPlayingSpeech();
private:
StarTrekEngine *_vm;
@@ -67,12 +73,17 @@ private:
// MIDI-Related Variables
MidiDriver *_midiDriver;
- MidiSlot _midiSlots[8]; // 0 is for music; 1-7 are for sfx
- Common::List<MidiSlot*> _sfxSlotList; // Sorts midi slots by most recently used
+ MidiPlaybackSlot _midiSlots[8]; // 0 is for music; 1-7 are for sfx
+ Common::List<MidiPlaybackSlot*> _sfxSlotList; // Sorts midi slots by most recently used
byte *loadedSoundData;
uint32 _midiDevice;
+ // VOC-related variables
+ Common::String _loopingAudioName;
+ Audio::SoundHandle _sfxHandles[MAX_SFX_PLAYING];
+ Audio::SoundHandle _speechHandle;
+ bool _playingSpeech;
// Driver callback
static void midiDriverCallback(void *data);
diff --git a/engines/startrek/startrek.cpp b/engines/startrek/startrek.cpp
index dba8a48756..d888d1f710 100755
--- a/engines/startrek/startrek.cpp
+++ b/engines/startrek/startrek.cpp
@@ -42,8 +42,11 @@ StarTrekEngine::StarTrekEngine(OSystem *syst, const StarTrekGameDescription *gam
_gfx = nullptr;
_sound = nullptr;
_macResFork = nullptr;
-
_room = nullptr;
+
+ _audioEnabled = true;
+ _musicEnabled = true;
+ _sfxEnabled = true;
}
StarTrekEngine::~StarTrekEngine() {
@@ -55,9 +58,6 @@ StarTrekEngine::~StarTrekEngine() {
}
Common::Error StarTrekEngine::run() {
- _cdAudioEnabled = true;
- _midiAudioEnabled = true;
-
_gfx = new Graphics(this);
_sound = new Sound(this);
@@ -101,7 +101,7 @@ Common::Error StarTrekEngine::run() {
_gfx->loadPri("DEMON0.PRI");
_gfx->redrawScreen();
- _sound->loadMusicFile("BRIDGEW");
+ _sound->loadMusicFile("GROUND");
} else {
_gfx->drawBackgroundImage("BRIDGE.BGD");
}
@@ -191,50 +191,50 @@ void StarTrekEngine::pollSystemEvents() {
}
void StarTrekEngine::playSoundEffectIndex(int index) {
- switch(index-4) {
- case 0:
+ switch(index) {
+ case 0x04:
_sound->playSoundEffect("tricorde");
break;
- case 1:
+ case 0x05:
_sound->playSoundEffect("STDOOR1");
break;
- case 2:
+ case 0x06:
_sound->playSoundEffect("PHASSHOT");
break;
- case 3:
+ case 0x07:
_sound->playMidiTrack(index);
break;
- case 4:
+ case 0x08:
_sound->playSoundEffect("TRANSDEM");
break;
- case 5:
+ case 0x09:
_sound->playSoundEffect("TRANSMAT");
break;
- case 6:
+ case 0x0a:
_sound->playSoundEffect("TRANSENE");
break;
- case 0x0c: // Menu selection sound
+ case 0x10: // Menu selection sound
_sound->playMidiTrack(index);
break;
- case 0x1e:
+ case 0x22:
_sound->playSoundEffect("HAILING");
break;
- case 0x20:
+ case 0x24:
_sound->playSoundEffect("PHASSHOT");
break;
- case 0x21:
+ case 0x25:
_sound->playSoundEffect("PHOTSHOT");
break;
- case 0x22:
+ case 0x26:
_sound->playSoundEffect("HITSHIEL");
break;
- case 0x23:
+ case 0x27:
_sound->playMidiTrack(index);
break;
- case 0x24:
+ case 0x28:
_sound->playSoundEffect("REDALERT");
break;
- case 0x25:
+ case 0x29:
_sound->playSoundEffect("WARP");
break;
default:
@@ -242,6 +242,14 @@ void StarTrekEngine::playSoundEffectIndex(int index) {
}
}
+void StarTrekEngine::playSpeech(const Common::String &filename) {
+ _sound->playSpeech(filename.c_str());
+}
+
+void StarTrekEngine::stopPlayingSpeech() {
+ _sound->stopPlayingSpeech();
+}
+
void StarTrekEngine::updateClockTicks() {
// TODO (based on DOS interrupt 1A, AH=0; read system clock counter)
diff --git a/engines/startrek/startrek.h b/engines/startrek/startrek.h
index c190659d6a..232482a767 100755
--- a/engines/startrek/startrek.h
+++ b/engines/startrek/startrek.h
@@ -92,6 +92,8 @@ public:
void pollSystemEvents();
void playSoundEffectIndex(int index);
+ void playSpeech(const Common::String &filename);
+ void stopPlayingSpeech();
// Events
public:
@@ -135,11 +137,12 @@ public:
uint32 _clockTicks;
- bool _midiAudioEnabled;
- bool _cdAudioEnabled;
+ bool _musicEnabled;
+ bool _sfxEnabled;
uint16 _word_467a6;
uint16 _word_467a8;
- bool _textboxVar4;
+ bool _audioEnabled;
+ bool _finishedPlayingSpeech;
private:
diff --git a/engines/startrek/text.cpp b/engines/startrek/text.cpp
index fe2f0eeb6c..2d875da397 100644
--- a/engines/startrek/text.cpp
+++ b/engines/startrek/text.cpp
@@ -88,12 +88,12 @@ int Graphics::showText(TextGetterFunc textGetter, int var, int xoffset, int yoff
int choiceIndex = 0;
int scrollOffset = 0;
if (tmpTextboxVar1 != 0 && tmpTextboxVar1 != 1 && numChoices == 1
- && _vm->_cdAudioEnabled && !_vm->_textboxVar4)
+ && _vm->_sfxEnabled && !_vm->_audioEnabled)
_textboxHasMultipleChoices = false;
else
_textboxHasMultipleChoices = true;
- if (tmpTextboxVar1 >= 0 && tmpTextboxVar1 <= 2 && _vm->_cdAudioEnabled && !_vm->_textboxVar4)
+ if (tmpTextboxVar1 >= 0 && tmpTextboxVar1 <= 2 && _vm->_sfxEnabled && !_vm->_audioEnabled)
_textboxVar6 = true;
else
_textboxVar6 = false;
@@ -268,7 +268,7 @@ reloadText:
}
_textboxVar2 = _textboxVar3;
- // sub_29EE3();
+ _vm->stopPlayingSpeech();
return choiceIndex;
}
@@ -312,8 +312,8 @@ int Graphics::handleTextboxEvents(uint32 ticksUntilClickingEnabled, bool arg4) {
// sub_10BE7();
// sub_2A4B1();
- if (_word_4B422 != 0) {
- _word_4B422 = 0;
+ if (_vm->_finishedPlayingSpeech != 0) {
+ _vm->_finishedPlayingSpeech = 0;
if (_textboxVar1 != 0) {
return TEXTEVENT_SPEECH_DONE;
}
@@ -539,13 +539,13 @@ String Graphics::readLineFormattedText(TextGetterFunc textGetter, int var, int c
String headerText;
String text = (this->*textGetter)(choiceIndex, &var, &headerText);
- if (_textboxVar1 == 2 && _vm->_cdAudioEnabled && _vm->_textboxVar4) {
+ if (_textboxVar1 == 2 && _vm->_sfxEnabled && _vm->_audioEnabled) {
uint32 oldSize = text.size();
text = playTextAudio(text);
if (oldSize != text.size())
_textboxHasMultipleChoices = true;
}
- else if ((_textboxVar1 == 0 || _textboxVar1 == 1) && _vm->_cdAudioEnabled && _vm->_textboxVar4) {
+ else if ((_textboxVar1 == 0 || _textboxVar1 == 1) && _vm->_sfxEnabled && _vm->_audioEnabled) {
text = playTextAudio(text);
}
else {
@@ -682,9 +682,29 @@ String Graphics::skipTextAudioPrompt(const String &str) {
return String(text+1);
}
+/**
+ * Plays an audio prompt, if it exists, and returns the string starting at the end of the
+ * prompt.
+ */
String Graphics::playTextAudio(const String &str) {
- // TODO
- return skipTextAudioPrompt(str);
+ const char *text = str.c_str();
+ char soundFile[0x100];
+
+ if (*text != '#')
+ return str;
+
+ int len = 0;
+ text++;
+ while (*text != '#') {
+ if (*text == '\0' || len > 0xfa)
+ return str;
+ soundFile[len++] = *text++;
+ }
+
+ soundFile[len] = '\0';
+ _vm->playSpeech(soundFile);
+
+ return String(text+1);
}
/**