aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaweł Kołodziejski2004-01-06 17:28:29 +0000
committerPaweł Kołodziejski2004-01-06 17:28:29 +0000
commit8fd123992d746a3afa683b60790668757d0c9437 (patch)
tree5f9b3d854b8aad9c40e50e7cf0e51e3485bc6c33
parent2c2ae5f59ff309950fe5ffabbdb309b89f7531b8 (diff)
downloadscummvm-rg350-8fd123992d746a3afa683b60790668757d0c9437.tar.gz
scummvm-rg350-8fd123992d746a3afa683b60790668757d0c9437.tar.bz2
scummvm-rg350-8fd123992d746a3afa683b60790668757d0c9437.zip
synced imuse digital with local tree
svn-id: r12187
-rw-r--r--scumm/akos.cpp3
-rw-r--r--scumm/bundle.h83
-rw-r--r--scumm/imuse_digi.h149
-rw-r--r--scumm/imuse_digi/.cvsignore1
-rw-r--r--scumm/imuse_digi/dimuse.cpp576
-rw-r--r--scumm/imuse_digi/dimuse.h154
-rw-r--r--scumm/imuse_digi/dimuse_bndmgr.cpp179
-rw-r--r--scumm/imuse_digi/dimuse_bndmgr.h72
-rw-r--r--scumm/imuse_digi/dimuse_codecs.cpp (renamed from scumm/bundle.cpp)340
-rw-r--r--scumm/imuse_digi/dimuse_sndmgr.cpp462
-rw-r--r--scumm/imuse_digi/dimuse_sndmgr.h126
-rw-r--r--scumm/imuse_digi/dimuse_tables.cpp (renamed from scumm/imuse_digi.cpp)883
-rw-r--r--scumm/resource.cpp6
-rw-r--r--scumm/saveload.cpp4
-rw-r--r--scumm/script_v6.cpp5
-rw-r--r--scumm/script_v8.cpp23
-rw-r--r--scumm/scummvm.cpp2
-rw-r--r--scumm/smush/insane.cpp20
-rw-r--r--scumm/smush/smush_player.cpp2
-rw-r--r--scumm/sound.cpp11
-rw-r--r--scumm/string.cpp7
21 files changed, 1638 insertions, 1470 deletions
diff --git a/scumm/akos.cpp b/scumm/akos.cpp
index c0b3570c4c..c47c1a9fd0 100644
--- a/scumm/akos.cpp
+++ b/scumm/akos.cpp
@@ -26,6 +26,7 @@
#include "scumm/akos.h"
#include "scumm/bomp.h"
#include "scumm/imuse.h"
+#include "scumm/imuse_digi/dimuse.h"
#include "scumm/sound.h"
namespace Scumm {
@@ -1328,7 +1329,7 @@ void ScummEngine::akos_queCommand(byte cmd, Actor *a, int param_1, int param_2)
case 3:
if (param_1 != 0) {
if (_features & GF_DIGI_IMUSE)
- _sound->playSound(param_1);
+ _imuseDigital->startSfx(param_1);
else
_sound->addSoundToQueue(param_1);
}
diff --git a/scumm/bundle.h b/scumm/bundle.h
deleted file mode 100644
index 2c25c47653..0000000000
--- a/scumm/bundle.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* ScummVM - Scumm Interpreter
- * Copyright (C) 2002-2004 The ScummVM project
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * $Header$
- */
-
-#ifndef BUNDLE_H
-#define BUNDLE_H
-
-#include "common/scummsys.h"
-#include "common/file.h"
-
-namespace Scumm {
-
-class Bundle {
-
-private:
-
- struct CompTable {
- int32 offset;
- int32 size;
- int32 codec;
- };
-
- struct BundleAudioTable {
- char filename[13];
- int32 size;
- int32 offset;
- };
-
- CompTable *_compVoiceTable;
- CompTable *_compMusicTable;
- BundleAudioTable *_bundleVoiceTable;
- BundleAudioTable *_bundleMusicTable;
- int32 _numVoiceFiles;
- int32 _numMusicFiles;
- int32 _lastSong;
-
- byte _destImcTable[93];
- uint32 _destImcTable2[5697];
-
- File _voiceFile;
- File _musicFile;
-
- void initializeImcTables();
-
- int32 decompressCodec(int32 codec, byte *comp_input, byte *comp_output, int32 size);
-
- int32 decompressVoiceSampleByIndex(int32 index, byte **comp_final);
- int32 decompressMusicSampleByIndex(int32 index, int32 number, byte *comp_final);
- int32 getNumberOfMusicSamplesByIndex(int32 index);
-
-public:
- Bundle();
- ~Bundle();
-
- bool openVoiceFile(const char *filename, const char *directory);
- bool openMusicFile(const char *filename, const char *directory);
- void closeVoiceFile();
- void closeMusicFile();
-
- int32 decompressVoiceSampleByName(const char *name, byte **comp_final);
- int32 decompressMusicSampleByName(const char *name, int32 number, byte *comp_final);
- int32 getNumberOfMusicSamplesByName(const char *name);
-};
-
-} // End of namespace Scumm
-
-#endif
diff --git a/scumm/imuse_digi.h b/scumm/imuse_digi.h
deleted file mode 100644
index 047283530a..0000000000
--- a/scumm/imuse_digi.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/* ScummVM - Scumm Interpreter
- * Copyright (C) 2001 Ludvig Strigeus
- * Copyright (C) 2001-2004 The ScummVM project
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * $Header$
- *
- */
-
-#ifndef IMUSE_DIGI_H
-#define IMUSE_DIGI_H
-
-#include "common/scummsys.h"
-#include "scumm/music.h"
-#include "sound/mixer.h"
-
-class AudioStream;
-
-namespace Scumm {
-
-#define MAX_DIGITAL_CHANNELS 8
-#define MAX_IMUSE_JUMPS 50
-#define MAX_IMUSE_REGIONS 50
-#define MAX_IMUSE_MARKERS 50
-
-class ScummEngine;
-class Bundle;
-
-/**
- * iMuse Digital Implementation for SCUMM v7 and higher.
- */
-class IMuseDigital : public MusicEngine {
-private:
-
- struct _region {
- uint32 start; // begin of region
- uint32 length; // lenght of region
- };
-
- struct _jump {
- uint32 start; // jump start position
- uint32 dest; // jump to dest position
- uint32 hookId; // id of hook
- uint32 fadeDelay; // fade delay in ms
- };
-
- struct _marker {
- char name[256]; // name of marker
- };
-
- struct Channel {
- int8 pan; // pan
- int32 vol; // volume
- int32 volFadeDest; //
- int32 volFadeStep; //
- int32 volFadeDelay; //
- bool volFadeUsed; //
-
- _region region[MAX_IMUSE_REGIONS];
- _marker marker[MAX_IMUSE_MARKERS];
- _jump jump[MAX_IMUSE_JUMPS];
- int32 offsetStop;
- int32 numJumps;
- int32 numRegions;
- int32 numMarkers;
-
- int idSound;
- bool used;
- bool started;
- PlayingSoundHandle handle;
- AudioStream *stream;
-
- Channel();
- };
-
- Channel _channel[MAX_DIGITAL_CHANNELS];
-
- ScummEngine *_scumm;
- bool _pause;
-
- static void timer_handler(void *refConf);
- void callback();
-
- //
- // Bundle music
- //
- const char *_nameBundleMusic;
- const char *_newNameBundleMusic;
- byte _musicDisk;
- byte _voiceDisk;
- int32 _currentSampleBundleMusic;
- int32 _numberSamplesBundleMusic;
- int32 _offsetSampleBundleMusic;
- int32 _offsetBufBundleMusic;
- byte *_musicBundleBufFinal;
- byte *_musicBundleBufOutput;
- bool _pauseBundleMusic;
- PlayingSoundHandle _bundleMusicTrack;
- bool _musicBundleToBeChanged;
- int32 _bundleMusicSampleBits;
- int32 _outputMixerSize;
- int32 _bundleSampleChannels;
- int32 _bundleMusicPosition;
-
- static void music_handler(void *refCon);
- void bundleMusicHandler();
-
- void playBundleMusic(const char *song);
-
-public:
- int32 _bundleSongPosInMs;
- Bundle *_bundle; // FIXME: should be protected but is used by ScummEngine::askForDisk
-
- void pauseBundleMusic(bool state);
- void stopBundleMusic();
- void playBundleSound(const char *sound);
-
- void startSound(int sound, byte *voiceBundleData, AudioStream *input);
-
-public:
- IMuseDigital(ScummEngine *scumm);
- ~IMuseDigital();
-
- void setMasterVolume(int vol) {}
-
- void startSound(int sound) { startSound(sound, 0, 0); }
- void stopSound(int sound);
- void stopAllSounds();
- void pause(bool pause);
- void parseScriptCmds(int a, int b, int c, int d, int e, int f, int g, int h);
- int getSoundStatus(int sound) const;
-};
-
-} // End of namespace Scumm
-
-#endif
diff --git a/scumm/imuse_digi/.cvsignore b/scumm/imuse_digi/.cvsignore
new file mode 100644
index 0000000000..39a06683b7
--- /dev/null
+++ b/scumm/imuse_digi/.cvsignore
@@ -0,0 +1 @@
+.deps
diff --git a/scumm/imuse_digi/dimuse.cpp b/scumm/imuse_digi/dimuse.cpp
new file mode 100644
index 0000000000..0abcc59043
--- /dev/null
+++ b/scumm/imuse_digi/dimuse.cpp
@@ -0,0 +1,576 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001-2004 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#include "stdafx.h"
+#include "common/timer.h"
+
+#include "scumm/actor.h"
+#include "scumm/scumm.h"
+#include "scumm/sound.h"
+#include "scumm/imuse_digi/dimuse.h"
+#include "scumm/imuse_digi/dimuse_bndmgr.h"
+
+#include "sound/audiostream.h"
+#include "sound/mixer.h"
+
+namespace Scumm {
+
+IMuseDigital::Track::Track()
+ : idSound(-1), used(false), stream(NULL) {
+}
+
+void IMuseDigital::timer_handler(void *refCon) {
+ IMuseDigital *imuseDigital = (IMuseDigital *)refCon;
+ imuseDigital->callback();
+}
+
+IMuseDigital::IMuseDigital(ScummEngine *scumm)
+ : _scumm(scumm) {
+ _pause = false;
+ _sound = new ImuseDigiSndMgr(_scumm);
+ _scumm->_timer->installTimerProc(timer_handler, 1000000 / 25, this);
+ _curMusicId = -1;
+}
+
+IMuseDigital::~IMuseDigital() {
+ _scumm->_timer->removeTimerProc(timer_handler);
+ stopAllSounds();
+ delete _sound;
+}
+
+void IMuseDigital::callback() {
+ int l = 0;
+
+ if (_pause || !_scumm)
+ return;
+
+ for (l = 0; l < MAX_DIGITAL_TRACKS;l ++) {
+ if (_track[l].used) {
+ if (_track[l].stream2) {
+ if (!_track[l].handle.isActive() && _track[l].started) {
+ debug(5, "IMuseDigital::callback(): stoped sound: %d", _track[l].idSound);
+ delete _track[l].stream2;
+ _track[l].stream2 = NULL;
+ _track[l].used = false;
+ continue;
+ }
+ } else if (_track[l].stream) {
+ if (_track[l].toBeRemoved) {
+ debug(5, "IMuseDigital::callback(): stoped sound: %d", _track[l].idSound);
+ if (_track[l].stream)
+ _track[l].stream->finish();
+ _track[l].stream = NULL;
+ _sound->closeSound(_track[l].soundHandle);
+ _track[l].used = false;
+ continue;
+ }
+ }
+
+ if (_track[l].volFadeUsed) {
+ if (_track[l].volFadeStep < 0) {
+ if (_track[l].vol > _track[l].volFadeDest) {
+ _track[l].vol += _track[l].volFadeStep;
+ if (_track[l].vol < _track[l].volFadeDest) {
+ _track[l].vol = _track[l].volFadeDest;
+ _track[l].volFadeUsed = false;
+ }
+ if (_track[l].vol == 0) {
+ _track[l].toBeRemoved = true;
+ }
+ }
+ } else if (_track[l].volFadeStep > 0) {
+ if (_track[l].vol < _track[l].volFadeDest) {
+ _track[l].vol += _track[l].volFadeStep;
+ if (_track[l].vol > _track[l].volFadeDest) {
+ _track[l].vol = _track[l].volFadeDest;
+ _track[l].volFadeUsed = false;
+ }
+ }
+ }
+ debug(5, "Fade: sound(%d), Vol(%d)", _track[l].idSound, _track[l].vol / 1000);
+ }
+
+ int pan = (_track[l].pan != 64) ? 2 * _track[l].pan - 127 : 0;
+
+ if (_scumm->_mixer->isReady()) {
+ if (_track[l].stream2) {
+ if (!_track[l].started) {
+ _track[l].started = true;
+ _scumm->_mixer->playInputStream(&_track[l].handle, _track[l].stream2, true, _track[l].vol / 1000, _track[l].pan, -1, false);
+ } else {
+ _scumm->_mixer->setChannelVolume(_track[l].handle, _track[l].vol / 1000);
+ _scumm->_mixer->setChannelPan(_track[l].handle, pan);
+ }
+ continue;
+ }
+ }
+
+ if (_track[l].stream) {
+ int32 mixer_size = _track[l].pullSize;
+ byte *data = NULL;
+ int32 result = 0;
+
+ if (_track[l].stream->endOfData())
+ mixer_size *= 2;
+
+ do {
+ if (_sound->getBits(_track[l].soundHandle) == 12) {
+ byte *ptr = NULL;
+ mixer_size += _track[l].mod;
+ int length = (((mixer_size * 3) / 4) / 3) * 3;
+ _track[l].mod = ((mixer_size * 3) / 4) - length;
+ mixer_size = length;
+
+ int32 offset = (_track[l].regionOffset * 3) / 4;
+ result = _sound->getDataFromRegion(_track[l].soundHandle, _track[l].curRegion, &ptr, offset, mixer_size);
+ int32 result2 = BundleCodecs::decode12BitsSample(ptr, &data, result);
+ result = (result * 4) / 3;
+ if (result != result2) {
+ debug(5, "result: %d, result2: %d", result, result2);
+ result &= ~1;
+ }
+ mixer_size = (mixer_size * 4) / 3;
+ free(ptr);
+ } else if (_sound->getBits(_track[l].soundHandle) == 16) {
+ result = _sound->getDataFromRegion(_track[l].soundHandle, _track[l].curRegion, &data, _track[l].regionOffset, mixer_size);
+ if (_sound->getChannels(_track[l].soundHandle) == 2) {
+ if (result & 3)
+ result &= ~2;
+ }
+ if (_sound->getChannels(_track[l].soundHandle) == 1) {
+ if (result & 1)
+ result &= ~1;
+ }
+ } else if (_sound->getBits(_track[l].soundHandle) == 8) {
+ result = _sound->getDataFromRegion(_track[l].soundHandle, _track[l].curRegion, &data, _track[l].regionOffset, mixer_size);
+ if (_sound->getChannels(_track[l].soundHandle) == 2) {
+ if (result & 1)
+ result &= ~1;
+ }
+ }
+
+ if (_scumm->_mixer->isReady()) {
+ _scumm->_mixer->setChannelVolume(_track[l].handle, _track[l].vol / 1000);
+ _scumm->_mixer->setChannelPan(_track[l].handle, pan);
+ _track[l].stream->append(data, result);
+ _track[l].regionOffset += result;
+ _track[l].trackOffset += result;
+ free(data);
+ }
+
+ if (_sound->isEndOfRegion(_track[l].soundHandle, _track[l].curRegion)) {
+ switchToNextRegion(l);
+ if (_track[l].toBeRemoved)
+ break;
+ }
+ mixer_size -= result;
+ assert(mixer_size >= 0);
+ } while (mixer_size != 0);
+ }
+ }
+ }
+}
+
+void IMuseDigital::switchToNextRegion(int track) {
+ // TODO - finish
+ int num_regions = _sound->getNumRegions(_track[track].soundHandle);
+ if (++_track[track].curRegion == num_regions) {
+ _track[track].toBeRemoved = true;
+ return;
+ }
+ _track[track].regionOffset = 0;
+}
+
+void IMuseDigital::startSound(int soundId, char *soundName, int soundType, int soundGroup, AudioStream *input) {
+ debug(5, "IMuseDigital::startSound(%d)", soundId);
+ int l;
+
+ for (l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if (!_track[l].used && !_track[l].handle.isActive()) {
+ _track[l].pan = 64;
+ _track[l].vol = 127 * 1000;
+ _track[l].volFadeDest = 0;
+ _track[l].volFadeStep = 0;
+ _track[l].volFadeDelay = 0;
+ _track[l].volFadeUsed = false;
+ _track[l].idSound = soundId;
+ _track[l].started = false;
+ _track[l].soundGroup = soundGroup;
+ _track[l].curHookId = 0;
+ _track[l].curRegion = 0;
+ _track[l].regionOffset = 0;
+ _track[l].trackOffset = 0;
+ _track[l].mod = 0;
+ _track[l].toBeRemoved = false;
+
+ int bits = 0, freq = 0, channels = 0, mixerFlags = 0;
+
+ if (input) {
+ // Do nothing here, we already have an audio stream
+ } else {
+ if (soundName == NULL)
+ _track[l].soundHandle = _sound->openSound(soundId, NULL, soundType, soundGroup);
+ else
+ _track[l].soundHandle = _sound->openSound(0, soundName, soundType, soundGroup);
+
+ if (_track[l].soundHandle == NULL)
+ return;
+
+ bits = _sound->getBits(_track[l].soundHandle);
+ channels = _sound->getChannels(_track[l].soundHandle);
+ freq = _sound->getFreq(_track[l].soundHandle);
+
+ if (channels == 2) {
+ mixerFlags = SoundMixer::FLAG_STEREO | SoundMixer::FLAG_REVERSE_STEREO;
+ _track[l].pullSize = freq * 2;
+ } else {
+ _track[l].pullSize = freq;
+ }
+
+ if (bits == 12) {
+ mixerFlags |= SoundMixer::FLAG_16BITS;
+ _track[l].pullSize *= 2;
+ } else if (bits == 16) {
+ mixerFlags |= SoundMixer::FLAG_16BITS;
+ _track[l].pullSize *= 2;
+ } else if (bits == 8) {
+ mixerFlags |= SoundMixer::FLAG_UNSIGNED;
+ } else
+ error("IMuseDigital::startSound(): Can't handle %d bit samples", bits);
+
+ _track[l].pullSize /= 25; // We want a "frame rate" of 25 audio blocks per second
+ if (soundGroup == IMUSE_MUSIC)
+ _curMusicId = soundId;
+ }
+
+ if (input) {
+ _track[l].stream2 = input;
+ _track[l].stream = NULL;
+ } else {
+ _track[l].stream2 = NULL;
+ _track[l].stream = makeAppendableAudioStream(freq, mixerFlags, 100000);
+ _scumm->_mixer->playInputStream(&_track[l].handle, _track[l].stream, true, _track[l].vol / 1000, _track[l].pan, -1, false);
+ }
+
+ _track[l].used = true;
+ return;
+ }
+ }
+ warning("IMuseDigital::startSound(): All slots are full");
+}
+
+void IMuseDigital::stopMusic() {
+ debug(5, "IMuseDigital::stopMusic()");
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].idSound == _curMusicId) && _track[l].used) {
+ if (_track[l].stream) {
+ _track[l].toBeRemoved = true;
+ }
+ }
+ }
+ _curMusicId = -1;
+}
+
+void IMuseDigital::stopSound(int soundId) {
+ debug(5, "IMuseDigital::stopSound(%d)", soundId);
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].idSound == soundId) && _track[l].used) {
+ if (_track[l].stream) {
+ _track[l].toBeRemoved = true;
+ }
+ else if (_track[l].stream2)
+ _scumm->_mixer->stopHandle(_track[l].handle);
+ }
+ }
+}
+
+void IMuseDigital::stopAllSounds() {
+ debug(5, "IMuseDigital::stopAllSounds");
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if (_track[l].used) {
+ if (_track[l].stream) {
+ _track[l].toBeRemoved = true;
+ } else if (_track[l].stream2)
+ _scumm->_mixer->stopHandle(_track[l].handle);
+ }
+ }
+}
+
+void IMuseDigital::pause(bool p) {
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if (_track[l].used) {
+ _scumm->_mixer->pauseHandle(_track[l].handle, p);
+ }
+ }
+ _pause = p;
+}
+
+void IMuseDigital::parseScriptCmds(int a, int b, int c, int d, int e, int f, int g, int h) {
+ int cmd = a;
+ int sample = b;
+ int sub_cmd = c;
+ int chan = -1;
+ int l, r;
+
+ if (!cmd)
+ return;
+
+ switch (cmd) {
+ case 10: // ImuseStopAllSounds
+ debug(5, "ImuseStopAllSounds()");
+ stopAllSounds();
+ break;
+ case 12: // ImuseSetParam
+ switch (sub_cmd) {
+ case 0x500: // set priority - could be ignored
+ break;
+ case 0x600: // set volume
+ debug(5, "ImuseSetParam (0x600), sample(%d), volume(%d)", sample, d);
+ for (l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].idSound == sample) && _track[l].used) {
+ _track[l].vol = d * 1000;
+// if (_track[l].volFadeUsed)
+// _track[l].volFadeStep = (_track[l].volFadeDest - _track[l].vol) * 60 * 40 / (1000 * _track[chan].volFadeDelay);
+ }
+ }
+ if (l == -1) {
+ debug(5, "ImuseSetParam (0x600), sample(%d) not exist in channels", sample);
+ return;
+ }
+ break;
+ case 0x700: // set pan
+ debug(5, "ImuseSetParam (0x700), sample(%d), pan(%d)", sample, d);
+ for (l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].idSound == sample) && _track[l].used) {
+ _track[l].pan = d;
+ }
+ }
+ if (l == -1) {
+ debug(5, "ImuseSetParam (0x700), sample(%d) not exist in channels", sample);
+ return;
+ }
+ break;
+ default:
+ warning("IMuseDigital::doCommand SetParam DEFAULT command %d", sub_cmd);
+ break;
+ }
+ break;
+ case 14: // ImuseFadeParam
+ switch (sub_cmd) {
+ case 0x600: // set new volume with fading
+ debug(5, "ImuseFadeParam - fade sample(%d), to volume(%d) with 60hz ticks(%d)", sample, d, e);
+ if ((_scumm->_gameId == GID_DIG) && (_scumm->_features & GF_DEMO)) {
+ stopSound(sample);
+ return;
+ }
+ for (l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].idSound == sample) && _track[l].used) {
+ _track[l].volFadeDelay = e;
+ _track[l].volFadeDest = d * 1000;
+ _track[l].volFadeStep = (_track[l].volFadeDest - _track[l].vol) * 60 * 40 / (1000 * e);
+ _track[l].volFadeUsed = true;
+ debug(5, "ImuseFadeParam: vol %d, volDest %d, step %d", _track[l].vol, d * 1000, _track[l].volFadeStep);
+ }
+ }
+ if (chan == -1) {
+ debug(5, "ImuseFadeParam (0x600), sample %d not exist in channels", sample);
+ return;
+ }
+ break;
+ default:
+ warning("IMuseDigital::doCommand FadeParam DEFAULT sub command %d", sub_cmd);
+ break;
+ }
+ break;
+ case 0x1000: // ImuseSetState
+ debug(5, "ImuseSetState (%d)", b);
+ if ((_scumm->_gameId == GID_DIG) && (_scumm->_features & GF_DEMO)) {
+ if (b == 1)
+ startMusic(1);
+ else {
+ if (getSoundStatus(2) == 0)
+ startMusic(2);
+ }
+ } else if (_scumm->_gameId == GID_DIG) {
+ if (b == 1000) { // STATE_NULL
+ stopMusic();
+ return;
+ }
+ for (l = 0; _digStateMusicMap[l].room != -1; l++) {
+ if (_digStateMusicMap[l].room == b) {
+ int music = _digStateMusicMap[l].table_index;
+ debug(5, "Play imuse music: %s, %s, %s", _digStateMusicTable[music].name, _digStateMusicTable[music].title, _digStateMusicTable[music].filename);
+ if (_digStateMusicTable[music].filename[0] != 0) {
+ startMusic((char *)_digStateMusicTable[music].filename, _digStateMusicTable[music].id);
+ }
+ break;
+ }
+ }
+ } else if ((_scumm->_gameId == GID_CMI) && (_scumm->_features & GF_DEMO)) {
+ if (b == 2) {
+ startMusic("in1.imx", 2002);
+ } else if (b == 4) {
+ startMusic("in2.imx", 2004);
+ } else if (b == 8) {
+ startMusic("out1.imx", 2008);
+ } else if (b == 9) {
+ startMusic("out2.imx", 2009);
+ } else if (b == 16) {
+ startMusic("gun.imx", 2016);
+ } else {
+ warning("imuse digital: set state unknown for cmi demo: %d, room: %d", b, this->_scumm->_currentRoom);
+ }
+ } else if (_scumm->_gameId == GID_CMI) {
+ if (b == 1000) { // STATE_NULL
+ stopMusic();
+ return;
+ }
+ for (l = 0; _comiStateMusicTable[l].id != -1; l++) {
+ if ((_comiStateMusicTable[l].id == b)) {
+ debug(5, "Play imuse music: %s, %s, %s", _comiStateMusicTable[l].name, _comiStateMusicTable[l].title, _comiStateMusicTable[l].filename);
+ if (_comiStateMusicTable[l].filename[0] != 0) {
+ startMusic((char *)_comiStateMusicTable[l].filename, b);
+ }
+ break;
+ }
+ }
+ } else if (_scumm->_gameId == GID_FT) {
+ for (l = 0;; l++) {
+ if (_ftStateMusicTable[l].index == -1) {
+ return;
+ }
+ if (_ftStateMusicTable[l].index == b) {
+ debug(5, "Play imuse music: %s, %s", _ftStateMusicTable[l].name, _ftStateMusicTable[l].audioname);
+ if (_ftStateMusicTable[l].audioname[0] != 0) {
+ for (r = 0; r < _scumm->_numAudioNames; r++) {
+ if (strcmp(_ftStateMusicTable[l].audioname, &_scumm->_audioNames[r * 9]) == 0) {
+ startMusic(r);
+ parseScriptCmds(12, r, 0x600, _ftStateMusicTable[l].volume, 0, 0, 0, 0);
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ case 0x1001: // ImuseSetSequence
+ debug(5, "ImuseSetSequence (%d)", b);
+ if (_scumm->_gameId == GID_DIG) {
+ for (l = 0; _digSeqMusicTable[l].room != -1; l++) {
+ if (_digSeqMusicTable[l].room == b) {
+ debug(5, "Play imuse music: %s, %s, %s", _digSeqMusicTable[l].name, _digSeqMusicTable[l].title, _digSeqMusicTable[l].filename);
+ if (_digSeqMusicTable[l].filename[0] != 0) {
+ startMusic((char *)_digSeqMusicTable[l].filename, b);
+ }
+ break;
+ }
+ }
+ } else if (_scumm->_gameId == GID_CMI) {
+ for (l = 0; _comiSeqMusicTable[l].id != -1; l++) {
+ if (_comiSeqMusicTable[l].id == b) {
+ debug(5, "Play imuse music: %s, %s, %s", _comiSeqMusicTable[l].name, _comiSeqMusicTable[l].title, _comiSeqMusicTable[l].filename);
+ if (_comiSeqMusicTable[l].filename[0] != 0) {
+ startMusic((char *)_comiSeqMusicTable[l].filename, b);
+ }
+ break;
+ }
+ }
+ } else if (_scumm->_gameId == GID_FT) {
+ for (l = 0; _ftSeqMusicTable[l].index != -1; l++) {
+ if (_ftSeqMusicTable[l].index == b) {
+ debug(5, "Play imuse music: %s, %s", _ftSeqMusicTable[l].name, _ftSeqMusicTable[l].audioname);
+ if (_ftSeqMusicTable[l].audioname[0] != 0) {
+ for (r = 0; r < _scumm->_numAudioNames; r++) {
+ if (strcmp(_ftSeqMusicTable[l].audioname, &_scumm->_audioNames[r * 9]) == 0) {
+ startMusic(r);
+ parseScriptCmds(12, r, 0x600, _ftSeqMusicTable[l].volume, 0, 0, 0, 0);
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ case 0x1002: // ImuseSetCuePoint
+ debug(5, "ImuseSetCuePoint (%d)", b);
+ // TODO
+ break;
+ case 0x1003: // ImuseSetAttribute
+ debug(5, "ImuseSetAttribute (%d, %d)", b, c);
+ // TODO
+ break;
+ case 0x2000: // ImuseSetMasterSFXVolume
+ debug(5, "ImuseSetMasterSFXVolume (%d)", b);
+ // TODO
+ break;
+ case 0x2001: // ImuseSetMasterVoiceVolume
+ debug(5, "ImuseSetMasterVoiceVolume (%d)", b);
+ // TODO
+ break;
+ case 0x2002: // ImuseSetMasterMusicVolume
+ debug(5, "ImuseSetMasterMusicVolume (%d)", b);
+ // TODO
+ break;
+ default:
+ warning("IMuseDigital::doCommand DEFAULT command %d", cmd);
+ }
+}
+
+int IMuseDigital::getSoundStatus(int sound) const {
+ debug(5, "IMuseDigital::getSoundStatus(%d)", sound);
+ for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
+ if ((_track[l].idSound == sound) && _track[l].used) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void IMuseDigital::closeBundleFiles() {
+ // TODO
+}
+
+int32 IMuseDigital::getCurMusicPosInMs() {
+ // TODO
+ return 0;
+}
+
+int32 IMuseDigital::getCurVoiceLipSyncWidth() {
+ // TODO
+ return _scumm->_rnd.getRandomNumber(255);
+}
+
+int32 IMuseDigital::getCurVoiceLipSyncHeight() {
+ // TODO
+ return _scumm->_rnd.getRandomNumber(255);
+}
+
+int32 IMuseDigital::getCurMusicLipSyncWidth() {
+ // TODO
+ return _scumm->_rnd.getRandomNumber(255);
+}
+
+int32 IMuseDigital::getCurMusicLipSyncHeight() {
+ // TODO
+ return _scumm->_rnd.getRandomNumber(255);
+}
+
+} // End of namespace Scumm
diff --git a/scumm/imuse_digi/dimuse.h b/scumm/imuse_digi/dimuse.h
new file mode 100644
index 0000000000..cb2ba02d1b
--- /dev/null
+++ b/scumm/imuse_digi/dimuse.h
@@ -0,0 +1,154 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001-2004 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#ifndef IMUSE_DIGI_H
+#define IMUSE_DIGI_H
+
+#include "common/scummsys.h"
+
+#include "scumm/imuse_digi/dimuse.h"
+#include "scumm/imuse_digi/dimuse_bndmgr.h"
+#include "scumm/imuse_digi/dimuse_sndmgr.h"
+#include "scumm/music.h"
+
+#include "sound/mixer.h"
+#include "sound/audiostream.h"
+
+namespace Scumm {
+
+#define MAX_DIGITAL_TRACKS 16
+
+class IMuseDigital : public MusicEngine {
+private:
+
+ struct Track {
+ int8 pan; // pan
+ int32 vol; // volume
+ int32 volFadeDest; //
+ int32 volFadeStep; //
+ int32 volFadeDelay; //
+ bool volFadeUsed; //
+
+ int idSound;
+ bool used;
+ bool toBeRemoved;
+ bool started;
+ int32 regionOffset;
+ int32 trackOffset;
+ int curRegion;
+ int curHookId;
+ int soundGroup;
+ void *soundHandle;
+ int32 pullSize;
+ int mod;
+ PlayingSoundHandle handle;
+ AppendableAudioStream *stream;
+ AudioStream *stream2;
+
+ Track();
+ };
+
+ Track _track[MAX_DIGITAL_TRACKS];
+
+ ScummEngine *_scumm;
+ ImuseDigiSndMgr *_sound;
+ bool _pause;
+ int _curMusicId;
+
+ static void timer_handler(void *refConf);
+ void callback();
+ void switchToNextRegion(int track);
+ void startSound(int soundId, char *soundName, int soundType, int soundGroup, AudioStream *input);
+
+public:
+ IMuseDigital(ScummEngine *scumm);
+ ~IMuseDigital();
+
+ void startVoice(int soundId, AudioStream *input)
+ { debug(0, "startVoiceStream(%d)", soundId); startSound(soundId, NULL, 0, IMUSE_VOICE, input); }
+ void startVoice(int soundId)
+ { debug(0, "startVoiceBundle(%d)", soundId); startSound(soundId, NULL, IMUSE_BUNDLE, IMUSE_VOICE, NULL); }
+ void startVoice(int soundId, char *soundName)
+ { debug(0, "startVoiceBundle(%s)", soundName); startSound(soundId, soundName, IMUSE_BUNDLE, IMUSE_VOICE, NULL); }
+ void startMusic(int soundId)
+ { debug(0, "startMusicResource(%d)", soundId); startSound(soundId, NULL, IMUSE_RESOURCE, IMUSE_MUSIC, NULL); }
+ void startMusic(char *soundName, int soundId)
+ { debug(0, "startMusicBundle(%s)", soundName); startSound(soundId, soundName, IMUSE_BUNDLE, IMUSE_MUSIC, NULL); }
+ void startSfx(int soundId)
+ { debug(0, "startSfx(%d)", soundId); startSound(soundId, NULL, IMUSE_RESOURCE, IMUSE_SFX, NULL); }
+ void startSound(int soundId)
+ { error("MusicEngine::startSound() Should be never called"); }
+
+ void setMasterVolume(int vol) {}
+ void stopMusic();
+ void stopSound(int soundId);
+ void stopAllSounds();
+ void pause(bool pause);
+ void parseScriptCmds(int a, int b, int c, int d, int e, int f, int g, int h);
+ int getSoundStatus(int sound) const;
+ int32 getCurMusicPosInMs();
+ int32 getCurVoiceLipSyncWidth();
+ int32 getCurVoiceLipSyncHeight();
+ int32 getCurMusicLipSyncWidth();
+ int32 getCurMusicLipSyncHeight();
+
+ void closeBundleFiles();
+};
+
+struct imuse_music_table {
+ int room;
+ int id;
+ int unk1;
+ int unk2;
+ int unk3;
+ int unk4;
+ char name[30];
+ char title[30];
+ char filename[13];
+};
+
+struct imuse_music_map {
+ int room;
+ int table_index;
+ int unk1;
+ int unk2;
+ int unk3;
+ int unk4;
+};
+
+struct imuse_ft_music_table {
+ int index;
+ char audioname[15];
+ int unk1;
+ int volume;
+ char name[30];
+};
+
+extern imuse_music_map _digStateMusicMap[];
+extern const imuse_music_table _digStateMusicTable[];
+extern const imuse_music_table _digSeqMusicTable[];
+extern const imuse_music_table _comiStateMusicTable[];
+extern const imuse_music_table _comiSeqMusicTable[];
+extern const imuse_ft_music_table _ftStateMusicTable[];
+extern const imuse_ft_music_table _ftSeqMusicTable[];
+
+} // End of namespace Scumm
+
+#endif
diff --git a/scumm/imuse_digi/dimuse_bndmgr.cpp b/scumm/imuse_digi/dimuse_bndmgr.cpp
new file mode 100644
index 0000000000..915ea73785
--- /dev/null
+++ b/scumm/imuse_digi/dimuse_bndmgr.cpp
@@ -0,0 +1,179 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001-2004 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#include "stdafx.h"
+#include "common/scummsys.h"
+#include "scumm/scumm.h"
+#include "scumm/imuse_digi/dimuse_bndmgr.h"
+
+namespace Scumm {
+
+BundleMgr::BundleMgr() {
+ _compTable = NULL;
+ _bundleTable = NULL;
+ _numFiles = 0;
+ _curSample = -1;
+}
+
+BundleMgr::~BundleMgr() {
+ free(_bundleTable);
+ free(_compTable);
+}
+
+bool BundleMgr::openFile(const char *filename, const char *directory) {
+ int32 tag, offset;
+
+ if (_file.isOpen())
+ return true;
+
+ if (_file.open(filename, directory) == false) {
+ warning("BundleMgr::openFile() Can't open bundle file: %s", filename);
+ return false;
+ }
+
+ tag = _file.readUint32BE();
+ offset = _file.readUint32BE();
+ _numFiles = _file.readUint32BE();
+
+ _bundleTable = (AudioTable *) malloc(_numFiles * sizeof(AudioTable));
+
+ _file.seek(offset, SEEK_SET);
+
+ for (int32 i = 0; i < _numFiles; i++) {
+ char name[13], c;
+ int32 z = 0;
+ int32 z2;
+
+ for (z2 = 0; z2 < 8; z2++)
+ if ((c = _file.readByte()) != 0)
+ name[z++] = c;
+ name[z++] = '.';
+ for (z2 = 0; z2 < 4; z2++)
+ if ((c = _file.readByte()) != 0)
+ name[z++] = c;
+ name[z] = '\0';
+ strcpy(_bundleTable[i].filename, name);
+ _bundleTable[i].offset = _file.readUint32BE();
+ _bundleTable[i].size = _file.readUint32BE();
+ }
+
+ return true;
+}
+
+void BundleMgr::closeFile() {
+ if (_file.isOpen()) {
+ _file.close();
+ free(_bundleTable);
+ _bundleTable = NULL;
+ }
+}
+
+int32 BundleMgr::decompressSampleByCurIndex(int32 offset, int32 size, byte **comp_final, int header_size) {
+ return decompressSampleByIndex(_curSample, offset, size, comp_final, header_size);
+}
+
+int32 BundleMgr::decompressSampleByIndex(int32 index, int32 offset, int32 size, byte **comp_final, int header_size) {
+ int32 i, tag, num, final_size, output_size;
+ byte *comp_input, *comp_output;
+
+ if (index != -1)
+ _curSample = index;
+
+ if (_file.isOpen() == false) {
+ warning("BundleMgr::decompressSampleByIndex() File is not open!");
+ return 0;
+ }
+
+ _file.seek(_bundleTable[index].offset, SEEK_SET);
+ tag = _file.readUint32BE();
+ num = _file.readUint32BE();
+ _file.readUint32BE();
+ _file.readUint32BE();
+
+ if (tag != MKID_BE('COMP')) {
+ warning("BundleMgr::decompressSampleByIndex() Compressed sound %d invalid (%s)", index, tag2str(tag));
+ return 0;
+ }
+
+ free(_compTable);
+ _compTable = (CompTable *)malloc(sizeof(CompTable) * num);
+ for (i = 0; i < num; i++) {
+ _compTable[i].offset = _file.readUint32BE();
+ _compTable[i].size = _file.readUint32BE();
+ _compTable[i].codec = _file.readUint32BE();
+ _file.readUint32BE();
+ }
+
+ int first_block = (offset + header_size) / 0x2000;
+ int last_block = (offset + size + header_size - 1) / 0x2000;
+
+ comp_output = (byte *)malloc(0x2000);
+ *comp_final = (byte *)malloc(0x2000 * (1 + last_block - first_block));
+ final_size = 0;
+
+ int skip = offset - (first_block * 0x2000) + header_size;
+
+ for (i = first_block; i <= last_block; i++) {
+ assert(size);
+ // CMI hack: one more zero byte at the end of input buffer
+ comp_input = (byte *)malloc(_compTable[i].size + 1);
+ comp_input[_compTable[i].size] = 0;
+
+ _file.seek(_bundleTable[index].offset + _compTable[i].offset, SEEK_SET);
+ _file.read(comp_input, _compTable[i].size);
+
+ output_size = BundleCodecs::decompressCodec(_compTable[i].codec, comp_input, comp_output, _compTable[i].size);
+ assert(output_size <= 0x2000);
+ if ((header_size != 0) && (skip > header_size))
+ output_size -= skip;
+ if (output_size > size)
+ output_size = size;
+ memcpy(*comp_final + final_size, comp_output + skip, output_size);
+ final_size += output_size;
+ size -= output_size;
+ if (skip > 0)
+ skip = 0;
+
+ free(comp_input);
+ }
+ free(comp_output);
+
+ return final_size;
+}
+
+int32 BundleMgr::decompressSampleByName(const char *name, int32 offset, int32 size, byte **comp_final) {
+ int32 final_size = 0, i;
+
+ if (_file.isOpen() == false) {
+ warning("BundleMgr::decompressSampleByName() File is not open!");
+ return 0;
+ }
+
+ for (i = 0; i < _numFiles; i++) {
+ if (!scumm_stricmp(name, _bundleTable[i].filename)) {
+ final_size = decompressSampleByIndex(i, offset, size, comp_final, 0);
+ return final_size;
+ }
+ }
+ debug(2, "BundleMgr::decompressSampleByName() Failed finding voice %s", name);
+ return final_size;
+}
+
+} // End of namespace Scumm
diff --git a/scumm/imuse_digi/dimuse_bndmgr.h b/scumm/imuse_digi/dimuse_bndmgr.h
new file mode 100644
index 0000000000..11560f1ee5
--- /dev/null
+++ b/scumm/imuse_digi/dimuse_bndmgr.h
@@ -0,0 +1,72 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001-2004 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#ifndef BUNDLE_MGR_H
+#define BUNDLE_MGR_H
+
+#include "common/scummsys.h"
+#include "common/file.h"
+
+namespace Scumm {
+
+class BundleMgr {
+
+private:
+
+ struct CompTable {
+ int32 offset;
+ int32 size;
+ int32 codec;
+ };
+
+ struct AudioTable {
+ char filename[13];
+ int32 size;
+ int32 offset;
+ };
+
+ CompTable *_compTable;
+ AudioTable *_bundleTable;
+ int32 _numFiles;
+ int32 _curSample;
+ File _file;
+
+public:
+ BundleMgr();
+ ~BundleMgr();
+
+ bool openFile(const char *filename, const char *directory);
+ void closeFile();
+ int32 decompressSampleByName(const char *name, int32 offset, int32 size, byte **comp_final);
+ int32 decompressSampleByIndex(int32 index, int32 offset, int32 size, byte **comp_final, int header_size);
+ int32 decompressSampleByCurIndex(int32 offset, int32 size, byte **comp_final, int header_size);
+};
+
+namespace BundleCodecs {
+
+uint32 decode12BitsSample(byte *src, byte **dst, uint32 size);
+void initializeImcTables();
+int32 decompressCodec(int32 codec, byte *comp_input, byte *comp_output, int32 input_size);
+
+} // End of namespace BundleCodecs
+
+} // End of namespace Scumm
+
+#endif
diff --git a/scumm/bundle.cpp b/scumm/imuse_digi/dimuse_codecs.cpp
index 921655458a..5d3e1f78f2 100644
--- a/scumm/bundle.cpp
+++ b/scumm/imuse_digi/dimuse_codecs.cpp
@@ -1,5 +1,5 @@
/* ScummVM - Scumm Interpreter
- * Copyright (C) 2002-2004 The ScummVM project
+ * Copyright (C) 2001-2004 The ScummVM project
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -20,11 +20,33 @@
#include "stdafx.h"
#include "common/scummsys.h"
-#include "scumm/scumm.h"
-#include "scumm/bundle.h"
+#include "common/util.h"
namespace Scumm {
+namespace BundleCodecs {
+
+uint32 decode12BitsSample(byte *src, byte **dst, uint32 size) {
+ uint32 loop_size = size / 3;
+ uint32 s_size = loop_size * 4;
+ byte *ptr = *dst = (byte *)malloc(s_size);
+
+ uint32 tmp;
+ while (loop_size--) {
+ byte v1 = *src++;
+ byte v2 = *src++;
+ byte v3 = *src++;
+ tmp = ((((v2 & 0x0f) << 8) | v1) << 4) - 0x8000;
+ WRITE_BE_UINT16(ptr, tmp); ptr += 2;
+ tmp = ((((v2 & 0xf0) << 4) | v3) << 4) - 0x8000;
+ WRITE_BE_UINT16(ptr, tmp); ptr += 2;
+ }
+ return s_size;
+}
+
+static byte _destImcTable[93];
+static uint32 _destImcTable2[5697];
+
#ifdef __PALM_OS__
static const int16 *imcTable;
#else
@@ -97,30 +119,7 @@ static const byte imxShortTable[] = {
0, 0, 1, 3, 7, 15, 31, 63
};
-
-Bundle::Bundle() {
- _compVoiceTable = NULL;
- _compMusicTable = NULL;
-
- _bundleVoiceTable = NULL;
- _bundleMusicTable = NULL;
-
- _numVoiceFiles = 0;
- _numMusicFiles = 0;
-
- _lastSong = -1;
-
- initializeImcTables();
-}
-
-Bundle::~Bundle() {
- free(_bundleVoiceTable);
- free(_bundleMusicTable);
- free(_compVoiceTable);
- free(_compMusicTable);
-}
-
-void Bundle::initializeImcTables() {
+void initializeImcTables() {
int32 destTablePos = 0;
int32 imcTable1Pos = 0;
do {
@@ -163,279 +162,6 @@ void Bundle::initializeImcTables() {
} while (++imcTable1Pos <= 88);
}
}
-
-bool Bundle::openVoiceFile(const char *filename, const char *directory) {
- int32 tag, offset;
-
- if (_voiceFile.isOpen())
- return true;
-
- if (_voiceFile.open(filename, directory) == false) {
- warning("Bundle: Can't open voice bundle file: %s", filename);
- return false;
- }
-
- tag = _voiceFile.readUint32BE();
- offset = _voiceFile.readUint32BE();
- _numVoiceFiles = _voiceFile.readUint32BE();
-
- _bundleVoiceTable = (BundleAudioTable *) malloc(_numVoiceFiles * sizeof(BundleAudioTable));
-
- _voiceFile.seek(offset, SEEK_SET);
-
- for (int32 i = 0; i < _numVoiceFiles; i++) {
- char name[13], c;
- int32 z = 0;
- int32 z2;
-
- for (z2 = 0; z2 < 8; z2++)
- if ((c = _voiceFile.readByte()) != 0)
- name[z++] = c;
- name[z++] = '.';
- for (z2 = 0; z2 < 4; z2++)
- if ((c = _voiceFile.readByte()) != 0)
- name[z++] = c;
- name[z] = '\0';
- strcpy(_bundleVoiceTable[i].filename, name);
- _bundleVoiceTable[i].offset = _voiceFile.readUint32BE();
- _bundleVoiceTable[i].size = _voiceFile.readUint32BE();
- }
-
- return true;
-}
-
-void Bundle::closeVoiceFile() {
- if (_voiceFile.isOpen()) {
- _voiceFile.close();
- free(_bundleVoiceTable);
- _bundleVoiceTable = NULL;
- }
-}
-
-bool Bundle::openMusicFile(const char *filename, const char *directory) {
- int32 tag, offset;
-
- if (_musicFile.isOpen())
- return true;
-
- if (_musicFile.open(filename, directory) == false) {
- warning("Bundle: Can't open music bundle file: %s", filename);
- return false;
- }
-
- tag = _musicFile.readUint32BE();
- offset = _musicFile.readUint32BE();
- _numMusicFiles = _musicFile.readUint32BE();
-
- _bundleMusicTable = (BundleAudioTable *) malloc(_numMusicFiles * sizeof(BundleAudioTable));
-
- _musicFile.seek(offset, SEEK_SET);
-
- for (int32 i = 0; i < _numMusicFiles; i++) {
- char name[13], c;
- int z = 0;
- int z2;
-
- for (z2 = 0; z2 < 8; z2++)
- if ((c = _musicFile.readByte()) != 0)
- name[z++] = c;
- name[z++] = '.';
- for (z2 = 0; z2 < 4; z2++)
- if ((c = _musicFile.readByte()) != 0)
- name[z++] = c;
- name[z] = '\0';
- strcpy(_bundleMusicTable[i].filename, name);
- _bundleMusicTable[i].offset = _musicFile.readUint32BE();
- _bundleMusicTable[i].size = _musicFile.readUint32BE();
- }
-
- return true;
-}
-
-void Bundle::closeMusicFile() {
- if (_musicFile.isOpen()) {
- _musicFile.close();
- free(_bundleMusicTable);
- _bundleMusicTable = NULL;
- _lastSong = -1;
- }
-}
-
-
-int32 Bundle::decompressVoiceSampleByIndex(int32 index, byte **comp_final) {
- int32 i, tag, num, final_size, output_size;
- byte *comp_input, *comp_output;
-
- if (_voiceFile.isOpen() == false) {
- warning("Bundle: voice file is not open!");
- return 0;
- }
-
- _voiceFile.seek(_bundleVoiceTable[index].offset, SEEK_SET);
- tag = _voiceFile.readUint32BE();
- num = _voiceFile.readUint32BE();
- _voiceFile.readUint32BE();
- _voiceFile.readUint32BE();
-
- if (tag != MKID_BE('COMP')) {
- warning("Bundle: Compressed sound %d invalid (%s)", index, tag2str(tag));
- return 0;
- }
-
- free(_compVoiceTable);
- _compVoiceTable = (CompTable *)malloc(sizeof(CompTable) * num);
- for (i = 0; i < num; i++) {
- _compVoiceTable[i].offset = _voiceFile.readUint32BE();
- _compVoiceTable[i].size = _voiceFile.readUint32BE();
- _compVoiceTable[i].codec = _voiceFile.readUint32BE();
- _voiceFile.readUint32BE();
- }
-
- final_size = 0;
-
- comp_output = (byte *)malloc(0x2000);
-
- *comp_final = (byte *)malloc(0x2000 * num);
-
- for (i = 0; i < num; i++) {
- // CMI hack: one more zero byte at the end of input buffer
- comp_input = (byte *)malloc(_compVoiceTable[i].size + 1);
- comp_input[_compVoiceTable[i].size] = 0;
-
- _voiceFile.seek(_bundleVoiceTable[index].offset + _compVoiceTable[i].offset, SEEK_SET);
- _voiceFile.read(comp_input, _compVoiceTable[i].size);
-
- output_size = decompressCodec(_compVoiceTable[i].codec, comp_input, comp_output, _compVoiceTable[i].size);
- assert(output_size <= 0x2000);
- memcpy(*comp_final + final_size, comp_output, output_size);
- final_size += output_size;
-
- free(comp_input);
- }
- free(comp_output);
-
- return final_size;
-}
-
-int32 Bundle::decompressMusicSampleByIndex(int32 index, int32 number, byte *comp_final) {
- int final_size;
- byte *comp_input;
-
- if (_musicFile.isOpen() == false) {
- warning("Bundle: music file is not open!");
- return 0;
- }
-
- if (_lastSong != index) {
- int i, tag, num;
- _musicFile.seek(_bundleMusicTable[index].offset, SEEK_SET);
- tag = _musicFile.readUint32BE();
- num = _musicFile.readUint32BE();
- _musicFile.readUint32BE();
- _musicFile.readUint32BE();
-
- if (tag != MKID_BE('COMP')) {
- warning("Bundle: Compressed sound %d invalid (%s)", index, tag2str(tag));
- return 0;
- }
-
- free(_compMusicTable);
- _compMusicTable = (CompTable *)malloc(sizeof(CompTable) * num);
-
- for (i = 0; i < num; i++) {
- _compMusicTable[i].offset = _musicFile.readUint32BE();
- _compMusicTable[i].size = _musicFile.readUint32BE();
- _compMusicTable[i].codec = _musicFile.readUint32BE();
- _musicFile.readUint32BE();
- }
-
- _lastSong = index;
- }
-
- // CMI hack: one more zero byte at the end of input buffer
- comp_input = (byte *)malloc(_compMusicTable[number].size + 1);
- comp_input[_compMusicTable[number].size] = 0;
-
- _musicFile.seek(_bundleMusicTable[index].offset + _compMusicTable[number].offset, SEEK_SET);
- _musicFile.read(comp_input, _compMusicTable[number].size);
-
- final_size = decompressCodec(_compMusicTable[number].codec, comp_input, comp_final, _compMusicTable[number].size);
-
- free(comp_input);
-
- return final_size;
-}
-
-int32 Bundle::decompressVoiceSampleByName(const char *name, byte **comp_final) {
- int32 final_size = 0, i;
-
- if (_voiceFile.isOpen() == false) {
- warning("Bundle: voice file is not open!");
- return 0;
- }
-
- for (i = 0; i < _numVoiceFiles; i++) {
- if (!scumm_stricmp(name, _bundleVoiceTable[i].filename)) {
- final_size = decompressVoiceSampleByIndex(i, comp_final);
- return final_size;
- }
- }
- debug(2, "Failed finding voice %s", name);
- return final_size;
-}
-
-int32 Bundle::decompressMusicSampleByName(const char *name, int32 number, byte *comp_final) {
- int32 final_size = 0, i;
-
- if (!name) {
- warning("Bundle: decompressMusicSampleByName called with no name!");
- return 0;
- }
-
- if (_musicFile.isOpen() == false) {
- warning("Bundle: music file is not open!");
- return 0;
- }
-
- for (i = 0; i < _numMusicFiles; i++) {
- if (!scumm_stricmp(name, _bundleMusicTable[i].filename)) {
- final_size = decompressMusicSampleByIndex(i, number, comp_final);
- return final_size;
- }
- }
- warning("Couldn't find sample %s", name);
- return final_size;
-}
-
-int32 Bundle::getNumberOfMusicSamplesByIndex(int32 index) {
- if (_musicFile.isOpen() == false) {
- warning("Bundle: music file is not open!");
- return 0;
- }
-
- _musicFile.seek(_bundleMusicTable[index].offset, SEEK_SET);
- _musicFile.readUint32BE();
- return _musicFile.readUint32BE();
-}
-
-int32 Bundle::getNumberOfMusicSamplesByName(const char *name) {
- int32 number = 0, i;
-
- if (_musicFile.isOpen() == false) {
- warning("Bundle: music file is not open!");
- return 0;
- }
-
- for (i = 0; i < _numMusicFiles; i++) {
- if (!scumm_stricmp(name, _bundleMusicTable[i].filename)) {
- number = getNumberOfMusicSamplesByIndex(i);
- return number;
- }
- }
- warning("Couldn't find numsample %s", name);
- return number;
-}
-
#define NextBit \
do { \
bit = mask & 1; \
@@ -483,7 +209,7 @@ static int32 compDecode(byte *src, byte *dst) {
}
#undef NextBit
-int32 Bundle::decompressCodec(int32 codec, byte *comp_input, byte *comp_output, int32 input_size) {
+int32 decompressCodec(int32 codec, byte *comp_input, byte *comp_output, int32 input_size) {
int32 output_size, channels;
int32 offset1, offset2, offset3, length, k, c, s, j, r, t, z;
byte *src, *t_table, *p, *ptr;
@@ -946,7 +672,7 @@ int32 Bundle::decompressCodec(int32 codec, byte *comp_input, byte *comp_output,
break;
default:
- warning("Bundle: Unknown codec %d!", (int)codec);
+ error("BundleCodecs::decompressCodec() Unknown codec %d!", (int)codec);
output_size = 0;
break;
}
@@ -954,19 +680,19 @@ int32 Bundle::decompressCodec(int32 codec, byte *comp_input, byte *comp_output,
return output_size;
}
+} // End of namespace BundleCodecs
+
} // End of namespace Scumm
#ifdef __PALM_OS__
#include "scumm_globals.h"
-_GINIT(Bundle)
-_GSETPTR(Scumm::imcTable, GBVARS_IMCTABLE_INDEX, int16, GBVARS_SCUMM)
+_GINIT(BundleCodecs)
+_GSETPTR(Scumm::BundleCodecs::imcTable, GBVARS_IMCTABLE_INDEX, int16, GBVARS_SCUMM)
_GEND
-_GRELEASE(Bundle)
+_GRELEASE(BundleCodecs)
_GRELEASEPTR(GBVARS_IMCTABLE_INDEX, GBVARS_SCUMM)
_GEND
#endif
-
-
diff --git a/scumm/imuse_digi/dimuse_sndmgr.cpp b/scumm/imuse_digi/dimuse_sndmgr.cpp
new file mode 100644
index 0000000000..51a3e5eb09
--- /dev/null
+++ b/scumm/imuse_digi/dimuse_sndmgr.cpp
@@ -0,0 +1,462 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001-2004 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#include "stdafx.h"
+#include "common/scummsys.h"
+#include "common/util.h"
+#include "sound/voc.h"
+#include "scumm/scumm.h"
+#include "scumm/imuse_digi/dimuse_sndmgr.h"
+#include "scumm/imuse_digi/dimuse_bndmgr.h"
+
+namespace Scumm {
+
+ImuseDigiSndMgr::ImuseDigiSndMgr(ScummEngine *scumm) {
+ memset(&_sounds, 0, sizeof(_sounds));
+ _scumm = scumm;
+ _mutex = g_system->create_mutex();
+ _disk = 0;
+ _accessFree = true;
+ BundleCodecs::initializeImcTables();
+}
+
+ImuseDigiSndMgr::~ImuseDigiSndMgr() {
+ for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
+ closeSound(&_sounds[l]);
+ }
+}
+
+void ImuseDigiSndMgr::waitForFreeAccess() {
+ Common::StackLock lock(_mutex);
+ while (!_accessFree) {
+ }
+}
+
+void ImuseDigiSndMgr::lock() {
+ Common::StackLock lock(_mutex);
+ waitForFreeAccess();
+ _accessFree = false;
+}
+
+void ImuseDigiSndMgr::unlock() {
+ Common::StackLock lock(_mutex);
+ _accessFree = true;
+}
+
+void ImuseDigiSndMgr::prepareSound(byte *ptr, int slot) {
+ Common::StackLock lock(_mutex);
+ if (READ_UINT32(ptr) == MKID('Crea')) {
+ int size, rate, loops;
+ _sounds[slot].resPtr = readVOCFromMemory(ptr, size, rate, loops);
+ _sounds[slot].freeResPtr = true;
+ _sounds[slot].bits = 8;
+ _sounds[slot].freq = rate;
+ _sounds[slot].channels = 1;
+ _sounds[slot].region[0].length = size;
+ _sounds[slot].numRegions++;
+ _sounds[slot].numJumps++;
+ } else if (READ_UINT32(ptr) == MKID('iMUS')) {
+ uint32 tag;
+ int32 size = 0;
+ byte *s_ptr = ptr;
+
+ ptr += 16;
+ do {
+ tag = READ_BE_UINT32(ptr); ptr += 4;
+ switch(tag) {
+ case MKID_BE('FRMT'):
+ ptr += 12;
+ _sounds[slot].bits = READ_BE_UINT32(ptr); ptr += 4;
+ _sounds[slot].freq = READ_BE_UINT32(ptr); ptr += 4;
+ _sounds[slot].channels = READ_BE_UINT32(ptr); ptr += 4;
+ break;
+ case MKID_BE('TEXT'):
+ size = READ_BE_UINT32(ptr); ptr += 4;
+ if (_sounds[slot].numMarkers >= MAX_IMUSE_MARKERS) {
+ warning("ImuseDigiSndMgr::prepareSound() Not enough space for Marker");
+ ptr += size;
+ break;
+ }
+ strcpy(_sounds[slot].marker[_sounds[slot].numMarkers].name, (char *)ptr + 4);
+ _sounds[slot].numMarkers++;
+ ptr += size;
+ break;
+ case MKID_BE('REGN'):
+ size = READ_BE_UINT32(ptr); ptr += 4;
+ if (_sounds[slot].numRegions >= MAX_IMUSE_REGIONS) {
+ warning("ImuseDigiSndMgr::prepareSound() Not enough space for Region");
+ ptr += 8;
+ break;
+ }
+ _sounds[slot].region[_sounds[slot].numRegions].offset = READ_BE_UINT32(ptr); ptr += 4;
+ _sounds[slot].region[_sounds[slot].numRegions].length = READ_BE_UINT32(ptr); ptr += 4;
+ _sounds[slot].numRegions++;
+ break;
+ case MKID_BE('STOP'):
+ ptr += 4;
+ _sounds[slot].offsetStop = READ_BE_UINT32(ptr); ptr += 4;
+ break;
+ case MKID_BE('JUMP'):
+ size = READ_BE_UINT32(ptr); ptr += 4;
+ if (_sounds[slot].numJumps >= MAX_IMUSE_JUMPS) {
+ warning("ImuseDigiSndMgr::prepareSound() Not enough space for Jump");
+ ptr += size;
+ break;
+ }
+ _sounds[slot].jump[_sounds[slot].numJumps].offset = READ_BE_UINT32(ptr); ptr += 4;
+ _sounds[slot].jump[_sounds[slot].numJumps].dest = READ_BE_UINT32(ptr); ptr += 4;
+ _sounds[slot].jump[_sounds[slot].numJumps].hookId = READ_BE_UINT32(ptr); ptr += 4;
+ _sounds[slot].jump[_sounds[slot].numJumps].fadeDelay = READ_BE_UINT32(ptr); ptr += 4;
+ _sounds[slot].numJumps++;
+ break;
+ case MKID_BE('SYNC'):
+ size = READ_BE_UINT32(ptr); ptr += size + 4;
+ break;
+ case MKID_BE('DATA'):
+ size = READ_BE_UINT32(ptr); ptr += 4;
+ break;
+ default:
+ error("ImuseDigiSndMgr::prepareSound() Unknown sfx header '%s'", tag2str(tag));
+ }
+ } while (tag != MKID_BE('DATA'));
+ _sounds[slot].offsetData = ptr - s_ptr;
+ } else {
+ error("ImuseDigiSndMgr::prepareSound(): Unknown sound format");
+ }
+}
+
+int ImuseDigiSndMgr::allocSlot() {
+ Common::StackLock lock(_mutex);
+ for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
+ if (!_sounds[l].inUse) {
+ _sounds[l].inUse = true;
+ return l;
+ }
+ }
+
+ return -1;
+}
+
+bool ImuseDigiSndMgr::openMusicBundle(int slot) {
+ Common::StackLock lock(_mutex);
+ bool result = false;
+
+ _sounds[slot]._bundle = new BundleMgr();
+ if (_scumm->_gameId == GID_CMI) {
+ if (_scumm->_features & GF_DEMO) {
+ result = _sounds[slot]._bundle->openFile("music.bun", _scumm->getGameDataPath());
+ } else {
+ char musicfile[20];
+ sprintf(musicfile, "musdisk%d.bun", _scumm->VAR(_scumm->VAR_CURRENTDISK));
+ if (_disk != _scumm->VAR(_scumm->VAR_CURRENTDISK))
+ _sounds[slot]._bundle->closeFile();
+
+ result = _sounds[slot]._bundle->openFile(musicfile, _scumm->getGameDataPath());
+
+ if (result == false)
+ result = _sounds[slot]._bundle->openFile("music.bun", _scumm->getGameDataPath());
+ _disk = (byte)_scumm->VAR(_scumm->VAR_CURRENTDISK);
+ }
+ } else if (_scumm->_gameId == GID_DIG)
+ result = _sounds[slot]._bundle->openFile("digmusic.bun", _scumm->getGameDataPath());
+ else
+ error("ImuseDigiSndMgr::openMusicBundle() Don't know which bundle file to load");
+
+ return result;
+}
+
+bool ImuseDigiSndMgr::openVoiceBundle(int slot) {
+ Common::StackLock lock(_mutex);
+ bool result = false;
+
+ _sounds[slot]._bundle = new BundleMgr();
+ if (_scumm->_gameId == GID_CMI) {
+ if (_scumm->_features & GF_DEMO) {
+ result = _sounds[slot]._bundle->openFile("voice.bun", _scumm->getGameDataPath());
+ } else {
+ char voxfile[20];
+ sprintf(voxfile, "voxdisk%d.bun", _scumm->VAR(_scumm->VAR_CURRENTDISK));
+ if (_disk != _scumm->VAR(_scumm->VAR_CURRENTDISK))
+ _sounds[slot]._bundle->closeFile();
+
+ result = _sounds[slot]._bundle->openFile(voxfile, _scumm->getGameDataPath());
+
+ if (result == false)
+ result = _sounds[slot]._bundle->openFile("voice.bun", _scumm->getGameDataPath());
+ _disk = (byte)_scumm->VAR(_scumm->VAR_CURRENTDISK);
+ }
+ } else if (_scumm->_gameId == GID_DIG)
+ result = _sounds[slot]._bundle->openFile("digvoice.bun", _scumm->getGameDataPath());
+ else
+ error("ImuseDigiSndMgr::openVoiceBundle() Don't know which bundle file to load");
+
+ return result;
+}
+
+void *ImuseDigiSndMgr::openSound(int32 soundId, char *soundName, int soundType, int soundGroup) {
+ assert(soundId >= 0);
+ assert(soundType);
+ Common::StackLock lock(_mutex);
+ ImuseDigiSndMgr::lock();
+
+ int slot = allocSlot();
+ if (slot == -1) {
+ error("ImuseDigiSndMgr::openSound() can't alloc free sound slot");
+ }
+
+ bool result = false;
+ byte *ptr = NULL;
+
+ if (soundName == NULL) {
+ if ((soundType == IMUSE_RESOURCE)) {
+ ptr = _scumm->getResourceAddress(rtSound, soundId);
+ if (ptr == NULL) {
+ closeSound(&_sounds[slot]);
+ unlock();
+ return NULL;
+ }
+ _sounds[slot].resPtr = ptr;
+ result = true;
+ } else if (soundType == IMUSE_BUNDLE) {
+ if (soundGroup == IMUSE_VOICE)
+ result = openVoiceBundle(slot);
+ else if (soundGroup == IMUSE_MUSIC)
+ result = openMusicBundle(slot);
+ else
+ error("ImuseDigiSndMgr::openSound() Don't know how load sound: %d", soundId);
+ _sounds[slot]._bundle->decompressSampleByIndex(soundId, 0, 0x2000, &ptr, 0);
+ } else {
+ error("ImuseDigiSndMgr::openSound() Don't know how load sound: %d", soundId);
+ }
+ } else if (soundName != NULL) {
+ if (soundType == IMUSE_BUNDLE) {
+ if (soundGroup == IMUSE_VOICE)
+ result = openVoiceBundle(slot);
+ else if (soundGroup == IMUSE_MUSIC)
+ result = openMusicBundle(slot);
+ else
+ error("ImuseDigiSndMgr::openSound() Don't know how load sound: %d", soundId);
+ _sounds[slot]._bundle->decompressSampleByName(soundName, 0, 0x2000, &ptr);
+ } else {
+ error("ImuseDigiSndMgr::openSound() Don't know how load sound: %s", soundName);
+ }
+ }
+
+ if (result) {
+ if (ptr == NULL) {
+ closeSound(&_sounds[slot]);
+ unlock();
+ return NULL;
+ }
+ prepareSound(ptr, slot);
+ void *soundHandle = &_sounds[slot];
+ unlock();
+ return soundHandle;
+ }
+
+ unlock();
+ return NULL;
+}
+
+void ImuseDigiSndMgr::closeSound(void *soundHandle) {
+ assert(soundHandle && checkForProperHandle(soundHandle));
+ Common::StackLock lock(_mutex);
+
+ for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
+ if (&_sounds[l] == soundHandle) {
+ if (_sounds[l].freeResPtr)
+ free(_sounds[l].resPtr);
+ if (_sounds[l]._bundle)
+ delete _sounds[l]._bundle;
+ memset(&_sounds[l], 0, sizeof(soundStruct));
+ }
+ }
+}
+
+bool ImuseDigiSndMgr::checkForProperHandle(void *soundHandle) {
+ Common::StackLock lock(_mutex);
+ for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
+ if (soundHandle == &_sounds[l])
+ return true;
+ }
+ return false;
+}
+
+int ImuseDigiSndMgr::getFreq(void *soundHandle) {
+ Common::StackLock lock(_mutex);
+ ImuseDigiSndMgr::lock();
+ assert(soundHandle && checkForProperHandle(soundHandle));
+ int result = ((soundStruct *)soundHandle)->freq;
+ unlock();
+ return result;
+}
+
+int ImuseDigiSndMgr::getBits(void *soundHandle) {
+ Common::StackLock lock(_mutex);
+ ImuseDigiSndMgr::lock();
+ assert(soundHandle && checkForProperHandle(soundHandle));
+ int result = ((soundStruct *)soundHandle)->bits;
+ unlock();
+ return result;
+}
+
+int ImuseDigiSndMgr::getChannels(void *soundHandle) {
+ Common::StackLock lock(_mutex);
+ ImuseDigiSndMgr::lock();
+ assert(soundHandle && checkForProperHandle(soundHandle));
+ int result = ((soundStruct *)soundHandle)->channels;
+ unlock();
+ return result;
+}
+
+bool ImuseDigiSndMgr::isEndOfRegion(void *soundHandle, int region) {
+ Common::StackLock lock(_mutex);
+ ImuseDigiSndMgr::lock();
+ assert(soundHandle && checkForProperHandle(soundHandle));
+ assert(region >= 0 && region < ((soundStruct *)soundHandle)->numRegions);
+ bool result = ((soundStruct *)soundHandle)->endFlag;
+ unlock();
+ return result;
+}
+
+int ImuseDigiSndMgr::getNumRegions(void *soundHandle) {
+ Common::StackLock lock(_mutex);
+ ImuseDigiSndMgr::lock();
+ assert(soundHandle && checkForProperHandle(soundHandle));
+ int result = ((soundStruct *)soundHandle)->numRegions;
+ unlock();
+ return result;
+}
+
+int ImuseDigiSndMgr::getNumJumps(void *soundHandle) {
+ Common::StackLock lock(_mutex);
+ ImuseDigiSndMgr::lock();
+ assert(soundHandle && checkForProperHandle(soundHandle));
+ int result = ((soundStruct *)soundHandle)->numJumps;
+ unlock();
+ return result;
+}
+
+int ImuseDigiSndMgr::getNumMarkers(void *soundHandle) {
+ Common::StackLock lock(_mutex);
+ ImuseDigiSndMgr::lock();
+ assert(soundHandle && checkForProperHandle(soundHandle));
+ int result = ((soundStruct *)soundHandle)->numMarkers;
+ unlock();
+ return result;
+}
+
+int ImuseDigiSndMgr::getJumpIdByRegion(void *soundHandle, int number) {
+ Common::StackLock lock(_mutex);
+ ImuseDigiSndMgr::lock();
+ assert(soundHandle && checkForProperHandle(soundHandle));
+ assert(number >= 0 && number < ((soundStruct *)soundHandle)->numRegions);
+ for (int l = 0; l < ((soundStruct *)soundHandle)->numJumps; l++) {
+ if (((soundStruct *)soundHandle)->jump[number].offset == ((soundStruct *)soundHandle)->region[l].offset)
+ unlock();
+ return l;
+ }
+
+ unlock();
+ return -1;
+}
+
+int ImuseDigiSndMgr::getJumpDestRegionId(void *soundHandle, int number) {
+ Common::StackLock lock(_mutex);
+ ImuseDigiSndMgr::lock();
+ assert(soundHandle && checkForProperHandle(soundHandle));
+ assert(number >= 0 && number < ((soundStruct *)soundHandle)->numJumps);
+ for (int l = 0; l < ((soundStruct *)soundHandle)->numRegions; l++) {
+ if (((soundStruct *)soundHandle)->jump[number].dest == ((soundStruct *)soundHandle)->region[l].offset) {
+ unlock();
+ return l;
+ }
+ }
+
+ unlock();
+ return -1;
+}
+
+int ImuseDigiSndMgr::getJumpHookId(void *soundHandle, int number) {
+ Common::StackLock lock(_mutex);
+ ImuseDigiSndMgr::lock();
+ assert(soundHandle && checkForProperHandle(soundHandle));
+ assert(number >= 0 && number < ((soundStruct *)soundHandle)->numJumps);
+ int result = ((soundStruct *)soundHandle)->jump[number].hookId;
+ unlock();
+ return result;
+}
+
+int ImuseDigiSndMgr::getJumpFade(void *soundHandle, int number) {
+ Common::StackLock lock(_mutex);
+ ImuseDigiSndMgr::lock();
+ assert(soundHandle && checkForProperHandle(soundHandle));
+ assert(number >= 0 && number < ((soundStruct *)soundHandle)->numJumps);
+ unlock();
+ return ((soundStruct *)soundHandle)->jump[number].fadeDelay;
+}
+
+char *ImuseDigiSndMgr::getMarker(void *soundHandle, int number) {
+ Common::StackLock lock(_mutex);
+ ImuseDigiSndMgr::lock();
+ assert(soundHandle && checkForProperHandle(soundHandle));
+ assert(number >= 0 && number < ((soundStruct *)soundHandle)->numMarkers);
+ char *result = (char *)(((soundStruct *)soundHandle)->marker[number].name);
+ unlock();
+ return result;
+}
+
+int32 ImuseDigiSndMgr::getDataFromRegion(void *soundHandle, int region, byte **buf, int32 offset, int32 size) {
+ Common::StackLock lock(_mutex);
+ ImuseDigiSndMgr::lock();
+ assert(soundHandle && checkForProperHandle(soundHandle));
+ assert(buf && offset >= 0 && size >= 0);
+ assert(region >= 0 && region < ((soundStruct *)soundHandle)->numRegions);
+
+ int32 region_offset = ((soundStruct *)soundHandle)->region[region].offset;
+ int32 region_length = ((soundStruct *)soundHandle)->region[region].length;
+ int32 offset_data = ((soundStruct *)soundHandle)->offsetData;
+ int32 start = region_offset - offset_data;
+
+ if (offset + size + offset_data > region_length) {
+ size = region_length - offset;
+ ((soundStruct *)soundHandle)->endFlag = true;
+ } else {
+ ((soundStruct *)soundHandle)->endFlag = false;
+ }
+
+ int header_size = ((soundStruct *)soundHandle)->offsetData;
+
+ if (((soundStruct *)soundHandle)->_bundle) {
+// *buf = (byte *)malloc(size);
+// memset(*buf, 0, size);
+ size = ((soundStruct *)soundHandle)->_bundle->decompressSampleByCurIndex(start + offset, size, buf, header_size);
+ } else if (((soundStruct *)soundHandle)->resPtr) {
+ byte *ptr = ((soundStruct *)soundHandle)->resPtr;
+ *buf = (byte *)malloc(size);
+// warning("%d, %d, %d", start + header_size + offset, region_offset + region_length, size);
+ memcpy(*buf, ptr + start + offset + header_size, size);
+ }
+
+ unlock();
+ return size;
+}
+
+} // End of namespace Scumm
diff --git a/scumm/imuse_digi/dimuse_sndmgr.h b/scumm/imuse_digi/dimuse_sndmgr.h
new file mode 100644
index 0000000000..9ac8cf7f32
--- /dev/null
+++ b/scumm/imuse_digi/dimuse_sndmgr.h
@@ -0,0 +1,126 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001-2004 The ScummVM project
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#ifndef IMUSE_DIGI_SNDMGR_H
+#define IMUSE_DIGI_SNDMGR_H
+
+#include "stdafx.h"
+#include "common/scummsys.h"
+#include "common/system.h"
+
+namespace Scumm {
+
+class ScummEngine;
+class BundleMgr;
+
+class ImuseDigiSndMgr {
+public:
+
+#define MAX_IMUSE_SOUNDS 20
+#define MAX_IMUSE_JUMPS 50
+#define MAX_IMUSE_REGIONS 50
+#define MAX_IMUSE_MARKERS 50
+
+#define IMUSE_RESOURCE 1
+#define IMUSE_BUNDLE 2
+#define IMUSE_VOICE 1
+#define IMUSE_SFX 2
+#define IMUSE_MUSIC 3
+
+private:
+ struct _region {
+ int32 offset; // offset of region
+ int32 length; // lenght of region
+ };
+
+ struct _jump {
+ int32 offset; // jump offset position
+ int32 dest; // jump to dest position
+ int hookId; // id of hook
+ int fadeDelay; // fade delay in ms
+ };
+
+ struct _marker {
+ char name[256]; // name of marker
+ };
+
+ struct soundStruct {
+ int freq; // frequency
+ int channels; // stereo or mono
+ int bits; // 8, 12, 16
+ int numJumps; // number of Jumps
+ int numRegions; // number of Regions
+ int numMarkers; // number of Markers
+ int32 offsetStop; // end offset in source data
+ bool endFlag;
+ bool inUse;
+ byte *allData;
+ int32 offsetData;
+ byte *resPtr;
+ bool freeResPtr;
+ BundleMgr *_bundle;
+ _region region[MAX_IMUSE_REGIONS];
+ _marker marker[MAX_IMUSE_MARKERS];
+ _jump jump[MAX_IMUSE_JUMPS];
+ } _sounds[MAX_IMUSE_SOUNDS];
+
+ bool checkForProperHandle(void *soundHandle);
+ int allocSlot();
+ void prepareSound(byte *ptr, int slot);
+
+ ScummEngine *_scumm;
+ OSystem::MutexRef _mutex;
+ byte _disk;
+ bool _accessFree;
+
+ void waitForFreeAccess();
+ void lock();
+ void unlock();
+
+ bool openMusicBundle(int slot);
+ bool openVoiceBundle(int slot);
+
+public:
+
+ ImuseDigiSndMgr(ScummEngine *scumm);
+ ~ImuseDigiSndMgr();
+
+ void *openSound(int32 soundId, char *soundName, int soundType, int soundGroup);
+ void closeSound(void *soundHandle);
+
+ int getFreq(void *soundHandle);
+ int getBits(void *soundHandle);
+ int getChannels(void *soundHandle);
+ bool isEndOfRegion(void *soundHandle, int region);
+ int getNumRegions(void *soundHandle);
+ int getNumJumps(void *soundHandle);
+ int getNumMarkers(void *soundHandle);
+ int getJumpIdByRegion(void *soundHandle, int number);
+ int getJumpDestRegionId(void *soundHandle, int number);
+ int getJumpHookId(void *soundHandle, int number);
+ int getJumpFade(void *soundHandle, int number);
+ char *getMarker(void *soundHandle, int number);
+
+ int32 getDataFromRegion(void *soundHandle, int region, byte **buf, int32 offset, int32 size);
+};
+
+} // End of namespace Scumm
+
+#endif
diff --git a/scumm/imuse_digi.cpp b/scumm/imuse_digi/dimuse_tables.cpp
index 6ca2fc1e15..d9f5fa9301 100644
--- a/scumm/imuse_digi.cpp
+++ b/scumm/imuse_digi/dimuse_tables.cpp
@@ -19,50 +19,11 @@
*/
#include "stdafx.h"
-#include "common/timer.h"
-#include "scumm/actor.h"
-#include "scumm/bundle.h"
-#include "scumm/imuse_digi.h"
-#include "scumm/scumm.h"
-#include "scumm/sound.h"
-
-#include "sound/audiostream.h"
-#include "sound/mixer.h"
-#include "sound/voc.h"
+#include "scumm/imuse_digi/dimuse.h"
namespace Scumm {
-struct imuse_music_table {
- int room;
- int id;
- int unk1;
- int unk2;
- int unk3;
- int unk4;
- char name[30];
- char title[30];
- char filename[13];
-};
-
-struct imuse_music_map {
- int room;
- int table_index;
- int unk1;
- int unk2;
- int unk3;
- int unk4;
-};
-
-#ifdef __PALM_OS__
-// these games are currently not supported under PalmOS so we can save this space
-// to prevent full data segement
-static const imuse_music_map *_digStateMusicMap;
-static const imuse_music_table *_digStateMusicTable;
-static const imuse_music_table *_comiStateMusicTable;
-static const imuse_music_table *_comiSeqMusicTable;
-static const imuse_music_table *_digSeqMusicTable;
-#else
-static const imuse_music_map _digStateMusicMap[] = {
+imuse_music_map _digStateMusicMap[] = {
{0, 0, 0, 0, 0, 0 },
{1, 0, 0, 0, 0, 0 },
{2, 2, 0, 0, 0, 0 },
@@ -180,7 +141,7 @@ static const imuse_music_map _digStateMusicMap[] = {
{-1, 1, 0, 0, 0, 0 }
};
-static const imuse_music_table _digStateMusicTable[] = {
+const imuse_music_table _digStateMusicTable[] = {
{0, 1000, 0, 0, 0, 0, "STATE_NULL", "", ""},
{1, 1001, 0, 0, 0, 0, "stateNoChange", "", ""},
{2, 1100, 0, 3, 2, 0, "stateAstShip", "Asteroid (amb-ship)", "ASTERO~1.IMU"},
@@ -248,7 +209,7 @@ static const imuse_music_table _digStateMusicTable[] = {
{-1, -1, 0, 0, 0, 0, "", "", ""}
};
-static const imuse_music_table _digSeqMusicTable[] = {
+const imuse_music_table _digSeqMusicTable[] = {
{0, 2000, 0, 0, 0, 0, "SEQ_NULL", "", "" },
{0, 2005, 0, 0, 0, 0, "seqLogo", "", "" },
{0, 2010, 0, 0, 0, 0, "seqIntro", "", "" },
@@ -319,7 +280,7 @@ static const imuse_music_table _digSeqMusicTable[] = {
{-1, -1, 0, 0, 0, 0, "", "", "" }
};
-static const imuse_music_table _comiStateMusicTable[] = {
+const imuse_music_table _comiStateMusicTable[] = {
{0, 1000, 0, 0, 0, 0, "STATE_NULL", "", ""},
{0, 1001, 0, 0, 0, 0, "stateNoChange", "", ""},
{0, 1098, 0, 3, 0, 0, "stateCredits1", "1098-Credits1", "1098-C~1.IMX"},
@@ -416,7 +377,7 @@ static const imuse_music_table _comiStateMusicTable[] = {
{-1, -1, 0, 0, 0, 0, "", "", ""}
};
-static const imuse_music_table _comiSeqMusicTable[] = {
+const imuse_music_table _comiSeqMusicTable[] = {
{0, 2000, 0, 0, 0, 0, "SEQ_NULL", "", ""},
{0, 2100, 0, 0, 0, 0, "seqINTRO", "", ""},
{0, 2105, 0, 3, 0, 0, "seqInterlude1", "2105-Interlude1", "2105-I~1.IMX"},
@@ -509,23 +470,7 @@ static const imuse_music_table _comiSeqMusicTable[] = {
{-1, -1, 0, 0, 0, 0, "", "", ""}
};
-#endif
-
-struct imuse_ft_music_table {
- int index;
- char audioname[15];
- int unk1;
- int volume;
- char name[30];
-};
-
-#ifdef __PALM_OS__
-// these games are currently not supported under PalmOS so we can save this space
-// to prevent full data segement
-static const imuse_ft_music_table *_ftStateMusicTable;
-static const imuse_ft_music_table *_ftSeqMusicTable;
-#else
-static const imuse_ft_music_table _ftStateMusicTable[] = {
+const imuse_ft_music_table _ftStateMusicTable[] = {
{0, "", 0, 0, "STATE_NULL" },
{1, "", 4, 127, "stateKstandOutside" },
{2, "kinside", 2, 127, "stateKstandInside" },
@@ -578,7 +523,7 @@ static const imuse_ft_music_table _ftStateMusicTable[] = {
{-1, "", 0, 0, "" }
};
-static const imuse_ft_music_table _ftSeqMusicTable[] = {
+const imuse_ft_music_table _ftSeqMusicTable[] = {
{0, "", 2, 127, "SEQ_NULL" },
{1, "opening", 2, 127, "seqLogo" },
{2, "barbeat", 2, 127, "seqOpenFlick" },
@@ -634,817 +579,5 @@ static const imuse_ft_music_table _ftSeqMusicTable[] = {
{52, "bornbad", 2, 127, "seqCredits" },
{-1, "", 0, 0, "" }
};
-#endif
-
-static uint32 decode12BitsSample(byte *src, byte **dst, uint32 size) {
- uint32 loop_size = size / 3;
- uint32 s_size = loop_size * 4;
- byte *ptr = *dst = (byte *)malloc(s_size);
-
- uint32 tmp;
- while (loop_size--) {
- byte v1 = *src++;
- byte v2 = *src++;
- byte v3 = *src++;
- tmp = ((((v2 & 0x0f) << 8) | v1) << 4) - 0x8000;
- WRITE_BE_UINT16(ptr, tmp); ptr += 2;
- tmp = ((((v2 & 0xf0) << 4) | v3) << 4) - 0x8000;
- WRITE_BE_UINT16(ptr, tmp); ptr += 2;
- }
- return s_size;
-}
-
-IMuseDigital::Channel::Channel()
- : idSound(-1), used(false), stream(0) {
-}
-
-void IMuseDigital::timer_handler(void *refCon) {
- IMuseDigital *imuseDigital = (IMuseDigital *)refCon;
- imuseDigital->callback();
-}
-
-IMuseDigital::IMuseDigital(ScummEngine *scumm)
- : _scumm(scumm) {
- _pause = false;
-
- _nameBundleMusic = "";
- _musicBundleBufFinal = NULL;
- _musicBundleBufOutput = NULL;
- _musicDisk = 0;
-
- _bundle = new Bundle();
-
- _scumm->_timer->installTimerProc(timer_handler, 1000000 / 25, this);
-}
-
-IMuseDigital::~IMuseDigital() {
- _scumm->_timer->removeTimerProc(timer_handler);
- stopBundleMusic();
-
- for (int l = 0; l < MAX_DIGITAL_CHANNELS; l++) {
- _scumm->_mixer->stopHandle(_channel[l].handle);
- delete _channel[l].stream;
- _channel[l].stream = 0;
- }
-
- delete _bundle;
-}
-
-void IMuseDigital::callback() {
- int l = 0;
-
- if (_pause || !_scumm)
- return;
-
- for (l = 0; l < MAX_DIGITAL_CHANNELS;l ++) {
- if (_channel[l].used) {
- assert(_channel[l].stream);
-
- if (!_channel[l].handle.isActive() && _channel[l].started) {
- debug(5, "IMuseDigital::callback(): stopped sound: %d", _channel[l].idSound);
- delete _channel[l].stream;
- _channel[l].stream = 0;
- _channel[l].used = false;
- continue;
- }
-
- if (_channel[l].volFadeUsed) {
- if (_channel[l].volFadeStep < 0) {
- if (_channel[l].vol > _channel[l].volFadeDest) {
- _channel[l].vol += _channel[l].volFadeStep;
- if (_channel[l].vol < _channel[l].volFadeDest) {
- _channel[l].vol = _channel[l].volFadeDest;
- _channel[l].volFadeUsed = false;
- }
- if (_channel[l].vol == 0) {
- _scumm->_mixer->stopHandle(_channel[l].handle);
- }
- }
- } else if (_channel[l].volFadeStep > 0) {
- if (_channel[l].vol < _channel[l].volFadeDest) {
- _channel[l].vol += _channel[l].volFadeStep;
- if (_channel[l].vol > _channel[l].volFadeDest) {
- _channel[l].vol = _channel[l].volFadeDest;
- _channel[l].volFadeUsed = false;
- }
- }
- }
- debug(5, "Fade: sound(%d), Vol(%d)", _channel[l].idSound, _channel[l].vol / 1000);
- }
-
- if (_scumm->_mixer->isReady()) {
- int pan = (_channel[l].pan != 64) ? 2 * _channel[l].pan - 127 : 0;
- if (!_channel[l].started) {
- _channel[l].started = true;
- _scumm->_mixer->playInputStream(&_channel[l].handle, _channel[l].stream, true, _channel[l].vol / 1000, _channel[l].pan, -1, false);
- } else {
- _scumm->_mixer->setChannelVolume(_channel[l].handle, _channel[l].vol / 1000);
- _scumm->_mixer->setChannelPan(_channel[l].handle, pan);
- }
- }
- }
- }
-}
-
-void IMuseDigital::startSound(int sound, byte *voiceBundleData, AudioStream *input) {
- debug(5, "IMuseDigital::startSound(%d)", sound);
- int l, r;
-
- for (l = 0; l < MAX_DIGITAL_CHANNELS; l++) {
- if (!_channel[l].used && !_channel[l].handle.isActive()) {
- byte *ptr, *s_ptr;
- if (sound != kTalkSoundID) {
- s_ptr = ptr = _scumm->getResourceAddress(rtSound, sound);
- if (ptr == NULL) {
- warning("IMuseDigital::startSound(%d) NULL resource pointer", sound);
- return;
- }
- } else if (voiceBundleData) {
- s_ptr = ptr = voiceBundleData;
- } else if (input) {
- s_ptr = ptr = 0;
- } else {
- error("IMuseDigital::startSound() unknown condition");
- }
- _channel[l].pan = 64;
- _channel[l].vol = 127 * 1000;
- _channel[l].volFadeDest = 0;
- _channel[l].volFadeStep = 0;
- _channel[l].volFadeDelay = 0;
- _channel[l].volFadeUsed = false;
-
- _channel[l].numJumps = 0;
- _channel[l].numRegions = 0;
- _channel[l].numMarkers = 0;
-
- _channel[l].idSound = sound;
-
- if (input) {
- // Do nothing here, we already have an audio stream
- } else if (READ_UINT32(ptr) == MKID('Crea')) {
- // Create an AudioStream
- input = makeVOCStream(ptr);
- } else if (READ_UINT32(ptr) == MKID('iMUS')) {
- uint32 tag;
- int32 size = 0;
-
- int freq, channels, bits;
- int mixerFlags;
- byte *data;
-
- ptr += 16;
- freq = channels = bits = 0;
- do {
- tag = READ_BE_UINT32(ptr); ptr += 4;
- switch(tag) {
- case MKID_BE('FRMT'):
- ptr += 12;
- bits = READ_BE_UINT32(ptr); ptr += 4;
- freq = READ_BE_UINT32(ptr); ptr += 4;
- channels = READ_BE_UINT32(ptr); ptr += 4;
- break;
- case MKID_BE('TEXT'):
- size = READ_BE_UINT32(ptr); ptr += 4;
- if (_channel[l].numMarkers >= MAX_IMUSE_MARKERS) {
- warning("IMuseDigital::startSound() Not enough space for Marker");
- ptr += size;
- break;
- }
- strcpy(_channel[l].marker[_channel[l].numMarkers].name, (char *)ptr + 4);
- _channel[l].numMarkers++;
- ptr += size;
- break;
- case MKID_BE('REGN'):
- size = READ_BE_UINT32(ptr); ptr += 4;
- if (_channel[l].numRegions >= MAX_IMUSE_REGIONS) {
- warning("IMuseDigital::startSound() Not enough space for Region");
- ptr += 8;
- break;
- }
- _channel[l].region[_channel[l].numRegions].start = READ_BE_UINT32(ptr); ptr += 4;
- _channel[l].region[_channel[l].numRegions].length = READ_BE_UINT32(ptr); ptr += 4;
- _channel[l].numRegions++;
- break;
- case MKID_BE('STOP'):
- ptr += 4;
- _channel[l].offsetStop = READ_BE_UINT32(ptr); ptr += 4;
- break;
- case MKID_BE('JUMP'):
- size = READ_BE_UINT32(ptr); ptr += 4;
- if (_channel[l].numJumps >= MAX_IMUSE_JUMPS) {
- warning("IMuseDigital::startSound() Not enough space for Jump");
- ptr += size;
- break;
- }
- _channel[l].jump[_channel[l].numJumps].start = READ_BE_UINT32(ptr); ptr += 4;
- _channel[l].jump[_channel[l].numJumps].dest = READ_BE_UINT32(ptr); ptr += 4;
- _channel[l].jump[_channel[l].numJumps].hookId = READ_BE_UINT32(ptr); ptr += 4;
- _channel[l].jump[_channel[l].numJumps].fadeDelay = READ_BE_UINT32(ptr); ptr += 4;
- _channel[l].numJumps++;
- break;
- case MKID_BE('SYNC'):
- size = READ_BE_UINT32(ptr); ptr += size + 4;
- break;
- case MKID_BE('DATA'):
- size = READ_BE_UINT32(ptr); ptr += 4;
- break;
- default:
- error("IMuseDigital::startSound(%d) Unknown sfx header '%s'", sound, tag2str(tag));
- }
- } while (tag != MKID_BE('DATA'));
-
- if ((sound == kTalkSoundID) && voiceBundleData) {
- if (_scumm->_actorToPrintStrFor != 0xFF && _scumm->_actorToPrintStrFor != 0) {
- Actor *a = _scumm->derefActor(_scumm->_actorToPrintStrFor, "playBundleSound");
- freq = (freq * a->talkFrequency) / 256;
- _channel[l].pan = a->talkPan;
- }
- }
-
- uint32 header_size = ptr - s_ptr;
-
- _channel[l].offsetStop -= header_size;
- if (bits == 12) {
- _channel[l].offsetStop = (_channel[l].offsetStop / 3) * 4;
- }
- for (r = 0; r < _channel[l].numRegions; r++) {
- _channel[l].region[r].start -= header_size;
- if (bits == 12) {
- _channel[l].region[r].start = (_channel[l].region[r].start / 3) * 4;
- _channel[l].region[r].length = (_channel[l].region[r].length / 3) * 4;
- }
- }
- if (_channel[l].numJumps > 0) {
- for (r = 0; r < _channel[l].numJumps; r++) {
- _channel[l].jump[r].start -= header_size;
- _channel[l].jump[r].dest -= header_size;
- if (bits == 12) {
- _channel[l].jump[r].start = (_channel[l].jump[r].start / 3) * 4;
- _channel[l].jump[r].dest = (_channel[l].jump[r].dest / 3) * 4;
- }
- }
- }
-
- assert(channels == 1 || channels == 2);
-
- if (channels == 2) {
- // FIXME / TODO: Is FLAG_REVERSE_STEREO really needed here?
- // How do we know that it is needed? If we indeed have reasons
- // to believe that it is needed, those should be documented in
- // a comment here. And if the channels are reversed, then we
- // might just swap them right here, instead of using the mixer
- // flag - since we copy the data around anyway, swapping the
- // channels should be little extra work (in fact, none for
- // mono data, which includes the 12 bit compressed format).
-
- mixerFlags = SoundMixer::FLAG_STEREO | SoundMixer::FLAG_REVERSE_STEREO;
- } else {
- mixerFlags = 0;
- }
-
- if (bits == 12) {
- mixerFlags |= SoundMixer::FLAG_16BITS;
- size = decode12BitsSample(ptr, &data, size);
- } else if (bits == 16) {
- mixerFlags |= SoundMixer::FLAG_16BITS;
-
- // FIXME: For some weird reasons, sometimes we get an odd size, even though
- // the data is supposed to be in 16 bit format... that makes no sense...
- size &= ~1;
-
- data = (byte *)malloc(size);
- memcpy(data, ptr, size);
- } else if (bits == 8) {
- mixerFlags |= SoundMixer::FLAG_UNSIGNED;
-
- data = (byte *)malloc(size);
- memcpy(data, ptr, size);
- } else
- error("IMuseDigital::startSound(): Can't handle %d bit samples", bits);
-
- // Create an AudioStream
- input = makeLinearInputStream(freq, mixerFlags | SoundMixer::FLAG_AUTOFREE, data, size, 0, 0);
- } else {
- error("IMuseDigital::startSound(): Unknown sound format");
- }
-
- // Set the audio stream for this new channel
- _channel[l].stream = input;
-
- _channel[l].started = false;
- _channel[l].used = true;
- return;
- }
- }
- warning("IMuseDigital::startSound(): All slots are full");
-}
-
-void IMuseDigital::stopSound(int sound) {
- debug(5, "IMuseDigital::stopSound(%d)", sound);
- for (int l = 0; l < MAX_DIGITAL_CHANNELS; l++) {
- if ((_channel[l].idSound == sound) && _channel[l].used) {
- _scumm->_mixer->stopHandle(_channel[l].handle);
- }
- }
-}
-
-void IMuseDigital::stopAllSounds() {
- debug(5, "IMuseDigital::stopAllSounds");
- for (int l = 0; l < MAX_DIGITAL_CHANNELS; l++) {
- if (_channel[l].used) {
- _scumm->_mixer->stopHandle(_channel[l].handle);
- }
- }
-}
-
-void IMuseDigital::pause(bool p) {
- for (int l = 0; l < MAX_DIGITAL_CHANNELS; l++) {
- if (_channel[l].used) {
- _scumm->_mixer->pauseHandle(_channel[l].handle, p);
- }
- }
- _pause = p;
- pauseBundleMusic(p);
-}
-
-void IMuseDigital::parseScriptCmds(int a, int b, int c, int d, int e, int f, int g, int h) {
- int cmd = a;
- int sample = b;
- int sub_cmd = c;
- int chan = -1;
- int l, r;
-
- if (!cmd)
- return;
-
- switch (cmd) {
- case 10: // ImuseStopAllSounds
- debug(5, "ImuseStopAllSounds()");
- stopAllSounds();
- break;
- case 12: // ImuseSetParam
- switch (sub_cmd) {
- case 0x500: // set priority - could be ignored
- break;
- case 0x600: // set volume
- debug(5, "ImuseSetParam (0x600), sample(%d), volume(%d)", sample, d);
- for (l = 0; l < MAX_DIGITAL_CHANNELS; l++) {
- if ((_channel[l].idSound == sample) && _channel[l].used) {
- _channel[l].vol = d * 1000;
-// if (_channel[l].volFadeUsed)
-// _channel[l].volFadeStep = (_channel[l].volFadeDest - _channel[l].vol) * 60 * 40 / (1000 * _channel[chan].volFadeDelay);
- }
- }
- if (l == -1) {
- debug(5, "ImuseSetParam (0x600), sample(%d) not exist in channels", sample);
- return;
- }
- break;
- case 0x700: // set pan
- debug(5, "ImuseSetParam (0x700), sample(%d), pan(%d)", sample, d);
- for (l = 0; l < MAX_DIGITAL_CHANNELS; l++) {
- if ((_channel[l].idSound == sample) && _channel[l].used) {
- _channel[l].pan = d;
- }
- }
- if (l == -1) {
- debug(5, "ImuseSetParam (0x700), sample(%d) not exist in channels", sample);
- return;
- }
- break;
- default:
- warning("IMuseDigital::doCommand SetParam DEFAULT command %d", sub_cmd);
- break;
- }
- break;
- case 14: // ImuseFadeParam
- switch (sub_cmd) {
- case 0x600: // set new volume with fading
- debug(5, "ImuseFadeParam - fade sample(%d), to volume(%d) with 60hz ticks(%d)", sample, d, e);
- if ((_scumm->_gameId == GID_DIG) && (_scumm->_features & GF_DEMO)) {
- stopSound(sample);
- return;
- }
- for (l = 0; l < MAX_DIGITAL_CHANNELS; l++) {
- if ((_channel[l].idSound == sample) && _channel[l].used) {
- _channel[l].volFadeDelay = e;
- _channel[l].volFadeDest = d * 1000;
- _channel[l].volFadeStep = (_channel[l].volFadeDest - _channel[l].vol) * 60 * 40 / (1000 * e);
- _channel[l].volFadeUsed = true;
- debug(5, "ImuseFadeParam: vol %d, volDest %d, step %d", _channel[l].vol, d * 1000, _channel[l].volFadeStep);
- }
- }
- if (chan == -1) {
- debug(5, "ImuseFadeParam (0x600), sample %d not exist in channels", sample);
- return;
- }
- break;
- default:
- warning("IMuseDigital::doCommand FadeParam DEFAULT sub command %d", sub_cmd);
- break;
- }
- break;
- case 0x1000: // ImuseSetState
- debug(5, "ImuseSetState (%d)", b);
- if ((_scumm->_gameId == GID_DIG) && (_scumm->_features & GF_DEMO)) {
- if (b == 1)
- startSound(1);
- else {
- if (getSoundStatus(2) == 0)
- startSound(2);
- }
- } else if (_scumm->_gameId == GID_DIG) {
- if (b == 1000) { // STATE_NULL
- stopBundleMusic();
- return;
- }
- for (l = 0; _digStateMusicMap[l].room != -1; l++) {
- if (_digStateMusicMap[l].room == b) {
- int music = _digStateMusicMap[l].table_index;
- debug(5, "Play imuse music: %s, %s, %s", _digStateMusicTable[music].name, _digStateMusicTable[music].title, _digStateMusicTable[music].filename);
- if ((_digStateMusicTable[music].filename[0] != 0) &&
- (strcmp(_digStateMusicTable[_digStateMusicTable[music].unk3].filename, _nameBundleMusic) != 0) ) {
- playBundleMusic(_digStateMusicTable[music].filename);
- }
- break;
- }
- }
- } else if ((_scumm->_gameId == GID_CMI) && (_scumm->_features & GF_DEMO)) {
- if (b == 2) {
- playBundleMusic("in1.imx");
- } else if (b == 4) {
- playBundleMusic("in2.imx");
- } else if (b == 8) {
- playBundleMusic("out1.imx");
- } else if (b == 9) {
- playBundleMusic("out2.imx");
- } else if (b == 16) {
- playBundleMusic("gun.imx");
- } else {
- warning("imuse digital: set state unknown for cmi demo: %d, room: %d", b, this->_scumm->_currentRoom);
- }
- } else if (_scumm->_gameId == GID_CMI) {
- if (b == 1000) { // STATE_NULL
- stopBundleMusic();
- return;
- }
- for (l = 0; _comiStateMusicTable[l].id != -1; l++) {
- if ((_comiStateMusicTable[l].id == b)) {
- debug(5, "Play imuse music: %s, %s, %s", _comiStateMusicTable[l].name, _comiStateMusicTable[l].title, _comiStateMusicTable[l].filename);
- if (_comiStateMusicTable[l].filename[0] != 0) {
- playBundleMusic(_comiStateMusicTable[l].filename);
- }
- break;
- }
- }
- } else if (_scumm->_gameId == GID_FT) {
- for (l = 0;; l++) {
- if (_ftStateMusicTable[l].index == -1) {
- return;
- }
- if (_ftStateMusicTable[l].index == b) {
- debug(5, "Play imuse music: %s, %s", _ftStateMusicTable[l].name, _ftStateMusicTable[l].audioname);
- if (_ftStateMusicTable[l].audioname[0] != 0) {
- for (r = 0; r < _scumm->_numAudioNames; r++) {
- if (strcmp(_ftStateMusicTable[l].audioname, &_scumm->_audioNames[r * 9]) == 0) {
- startSound(r);
- parseScriptCmds(12, r, 1536, _ftStateMusicTable[l].volume, 0, 0, 0, 0);
- }
- }
- }
- }
- }
- }
- break;
- case 0x1001: // ImuseSetSequence
- debug(5, "ImuseSetSequence (%d)", b);
- if (_scumm->_gameId == GID_DIG) {
- for (l = 0; _digSeqMusicTable[l].room != -1; l++) {
- if (_digSeqMusicTable[l].room == b) {
- debug(5, "Play imuse music: %s, %s, %s", _digSeqMusicTable[l].name, _digSeqMusicTable[l].title, _digSeqMusicTable[l].filename);
- if (_digSeqMusicTable[l].filename[0] != 0) {
- playBundleMusic(_digSeqMusicTable[l].filename);
- }
- break;
- }
- }
- } else if (_scumm->_gameId == GID_CMI) {
- for (l = 0; _comiSeqMusicTable[l].id != -1; l++) {
- if (_comiSeqMusicTable[l].id == b) {
- debug(5, "Play imuse music: %s, %s, %s", _comiSeqMusicTable[l].name, _comiSeqMusicTable[l].title, _comiSeqMusicTable[l].filename);
- if (_comiSeqMusicTable[l].filename[0] != 0) {
- playBundleMusic(_comiSeqMusicTable[l].filename);
- }
- break;
- }
- }
- } else if (_scumm->_gameId == GID_FT) {
- for (l = 0; _ftSeqMusicTable[l].index != -1; l++) {
- if (_ftSeqMusicTable[l].index == b) {
- debug(5, "Play imuse music: %s, %s", _ftSeqMusicTable[l].name, _ftSeqMusicTable[l].audioname);
- if (_ftSeqMusicTable[l].audioname[0] != 0) {
- for (r = 0; r < _scumm->_numAudioNames; r++) {
- if (strcmp(_ftSeqMusicTable[l].audioname, &_scumm->_audioNames[r * 9]) == 0) {
-// startSound(r);
-// parseScriptCmds(12, r, 1536, _ftSeqMusicTable[l].volume, 0, 0, 0, 0);
- }
- }
- }
- }
- }
- }
- break;
- case 0x1002: // ImuseSetCuePoint
- debug(5, "ImuseSetCuePoint (%d)", b);
- break;
- case 0x1003: // ImuseSetAttribute
- debug(5, "ImuseSetAttribute (%d, %d)", b, c);
- break;
- case 0x2000: // ImuseSetMasterSFXVolume
- debug(5, "ImuseSetMasterSFXVolume (%d)", b);
- break;
- case 0x2001: // ImuseSetMasterVoiceVolume
- debug(5, "ImuseSetMasterVoiceVolume (%d)", b);
- break;
- case 0x2002: // ImuseSetMasterMusicVolume
- debug(5, "ImuseSetMasterMusicVolume (%d)", b);
- break;
- default:
- warning("IMuseDigital::doCommand DEFAULT command %d", cmd);
- }
-}
-
-int IMuseDigital::getSoundStatus(int sound) const {
- debug(5, "IMuseDigital::getSoundStatus(%d)", sound);
- for (int l = 0; l < MAX_DIGITAL_CHANNELS; l++) {
- if ((_channel[l].idSound == sound) && _channel[l].used) {
- return 1;
- }
- }
-
- return 0;
-}
-
-void IMuseDigital::music_handler(void *refCon) {
- ((IMuseDigital *)refCon)->bundleMusicHandler();
-}
-
-#define BUNDLE_MUSIC_ITER_PER_SEC 10
-
-void IMuseDigital::playBundleMusic(const char *song) {
- if (!_scumm->_mixer->isReady()) {
- return;
- }
-
- if (_nameBundleMusic[0] == 0) {
- if (_scumm->_gameId == GID_CMI) {
- _outputMixerSize = (22050 * 2 * 2);
-
- char bunfile[20];
- if (_scumm->_features & GF_DEMO) {
- if (_bundle->openMusicFile("music.bun", _scumm->getGameDataPath()) == false) {
- _outputMixerSize = 0;
- return;
- }
- } else {
-
- sprintf(bunfile, "musdisk%d.bun", _scumm->VAR(_scumm->VAR_CURRENTDISK));
- if (_musicDisk != _scumm->VAR(_scumm->VAR_CURRENTDISK))
- _bundle->closeMusicFile();
-
- if (_bundle->openMusicFile(bunfile, _scumm->getGameDataPath()) == false) {
- if (_bundle->openMusicFile("music.bun", _scumm->getGameDataPath()) == false) {
- _outputMixerSize = 0;
- return;
- }
- }
-
- _musicDisk = (byte)_scumm->VAR(_scumm->VAR_CURRENTDISK);
- }
- } else {
- _outputMixerSize = ((22050 * 2 * 2) / 4) * 3;
-
- if (_bundle->openMusicFile("digmusic.bun", _scumm->getGameDataPath()) == false)
- return;
- }
- _musicBundleBufFinal = (byte *)malloc(_outputMixerSize);
- _musicBundleBufOutput = (byte *)malloc(((_outputMixerSize / 0x2000) + 1) * _outputMixerSize);
- _currentSampleBundleMusic = 0;
- _offsetSampleBundleMusic = 0;
- _offsetBufBundleMusic = 0;
- _bundleMusicPosition = 0;
- _bundleSongPosInMs = 0;
- _pauseBundleMusic = false;
- _musicBundleToBeChanged = false;
- _numberSamplesBundleMusic = _bundle->getNumberOfMusicSamplesByName(song);
- _nameBundleMusic = song;
- _outputMixerSize /= BUNDLE_MUSIC_ITER_PER_SEC;
- _scumm->_timer->installTimerProc(&music_handler, 1000000 / BUNDLE_MUSIC_ITER_PER_SEC, this);
- } else if (strcmp(_nameBundleMusic, song) != 0) {
- _newNameBundleMusic = song;
- _musicBundleToBeChanged = true;
- }
-}
-
-void IMuseDigital::pauseBundleMusic(bool state) {
- _pauseBundleMusic = state;
-}
-
-void IMuseDigital::stopBundleMusic() {
- // First stop the music timer
- _scumm->_timer->removeTimerProc(&music_handler);
- _nameBundleMusic = "";
- _scumm->_mixer->stopHandle(_bundleMusicTrack);
- if (_musicBundleBufFinal) {
- free(_musicBundleBufFinal);
- _musicBundleBufFinal = NULL;
- }
- if (_musicBundleBufOutput) {
- free(_musicBundleBufOutput);
- _musicBundleBufOutput = NULL;
- }
-}
-
-void IMuseDigital::bundleMusicHandler() {
- byte *ptr;
- int32 l, num = _numberSamplesBundleMusic, length, k;
- int32 rate = 22050;
- int32 tag, size = -1, header_size = 0;
-
- if (_pauseBundleMusic)
- return;
-
- if (_musicBundleToBeChanged) {
- _nameBundleMusic = _newNameBundleMusic;
- _numberSamplesBundleMusic = _bundle->getNumberOfMusicSamplesByName(_nameBundleMusic);
- _currentSampleBundleMusic = 0;
- _offsetSampleBundleMusic = 0;
- _offsetBufBundleMusic = 0;
- _musicBundleToBeChanged = false;
- _bundleMusicPosition = 0;
- _bundleSongPosInMs = 0;
- }
-
- ptr = _musicBundleBufOutput;
-
- for (k = 0, l = _currentSampleBundleMusic; l < num && (_offsetSampleBundleMusic < _outputMixerSize + header_size); k++) {
- length = _bundle->decompressMusicSampleByName(_nameBundleMusic, l, (_musicBundleBufOutput + ((k * 0x2000) + _offsetBufBundleMusic)));
- _offsetSampleBundleMusic += length;
-
- if (l == 0) {
- tag = READ_BE_UINT32(ptr); ptr += 4;
- if (tag != MKID_BE('iMUS')) {
- error("Decompressing bundle song failed (unknown tag '%s')", tag2str(tag));
- }
-
- ptr += 12;
- while (tag != MKID_BE('DATA')) {
- tag = READ_BE_UINT32(ptr); ptr += 4;
- switch(tag) {
- case MKID_BE('FRMT'):
- ptr += 12;
- _bundleMusicSampleBits = READ_BE_UINT32(ptr); ptr += 4;
- rate = READ_BE_UINT32(ptr); ptr += 4;
- _bundleSampleChannels = READ_BE_UINT32(ptr); ptr += 4;
- break;
- case MKID_BE('TEXT'):
- case MKID_BE('REGN'):
- case MKID_BE('STOP'):
- case MKID_BE('JUMP'):
- case MKID_BE('SYNC'):
- size = READ_BE_UINT32(ptr); ptr += size + 4;
- break;
- case MKID_BE('DATA'):
- size = READ_BE_UINT32(ptr); ptr += 4;
- break;
-
- default:
- error("Unknown sound header '%s'", tag2str(tag));
- }
- }
- if (size < 0) {
- error("Decompressing sound failed (missing size field)");
- }
- header_size = (ptr - _musicBundleBufOutput);
- }
-
- l++;
- _currentSampleBundleMusic = l;
-
- }
-
- if (_offsetSampleBundleMusic >= _outputMixerSize + header_size) {
- memcpy(_musicBundleBufFinal, (_musicBundleBufOutput + header_size), _outputMixerSize);
- _offsetBufBundleMusic = _offsetSampleBundleMusic - _outputMixerSize - header_size;
- memcpy(_musicBundleBufOutput, (_musicBundleBufOutput + (_outputMixerSize + header_size)), _offsetBufBundleMusic);
- _offsetSampleBundleMusic = _offsetBufBundleMusic;
- }
-
- if (_currentSampleBundleMusic == num) {
- _currentSampleBundleMusic = 0;
- _offsetSampleBundleMusic = 0;
- _offsetBufBundleMusic = 0;
- _bundleMusicPosition = 0;
- _bundleSongPosInMs = 0;
- }
-
- ptr = _musicBundleBufFinal;
-
- byte *buffer = NULL;
- uint32 final_size;
- if (_bundleMusicSampleBits == 12) {
- final_size = decode12BitsSample(ptr, &buffer, _outputMixerSize);
- } else if (_bundleMusicSampleBits == 16) {
- buffer = (byte *)malloc(_outputMixerSize);
- final_size = _outputMixerSize;
- memcpy(buffer, ptr, _outputMixerSize);
- } else {
- warning("IMuseDigital::bundleMusicHandler TODO: more newStream options...");
- return;
- }
-
- // Compute the position in the song in milliseconds (in brief: _outputMixerSize
- // gives the number of bytes used for one second, so if we compute the value of
- // (_bundleMusicPosition / _outputMixerSize), that is an offset in seconds;
- // multiplying that by 1000 gives milliseconds).
- _bundleSongPosInMs = 1000 * _bundleMusicPosition / (_outputMixerSize * BUNDLE_MUSIC_ITER_PER_SEC);
- _bundleMusicPosition += final_size;
- if (!_bundleMusicTrack.isActive())
- _scumm->_mixer->newStream(&_bundleMusicTrack, rate, SoundMixer::FLAG_16BITS | SoundMixer::FLAG_STEREO, 300000);
- _scumm->_mixer->appendStream(_bundleMusicTrack, buffer, final_size);
- free(buffer);
-}
-
-void IMuseDigital::playBundleSound(const char *sound) {
- byte *ptr = 0;
- bool result;
-
- if (!_scumm->_mixer->isReady())
- return;
-
- if (_scumm->_gameId == GID_CMI) {
- if (_scumm->_features & GF_DEMO) {
- result = _bundle->openVoiceFile("voice.bun", _scumm->getGameDataPath());
- } else {
- char voxfile[20];
- sprintf(voxfile, "voxdisk%d.bun", _scumm->VAR(_scumm->VAR_CURRENTDISK));
- if (_voiceDisk != _scumm->VAR(_scumm->VAR_CURRENTDISK))
- _bundle->closeVoiceFile();
-
- result = _bundle->openVoiceFile(voxfile, _scumm->getGameDataPath());
-
- if (result == false)
- result = _bundle->openVoiceFile("voice.bun", _scumm->getGameDataPath());
- _voiceDisk = (byte)_scumm->VAR(_scumm->VAR_CURRENTDISK);
- }
- } else if (_scumm->_gameId == GID_DIG)
- result = _bundle->openVoiceFile("digvoice.bun", _scumm->getGameDataPath());
- else
- error("Don't know which bundle file to load");
-
- if (!result)
- return;
-
- if (_scumm->_gameId == GID_CMI) {
- char name[20];
- strcpy(name, sound);
- if (!(_scumm->_features & GF_DEMO)) // CMI demo does not have .IMX for voice but does for music...
- strcat(name, ".IMX");
- _bundle->decompressVoiceSampleByName(name, &ptr);
- } else {
- _bundle->decompressVoiceSampleByName(sound, &ptr);
- }
-
- if (ptr) {
- stopSound(kTalkSoundID);
- startSound(kTalkSoundID, ptr, 0);
- free(ptr);
- }
-}
} // End of namespace Scumm
-
-#ifdef __PALM_OS__
-#include "scumm_globals.h"
-
-_GINIT(IMuseDigital)
-_GSETPTR(Scumm::_digStateMusicMap, GBVARS_DIGSTATEMUSICMAP_INDEX, Scumm::imuse_music_map , GBVARS_SCUMM)
-_GSETPTR(Scumm::_digStateMusicTable, GBVARS_DIGSTATEMUSICTABLE_INDEX, Scumm::imuse_music_table , GBVARS_SCUMM)
-_GSETPTR(Scumm::_comiStateMusicTable, GBVARS_COMISTATEMUSICTABLE_INDEX, Scumm::imuse_music_table , GBVARS_SCUMM)
-_GSETPTR(Scumm::_comiSeqMusicTable, GBVARS_COMISEQMUSICTABLE_INDEX, Scumm::imuse_music_table , GBVARS_SCUMM)
-_GSETPTR(Scumm::_digSeqMusicTable, GBVARS_DIGSEQMUSICTABLE_INDEX, Scumm::imuse_music_table , GBVARS_SCUMM)
-_GSETPTR(Scumm::_ftStateMusicTable, GBVARS_FTSTATEMUSICTABLE_INDEX, Scumm::imuse_ft_music_table , GBVARS_SCUMM)
-_GSETPTR(Scumm::_ftSeqMusicTable, GBVARS_FTSEQMUSICTABLE_INDEX, Scumm::imuse_ft_music_table , GBVARS_SCUMM)
-_GEND
-
-_GRELEASE(IMuseDigital)
-_GRELEASEPTR(GBVARS_DIGSTATEMUSICMAP_INDEX , GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_DIGSTATEMUSICTABLE_INDEX , GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_COMISTATEMUSICTABLE_INDEX , GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_COMISEQMUSICTABLE_INDEX , GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_DIGSEQMUSICTABLE_INDEX , GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_FTSTATEMUSICTABLE_INDEX , GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_FTSEQMUSICTABLE_INDEX , GBVARS_SCUMM)
-_GEND
-
-#endif
diff --git a/scumm/resource.cpp b/scumm/resource.cpp
index c715bbec24..1c178807ff 100644
--- a/scumm/resource.cpp
+++ b/scumm/resource.cpp
@@ -23,10 +23,9 @@
#include "stdafx.h"
#include "common/map.h"
#include "common/str.h"
-#include "scumm/bundle.h"
#include "scumm/dialogs.h"
#include "scumm/imuse.h"
-#include "scumm/imuse_digi.h"
+#include "scumm/imuse_digi/dimuse.h"
#include "scumm/object.h"
#include "scumm/resource.h"
#include "scumm/scumm.h"
@@ -228,8 +227,7 @@ void ScummEngine::askForDisk(const char *filename, int disknum) {
if (_version == 8) {
char result;
- _imuseDigital->_bundle->closeVoiceFile();
- _imuseDigital->_bundle->closeMusicFile();
+ _imuseDigital->closeBundleFiles();
#ifdef MACOSX
sprintf(buf, "Cannot find file: '%s'\nPlease insert disc %d.\nHit OK to retry, Cancel to exit", filename, disknum);
diff --git a/scumm/saveload.cpp b/scumm/saveload.cpp
index aa66eac9a4..50162a441c 100644
--- a/scumm/saveload.cpp
+++ b/scumm/saveload.cpp
@@ -26,7 +26,7 @@
#include "scumm/actor.h"
#include "scumm/charset.h"
-#include "scumm/imuse_digi.h"
+#include "scumm/imuse_digi/dimuse.h"
#include "scumm/imuse.h"
#include "scumm/object.h"
#include "scumm/resource.h"
@@ -125,8 +125,6 @@ bool ScummEngine::loadState(int slot, bool compat, SaveFileManager *mgr) {
memcpy(_saveLoadName, hdr.name, sizeof(hdr.name));
_sound->stopAllSounds();
- if (_imuseDigital)
- _imuseDigital->stopBundleMusic();
_sound->stopCD();
_sound->pauseSounds(true);
diff --git a/scumm/script_v6.cpp b/scumm/script_v6.cpp
index df33772509..e9139c881f 100644
--- a/scumm/script_v6.cpp
+++ b/scumm/script_v6.cpp
@@ -28,6 +28,7 @@
#include "scumm/actor.h"
#include "scumm/charset.h"
#include "scumm/imuse.h"
+#include "scumm/imuse_digi/dimuse.h"
#include "scumm/intern.h"
#include "scumm/object.h"
#include "scumm/resource.h"
@@ -936,7 +937,7 @@ void ScummEngine_v6::o6_startSound() {
pop(); // offset which seems to always be zero
if (_features & GF_DIGI_IMUSE)
- _sound->playSound(pop());
+ _imuseDigital->startSfx(pop());
else
_sound->addSoundToQueue(pop());
}
@@ -947,7 +948,7 @@ void ScummEngine_v6::o6_stopSound() {
void ScummEngine_v6::o6_startMusic() {
if (_features & GF_DIGI_IMUSE)
- _sound->playSound(pop());
+ error("o6_startMusic() It shouldn't be called here for imuse digital");
else
_sound->addSoundToQueue(pop());
}
diff --git a/scumm/script_v8.cpp b/scumm/script_v8.cpp
index 7ae55bac74..61fec48cbb 100644
--- a/scumm/script_v8.cpp
+++ b/scumm/script_v8.cpp
@@ -24,7 +24,7 @@
#include "scumm/actor.h"
#include "scumm/akos.h"
#include "scumm/charset.h"
-#include "scumm/imuse_digi.h"
+#include "scumm/imuse_digi/dimuse.h"
#include "scumm/intern.h"
#include "scumm/object.h"
#include "scumm/resource.h"
@@ -1444,14 +1444,9 @@ void ScummEngine_v8::o8_kernelGetFunctions() {
break;
}
case 0xDA: // lipSyncWidth
+ push(_imuseDigital->getCurVoiceLipSyncWidth());
case 0xDB: // lipSyncHeight
- {
- // TODO - get lip sync data for the currently active voice
- // HACK - return random values for now, to make things look half decent
- int val = _rnd.getRandomNumber(255);
-// warning("o8_kernelGetFunctions: lipSync(case 0x%x, len %d, val %d)", args[0], len, val);
- push(val);
- }
+ push(_imuseDigital->getCurVoiceLipSyncHeight());
break;
case 0xDC: // actorTalkAnimation
{
@@ -1482,18 +1477,12 @@ void ScummEngine_v8::o8_kernelGetFunctions() {
}
break;
case 0xE1: // imGetMusicPosition
- warning("o8_kernelGetFunctions: imGetMusicPosition(stub)");
- // FIXME - get this stuff to be properly implemented
- push(_imuseDigital->_bundleSongPosInMs);
+ push(_imuseDigital->getCurMusicPosInMs());
break;
case 0xE2: // musicLipSyncWidth
+ push(_imuseDigital->getCurMusicLipSyncWidth());
case 0xE3: // musicLipSyncHeight
- {
- // TODO - get lip sync data for the currently active music
- int val = _rnd.getRandomNumber(255);
-// warning("o8_kernelGetFunctions: musicLipSync(case 0x%x, len %d, val %d)", args[0], len, val);
- push(val);
- }
+ push(_imuseDigital->getCurMusicLipSyncHeight());
break;
default:
error("o8_kernelGetFunctions: default case 0x%x (len = %d)", args[0], len);
diff --git a/scumm/scummvm.cpp b/scumm/scummvm.cpp
index 554e72e428..a7a057c0d5 100644
--- a/scumm/scummvm.cpp
+++ b/scumm/scummvm.cpp
@@ -40,7 +40,7 @@
#include "scumm/costume.h"
#include "scumm/debugger.h"
#include "scumm/dialogs.h"
-#include "scumm/imuse_digi.h"
+#include "scumm/imuse_digi/dimuse.h"
#include "scumm/imuse.h"
#include "scumm/intern.h"
#include "scumm/object.h"
diff --git a/scumm/smush/insane.cpp b/scumm/smush/insane.cpp
index ee84c79b94..e92b0b2b2a 100644
--- a/scumm/smush/insane.cpp
+++ b/scumm/smush/insane.cpp
@@ -32,7 +32,7 @@
#include "scumm/sound.h"
#include "scumm/resource.h"
#include "scumm/imuse.h"
-#include "scumm/imuse_digi.h"
+#include "scumm/imuse_digi/dimuse.h"
#include "scumm/smush/smush_player.h"
#include "scumm/smush/chunk_type.h"
@@ -5914,30 +5914,16 @@ bool Insane::smlayer_isSoundRunning(int32 sound) {
}
bool Insane::smlayer_startSound1(int32 sound) {
- // FIXME: original startSound parameters:
- // startSound(id, 40, 1);
- // second param is priority in imuse,
- // third param set sound to group volume in imuse
- // (0 - master, 1-sfx, 2-voice, 3 - music,
- // 4 - background music)
- // there are no equivalents in scummvm
if (smlayer_loadSound(sound, 0, 2)) {
- _scumm->_sound->playSound(readArray(_numberArray, sound));
+ _scumm->_imuseDigital->startSfx(readArray(_numberArray, sound));
return true;
} else
return false;
}
bool Insane::smlayer_startSound2(int32 sound) {
- // FIXME: original startSound parameters:
- // startSound(id, 126, 2);
- // second param is priority in imuse,
- // third param set sound to group volume in imuse
- // (0 - master, 1-sfx, 2-voice, 3 - music,
- // 4 - background music)
- // there are no equivalents in scummvm
if (smlayer_loadSound(sound, 0, 2)) {
- _scumm->_sound->playSound(readArray(_numberArray, sound));
+ _scumm->_imuseDigital->startSfx(readArray(_numberArray, sound));
return true;
} else
return false;
diff --git a/scumm/smush/smush_player.cpp b/scumm/smush/smush_player.cpp
index 0d6aa66a7c..d3e6867fdf 100644
--- a/scumm/smush/smush_player.cpp
+++ b/scumm/smush/smush_player.cpp
@@ -29,7 +29,7 @@
#include "common/timer.h"
#include "scumm/bomp.h"
-#include "scumm/imuse_digi.h"
+#include "scumm/imuse_digi/dimuse.h"
#include "scumm/imuse.h"
#include "scumm/scumm.h"
#include "scumm/sound.h"
diff --git a/scumm/sound.cpp b/scumm/sound.cpp
index ade7faf0ba..91f007e684 100644
--- a/scumm/sound.cpp
+++ b/scumm/sound.cpp
@@ -23,7 +23,7 @@
#include "stdafx.h"
#include "scumm/actor.h"
#include "scumm/imuse.h"
-#include "scumm/imuse_digi.h"
+#include "scumm/imuse_digi/dimuse.h"
#include "scumm/scumm.h"
#include "scumm/sound.h"
@@ -126,11 +126,6 @@ void Sound::playSound(int soundID) {
return;
}
- if (_scumm->_features & GF_DIGI_IMUSE) {
- _scumm->_musicEngine->startSound(soundID);
- return;
- }
-
// Support for SFX in Monkey Island 1, Mac version
// This is rather hackish right now, but works OK. SFX are not sounding
// 100% correct, though, not sure right now what is causing this.
@@ -815,7 +810,6 @@ void Sound::startSfxSound(File *file, int file_size, PlayingSoundHandle *handle,
AudioStream *input;
-
if (file_size > 0) {
if (_vorbis_mode) {
#ifdef USE_VORBIS
@@ -831,7 +825,8 @@ void Sound::startSfxSound(File *file, int file_size, PlayingSoundHandle *handle,
}
if (_scumm->_imuseDigital) {
- _scumm->_imuseDigital->startSound(kTalkSoundID, 0, input);
+ _scumm->_imuseDigital->stopSound(kTalkSoundID);
+ _scumm->_imuseDigital->startVoice(kTalkSoundID, input);
} else {
_scumm->_mixer->playInputStream(handle, input, false, 255, 0, id);
}
diff --git a/scumm/string.cpp b/scumm/string.cpp
index 0940a85527..be1c9128f3 100644
--- a/scumm/string.cpp
+++ b/scumm/string.cpp
@@ -28,7 +28,7 @@
#include "scumm/actor.h"
#include "scumm/charset.h"
#include "scumm/dialogs.h"
-#include "scumm/imuse_digi.h"
+#include "scumm/imuse_digi/dimuse.h"
#include "scumm/verbs.h"
#include "scumm/sound.h"
@@ -921,7 +921,10 @@ const byte *ScummEngine::translateTextAndPlaySpeech(const byte *ptr) {
pointer[j] = 0;
// Play speech
- _imuseDigital->playBundleSound(pointer);
+ if (!(_features & GF_DEMO) && (_gameId == GID_CMI)) // CMI demo does not have .IMX for voice
+ strcat(pointer, ".IMX");
+ _imuseDigital->stopSound(kTalkSoundID);
+ _imuseDigital->startVoice(kTalkSoundID, pointer);
ptr = _transText;
}