aboutsummaryrefslogtreecommitdiff
path: root/sound.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sound.cpp')
-rw-r--r--sound.cpp295
1 files changed, 278 insertions, 17 deletions
diff --git a/sound.cpp b/sound.cpp
index cfee9440a0..c8e3beab9a 100644
--- a/sound.cpp
+++ b/sound.cpp
@@ -17,6 +17,10 @@
*
* Change Log:
* $Log$
+ * Revision 1.3 2001/11/05 19:21:49 strigeus
+ * bug fixes,
+ * speech in dott
+ *
* Revision 1.2 2001/10/16 10:01:48 strigeus
* preliminary DOTT support
*
@@ -30,6 +34,20 @@
#include "stdafx.h"
#include "scumm.h"
+#if defined(USE_IMUSE)
+#include "sound.h"
+#else
+struct SoundEngine {
+ byte **_base_sounds;
+ int start_sound(int sound) { return -1; }
+ int stop_sound(int sound) { return -1; }
+ int stop_all_sounds() { return -1; }
+ int32 do_command(int a, int b, int c, int d, int e, int f, int g, int h) { return -1; }
+ int get_sound_status(int sound) { return -1; }
+ int clear_queue() { return -1; }
+};
+#endif
+
void Scumm::addSoundToQueue(int sound) {
_vars[VAR_LAST_SOUND] = sound;
ensureResourceLoaded(4, sound);
@@ -42,11 +60,14 @@ void Scumm::addSoundToQueue2(int sound) {
}
}
-void Scumm::unkSoundProc22() {
+void Scumm::processSoundQues() {
byte d;
int i,j;
int num;
int16 data[16];
+ SoundEngine *se;
+
+ processSfxQueues();
while (_soundQue2Pos){
d=_soundQue2[--_soundQue2Pos];
@@ -54,39 +75,199 @@ void Scumm::unkSoundProc22() {
playSound(d);
}
-#if 0
for (i=0; i<_soundQuePos; ) {
num = _soundQue[i++];
+ if (i + num > _soundQuePos) {
+ warning("processSoundQues: invalid num value");
+ break;
+ }
for (j=0; j<16; j++)
data[j] = 0;
if (num>0) {
for (j=0; j<num; j++)
- _soundQue[i+j] = data[j];
+ data[j] = _soundQue[i+j];
i += num;
- /* XXX: not implemented */
- warning("unkSoundProc22: not implemented");
-// vm.vars[VAR_SOUNDRESULT] = soundProcPtr1(...);
+
+ se = (SoundEngine*)_soundDriver;
+#if 0
+ debug(1,"processSoundQues(%d,%d,%d,%d,%d,%d,%d,%d,%d)",
+ data[0]>>8,
+ data[0]&0xFF,
+ data[1],
+ data[2],
+ data[3],
+ data[4],
+ data[5],
+ data[6],
+ data[7]
+ );
+#endif
+ if (se)
+ _vars[VAR_SOUNDRESULT] = se->do_command(data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7]);
}
}
- #endif
_soundQuePos = 0;
}
void Scumm::playSound(int sound) {
- getResourceAddress(4, sound);
- /* XXX: not implemented */
-// warning("stub playSound(%d)", sound);
+ SoundEngine *se = (SoundEngine*)_soundDriver;
+ if (se) {
+ getResourceAddress(rtSound, sound);
+ se->start_sound(sound);
+ }
}
-int Scumm::unkSoundProc23(int a) {
- /* TODO: implement this */
-// warning("unkSoundProc23: not implemented");
+void Scumm::processSfxQueues() {
+ Actor *a;
+ int act;
+ bool b,finished;
+
+ if (_talk_sound_mode != 0) {
+ startTalkSound(_talk_sound_a, _talk_sound_b, _talk_sound_mode);
+ _talk_sound_mode = 0;
+ }
+
+ if (_sfxMode==2) {
+ act = _vars[VAR_TALK_ACTOR];
+ finished = isSfxFinished();
+
+ if (act!=0 && (uint)act<0x80 && !string[0].no_talk_anim) {
+ a = derefActorSafe(act, "processSfxQueues");
+ if (a->room==_currentRoom && (finished || !_endOfMouthSync)) {
+ b = true;
+ if (!finished)
+ b = isMouthSyncOff(_curSoundPos);
+ if (_mouthSyncMode != b) {
+ _mouthSyncMode = b;
+ startAnimActor(a, b ? a->talkFrame2 : a->talkFrame1, a->facing);
+ }
+ }
+ }
+ if (finished && _talkDelay==0) {
+ stopTalk();
+ _sfxMode = 0;
+ }
+ } else if (_sfxMode==1) {
+ if (isSfxFinished()) {
+ _sfxMode = 0;
+ }
+ }
+}
+
+void Scumm::startTalkSound(uint32 offset, uint32 b, int mode) {
+ int num, i;
+ byte file_byte,file_byte_2;
+ uint16 elem;
+
+ if (!_sfxFile) {
+ warning("startTalkSound: SFX file is not open");
+ return;
+ }
+
+ fileSeek((FILE*)_sfxFile, offset + 8, SEEK_SET);
+ i = 0;
+ if (b>8) {
+ num = (b-8)>>1;
+ do {
+ fileRead((FILE*)_sfxFile, &file_byte, sizeof(file_byte));
+ fileRead((FILE*)_sfxFile, &file_byte_2, sizeof(file_byte_2));
+ _mouthSyncTimes[i++] = file_byte | (file_byte_2<<8);
+ } while (--num);
+ }
+ _mouthSyncTimes[i] = 0xFFFF;
+ _sfxMode = mode;
+ _curSoundPos = 0;
+ _mouthSyncMode = true;
+
+ startSfxSound(_sfxFile);
+}
+
+bool Scumm::isMouthSyncOff(uint pos) {
+ uint j;
+ bool val = true;
+ uint16 *ms = _mouthSyncTimes;
+
+ _endOfMouthSync = false;
+ do {
+ val ^= 1;
+ j = *ms++;
+ if (j==0xFFFF) {
+ _endOfMouthSync = true;
+ break;
+ }
+ } while (pos > j);
+ return val;
+}
+
+
+int Scumm::isSoundRunning(int sound) {
+ SoundEngine *se;
+ int i;
+
+ i = _soundQue2Pos;
+ while (i--) {
+ if (_soundQue2[i] == sound)
+ return 1;
+ }
+
+ if (isSoundInQueue(sound))
+ return 1;
+
+ if (!isResourceLoaded(4, sound))
+ return 0;
+
+
+ se = (SoundEngine*)_soundDriver;
+ if (!se)
+ return 0;
+ return se->get_sound_status(sound);
+}
+
+bool Scumm::isSoundInQueue(int sound) {
+ int i = 0,j, num;
+ int16 table[16];
+
+ while (i < _soundQuePos) {
+ num = _soundQue[i++];
+
+ memset(table, 0, sizeof(table));
+
+ if (num > 0) {
+ for (j=0; j<num; j++)
+ table[j] = _soundQue[i+j];
+ i += num;
+ if (table[0] == 0x10F && table[1]==8 && table[2] == sound)
+ return 1;
+ }
+ }
return 0;
}
-void Scumm::unkSoundProc1(int a) {
- /* TODO: implement this */
-// warning("unkSoundProc: not implemented");
+void Scumm::stopSound(int a) {
+ SoundEngine *se;
+ int i;
+
+ se = (SoundEngine*)_soundDriver;
+ if (se)
+ se->stop_sound(a);
+
+ for (i=0; i<10; i++)
+ if (_soundQue2[i] == (byte)a)
+ _soundQue2[i] = 0;
+}
+
+void Scumm::stopAllSounds() {
+ SoundEngine *se = (SoundEngine*)_soundDriver;
+ if (se) {
+ se->stop_all_sounds();
+ se->clear_queue();
+ }
+ clearSoundQue();
+}
+
+void Scumm::clearSoundQue() {
+ _soundQue2Pos = 0;
+ memset(_soundQue2, 0, sizeof(_soundQue2));
}
void Scumm::soundKludge(int16 *list) {
@@ -94,7 +275,7 @@ void Scumm::soundKludge(int16 *list) {
int i;
if (list[0]==-1) {
- unkSoundProc22();
+ processSoundQues();
return;
}
_soundQue[_soundQuePos++] = 8;
@@ -106,4 +287,84 @@ void Scumm::soundKludge(int16 *list) {
*ptr++ = list[i];
if (_soundQuePos > 0x100)
error("Sound que buffer overflow");
+}
+
+void Scumm::talkSound(uint32 a, uint32 b, int mode) {
+ _talk_sound_a = a;
+ _talk_sound_b = b;
+ _talk_sound_mode = mode;
+}
+
+static const uint32 sound_tags[] = {
+ MKID('ADL ')
+};
+
+void Scumm::setupSound() {
+ SoundEngine *se = (SoundEngine*)_soundDriver;
+ if (se) {
+ se->_base_sounds = res.address[4];
+ }
+ _soundTagTable = (byte*)sound_tags;
+ _numSoundTags = 1;
+ if (_majorScummVersion==6)
+ _sfxFile = openSfxFile();
+}
+
+struct VOCHeader {
+ byte id[19];
+ byte extra[7];
+};
+
+static const char VALID_VOC_ID[] = "Creative Voice File";
+static const char VALID_VOC_VERSION[] = "";
+void Scumm::startSfxSound(void *file) {
+ VOCHeader hdr;
+ int block_type;
+ byte work[8];
+ uint size,i;
+ int rate,comp;
+ byte *data;
+
+ if (fread(&hdr, sizeof(hdr), 1, (FILE*)file) != 1 ||
+ memcmp(hdr.id, VALID_VOC_ID, sizeof(hdr.id)) != 0) {
+ warning("startSfxSound: invalid header");
+ return;
+ }
+
+ block_type = getc( (FILE*)file );
+ if (block_type != 1) {
+ warning("startSfxSound: Expecting block_type == 1, got %d", block_type);
+ return;
+ }
+
+ fread(work, 3, 1, (FILE*)file);
+
+ size = ( work[0] | ( work[1] << 8 ) | ( work[2] << 16 ) ) - 2;
+ rate = getc( (FILE*)file );
+ comp = getc( (FILE*)file );
+
+ if (comp != 0) {
+ warning("startSfxSound: Unsupported compression type %d", comp);
+ return;
+ }
+
+ data = (byte*) malloc(size);
+ if (data==NULL) {
+ error("startSfxSound: out of memory");
+ return;
+ }
+
+ if (fread(data, size, 1, (FILE*)file) != 1) {
+ /* no need to free the memory since error will shut down */
+ error("startSfxSound: cannot read %d bytes", size);
+ return;
+ }
+ for(i=0;i<size; i++)
+ data[i] ^= 0x80;
+
+ playSfxSound(data, size, 1000000 / (256 - rate) );
+}
+
+void *Scumm::openSfxFile() {
+ return fopen("monster.sou", "rb");
} \ No newline at end of file