aboutsummaryrefslogtreecommitdiff
path: root/scumm/imuse_digi
diff options
context:
space:
mode:
Diffstat (limited to 'scumm/imuse_digi')
-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.cpp698
-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.cpp583
9 files changed, 2851 insertions, 0 deletions
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/imuse_digi/dimuse_codecs.cpp b/scumm/imuse_digi/dimuse_codecs.cpp
new file mode 100644
index 0000000000..5d3e1f78f2
--- /dev/null
+++ b/scumm/imuse_digi/dimuse_codecs.cpp
@@ -0,0 +1,698 @@
+/* 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"
+
+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
+static const int16 imcTable[] = {
+ 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x0010, 0x0011,
+ 0x0013, 0x0015, 0x0017, 0x0019, 0x001C, 0x001F, 0x0022, 0x0025, 0x0029, 0x002D,
+ 0x0032, 0x0037, 0x003C, 0x0042, 0x0049, 0x0050, 0x0058, 0x0061, 0x006B, 0x0076,
+ 0x0082, 0x008F, 0x009D, 0x00AD, 0x00BE, 0x00D1, 0x00E6, 0x00FD, 0x0117, 0x0133,
+ 0x0151, 0x0173, 0x0198, 0x01C1, 0x01EE, 0x0220, 0x0256, 0x0292, 0x02D4, 0x031C,
+ 0x036C, 0x03C3, 0x0424, 0x048E, 0x0502, 0x0583, 0x0610, 0x06AB, 0x0756, 0x0812,
+ 0x08E0, 0x09C3, 0x0ABD, 0x0BD0, 0x0CFF, 0x0E4C, 0x0FBA, 0x114C, 0x1307, 0x14EE,
+ 0x1706, 0x1954, 0x1BDC, 0x1EA5, 0x21B6, 0x2515, 0x28CA, 0x2CDF, 0x315B, 0x364B,
+ 0x3BB9, 0x41B2, 0x4844, 0x4F7E, 0x5771, 0x602F, 0x69CE, 0x7462, 0x7FFF
+};
+#endif
+
+static const byte imxOtherTable[6][128] = {
+ {
+ 0xFF, 0x04, 0xFF, 0x04
+ },
+
+ {
+ 0xFF, 0xFF, 0x02, 0x08, 0xFF, 0xFF, 0x02, 0x08
+ },
+
+ {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x02, 0x04, 0x06,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x02, 0x04, 0x06
+ },
+
+ {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x01, 0x02, 0x04, 0x06, 0x08, 0x0C, 0x10, 0x20,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x01, 0x02, 0x04, 0x06, 0x08, 0x0C, 0x10, 0x20
+ },
+
+ {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x01, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
+ 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x20,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x01, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E,
+ 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x20
+ },
+
+ {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20
+ }
+};
+
+static const byte imxShortTable[] = {
+ 0, 0, 1, 3, 7, 15, 31, 63
+};
+
+void initializeImcTables() {
+ int32 destTablePos = 0;
+ int32 imcTable1Pos = 0;
+ do {
+ byte put = 1;
+ int32 tableValue = ((imcTable[imcTable1Pos] * 4) / 7) / 2;
+ if (tableValue != 0) {
+ do {
+ tableValue /= 2;
+ put++;
+ } while (tableValue != 0);
+ }
+ if (put < 3) {
+ put = 3;
+ }
+ if (put > 8) {
+ put = 8;
+ }
+ put--;
+ _destImcTable[destTablePos] = put;
+ destTablePos++;
+ } while (++imcTable1Pos <= 88);
+ _destImcTable[89] = 0;
+
+ for (int n = 0; n < 64; n++) {
+ imcTable1Pos = 0;
+ destTablePos = n;
+ do {
+ int32 count = 32;
+ int32 put = 0;
+ int32 tableValue = imcTable[imcTable1Pos];
+ do {
+ if ((count & n) != 0) {
+ put += tableValue;
+ }
+ count /= 2;
+ tableValue /= 2;
+ } while (count != 0);
+ _destImcTable2[destTablePos] = put;
+ destTablePos += 64;
+ } while (++imcTable1Pos <= 88);
+ }
+}
+#define NextBit \
+ do { \
+ bit = mask & 1; \
+ mask >>= 1; \
+ if (!--bitsleft) { \
+ mask = READ_LE_UINT16(srcptr); \
+ srcptr += 2; \
+ bitsleft = 16; \
+ } \
+ } while (0)
+
+static int32 compDecode(byte *src, byte *dst) {
+ byte *result, *srcptr = src, *dstptr = dst;
+ int data, size, bit, bitsleft = 16, mask = READ_LE_UINT16(srcptr);
+ srcptr += 2;
+
+ while (1) {
+ NextBit;
+ if (bit) {
+ *dstptr++ = *srcptr++;
+ } else {
+ NextBit;
+ if (!bit) {
+ NextBit;
+ size = bit << 1;
+ NextBit;
+ size = (size | bit) + 3;
+ data = *srcptr++ | 0xffffff00;
+ } else {
+ data = *srcptr++;
+ size = *srcptr++;
+
+ data |= 0xfffff000 + ((size & 0xf0) << 4);
+ size = (size & 0x0f) + 3;
+
+ if (size == 3)
+ if (((*srcptr++) + 1) == 1)
+ return dstptr - dst;
+ }
+ result = dstptr + data;
+ while (size--)
+ *dstptr++ = *result++;
+ }
+ }
+}
+#undef NextBit
+
+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;
+ byte t_tmp1, t_tmp2;
+
+ switch (codec) {
+ case 0:
+ memcpy(comp_output, comp_input, input_size);
+ output_size = input_size;
+ break;
+
+ case 1:
+ output_size = compDecode(comp_input, comp_output);
+ break;
+
+ case 2:
+ output_size = compDecode(comp_input, comp_output);
+ p = comp_output;
+ for (z = 1; z < output_size; z++)
+ p[z] += p[z - 1];
+ break;
+
+ case 3:
+ output_size = compDecode(comp_input, comp_output);
+ p = comp_output;
+ for (z = 2; z < output_size; z++)
+ p[z] += p[z - 1];
+ for (z = 1; z < output_size; z++)
+ p[z] += p[z - 1];
+ break;
+
+ case 4:
+ output_size = compDecode(comp_input, comp_output);
+ p = comp_output;
+ for (z = 2; z < output_size; z++)
+ p[z] += p[z - 1];
+ for (z = 1; z < output_size; z++)
+ p[z] += p[z - 1];
+
+ t_table = (byte *)malloc(output_size);
+ memset(t_table, 0, output_size);
+
+ src = comp_output;
+ length = (output_size * 8) / 12;
+ k = 0;
+ if (length > 0) {
+ c = -12;
+ s = 0;
+ j = 0;
+ do {
+ ptr = src + length + k / 2;
+ if (k & 1) {
+ r = c / 8;
+ t_table[r + 2] = ((src[j] & 0x0f) << 4) | (ptr[1] >> 4);
+ t_table[r + 1] = (src[j] & 0xf0) | (t_table[r + 1]);
+ } else {
+ r = s / 8;
+ t_table[r + 0] = ((src[j] & 0x0f) << 4) | (ptr[0] & 0x0f);
+ t_table[r + 1] = src[j] >> 4;
+ }
+ s += 12;
+ c += 12;
+ k++;
+ j++;
+ } while (k < length);
+ }
+ offset1 = ((length - 1) * 3) / 2;
+ t_table[offset1 + 1] = (t_table[offset1 + 1]) | (src[length - 1] & 0xf0);
+ memcpy(src, t_table, output_size);
+ free(t_table);
+ break;
+
+ case 5:
+ output_size = compDecode(comp_input, comp_output);
+ p = comp_output;
+ for (z = 2; z < output_size; z++)
+ p[z] += p[z - 1];
+ for (z = 1; z < output_size; z++)
+ p[z] += p[z - 1];
+
+ t_table = (byte *)malloc(output_size);
+ memset(t_table, 0, output_size);
+
+ src = comp_output;
+ length = (output_size * 8) / 12;
+ k = 1;
+ c = 0;
+ s = 12;
+ t_table[0] = src[length] / 16;
+ t = length + k;
+ j = 1;
+ if (t > k) {
+ do {
+ ptr = src + length + k / 2;
+ if (k & 1) {
+ r = c / 8;
+ t_table[r + 0] = (src[j - 1] & 0xf0) | t_table[r];
+ t_table[r + 1] = ((src[j - 1] & 0x0f) << 4) | (ptr[0] & 0x0f);
+ } else {
+ r = s / 8;
+ t_table[r + 0] = src[j - 1] >> 4;
+ t_table[r - 1] = ((src[j - 1] & 0x0f) << 4) | (ptr[0] >> 4);
+ }
+ s += 12;
+ c += 12;
+ k++;
+ j++;
+ } while (k < t);
+ }
+ memcpy(src, t_table, output_size);
+ free(t_table);
+ break;
+
+ case 6:
+ output_size = compDecode(comp_input, comp_output);
+ p = comp_output;
+ for (z = 2; z < output_size; z++)
+ p[z] += p[z - 1];
+ for (z = 1; z < output_size; z++)
+ p[z] += p[z - 1];
+
+ t_table = (byte *)malloc(output_size);
+ memset(t_table, 0, output_size);
+
+ src = comp_output;
+ length = (output_size * 8) / 12;
+ k = 0;
+ c = 0;
+ j = 0;
+ s = -12;
+ t_table[0] = src[output_size - 1];
+ t_table[output_size - 1] = src[length - 1];
+ t = length - 1;
+ if (t > 0) {
+ do {
+ ptr = src + length + k / 2;
+ if (k & 1) {
+ r = s / 8;
+ t_table[r + 2] = (src[j] & 0xf0) | *(t_table + r + 2);
+ t_table[r + 3] = ((src[j] & 0x0f) << 4) | (ptr[0] >> 4);
+ } else {
+ r = c / 8;
+ t_table[r + 2] = src[j] >> 4;
+ t_table[r + 1] = ((src[j] & 0x0f) << 4) | (ptr[0] & 0x0f);
+ }
+ s += 12;
+ c += 12;
+ k++;
+ j++;
+ } while (k < t);
+ }
+ memcpy(src, t_table, output_size);
+ free(t_table);
+ break;
+
+ case 10:
+ output_size = compDecode(comp_input, comp_output);
+ p = comp_output;
+ for (z = 2; z < output_size; z++)
+ p[z] += p[z - 1];
+ for (z = 1; z < output_size; z++)
+ p[z] += p[z - 1];
+
+ t_table = (byte *)malloc(output_size);
+ memcpy(t_table, p, output_size);
+
+ offset1 = output_size / 3;
+ offset2 = offset1 * 2;
+ offset3 = offset2;
+ src = comp_output;
+ do {
+ if (offset1 == 0)
+ break;
+ offset1--;
+ offset2 -= 2;
+ offset3--;
+ t_table[offset2 + 0] = src[offset1];
+ t_table[offset2 + 1] = src[offset3];
+ } while (1);
+
+ src = comp_output;
+ length = (output_size * 8) / 12;
+ k = 0;
+ if (length > 0) {
+ c = -12;
+ s = 0;
+ do {
+ j = length + k / 2;
+ if (k & 1) {
+ r = c / 8;
+ t_tmp1 = t_table[k];
+ t_tmp2 = t_table[j + 1];
+ src[r + 2] = ((t_tmp1 & 0x0f) << 4) | (t_tmp2 >> 4);
+ src[r + 1] = (src[r + 1]) | (t_tmp1 & 0xf0);
+ } else {
+ r = s / 8;
+ t_tmp1 = t_table[k];
+ t_tmp2 = t_table[j];
+ src[r + 0] = ((t_tmp1 & 0x0f) << 4) | (t_tmp2 & 0x0f);
+ src[r + 1] = t_tmp1 >> 4;
+ }
+ s += 12;
+ c += 12;
+ k++;
+ } while (k < length);
+ }
+ offset1 = ((length - 1) * 3) / 2;
+ src[offset1 + 1] = (t_table[length] & 0xf0) | src[offset1 + 1];
+ free(t_table);
+ break;
+
+ case 11:
+ output_size = compDecode(comp_input, comp_output);
+ p = comp_output;
+ for (z = 2; z < output_size; z++)
+ p[z] += p[z - 1];
+ for (z = 1; z < output_size; z++)
+ p[z] += p[z - 1];
+
+ t_table = (byte *)malloc(output_size);
+ memcpy(t_table, p, output_size);
+
+ offset1 = output_size / 3;
+ offset2 = offset1 * 2;
+ offset3 = offset2;
+ src = comp_output;
+ do {
+ if (offset1 == 0)
+ break;
+ offset1--;
+ offset2 -= 2;
+ offset3--;
+ t_table[offset2 + 0] = src[offset1];
+ t_table[offset2 + 1] = src[offset3];
+ } while (1);
+
+ src = comp_output;
+ length = (output_size * 8) / 12;
+ k = 1;
+ c = 0;
+ s = 12;
+ t_tmp1 = t_table[length] / 16;
+ src[0] = t_tmp1;
+ t = length + k;
+ if (t > k) {
+ do {
+ j = length + k / 2;
+ if (k & 1) {
+ r = c / 8;
+ t_tmp1 = t_table[k - 1];
+ t_tmp2 = t_table[j];
+ src[r + 0] = (src[r]) | (t_tmp1 & 0xf0);
+ src[r + 1] = ((t_tmp1 & 0x0f) << 4) | (t_tmp2 & 0x0f);
+ } else {
+ r = s / 8;
+ t_tmp1 = t_table[k - 1];
+ t_tmp2 = t_table[j];
+ src[r + 0] = t_tmp1 >> 4;
+ src[r - 1] = ((t_tmp1 & 0x0f) << 4) | (t_tmp2 >> 4);
+ }
+ s += 12;
+ c += 12;
+ k++;
+ } while (k < t);
+ }
+ free(t_table);
+ break;
+
+ case 12:
+ output_size = compDecode(comp_input, comp_output);
+ p = comp_output;
+ for (z = 2; z < output_size; z++)
+ p[z] += p[z - 1];
+ for (z = 1; z < output_size; z++)
+ p[z] += p[z - 1];
+
+ t_table = (byte *)malloc(output_size);
+ memcpy(t_table, p, output_size);
+
+ offset1 = output_size / 3;
+ offset2 = offset1 * 2;
+ offset3 = offset2;
+ src = comp_output;
+ do {
+ if (offset1 == 0)
+ break;
+ offset1--;
+ offset2 -= 2;
+ offset3--;
+ t_table[offset2 + 0] = src[offset1];
+ t_table[offset2 + 1] = src[offset3];
+ } while (1);
+
+ src = comp_output;
+ length = (output_size * 8) / 12;
+ k = 0;
+ c = 0;
+ s = -12;
+ src[0] = t_table[output_size - 1];
+ src[output_size - 1] = t_table[length - 1];
+ t = length - 1;
+ if (t > 0) {
+ do {
+ j = length + k / 2;
+ if (k & 1) {
+ r = s / 8;
+ t_tmp1 = t_table[k];
+ t_tmp2 = t_table[j];
+ src[r + 2] = (src[r + 2]) | (t_tmp1 & 0xf0);
+ src[r + 3] = ((t_tmp1 & 0x0f) << 4) | (t_tmp2 >> 4);
+ } else {
+ r = c / 8;
+ t_tmp1 = t_table[k];
+ t_tmp2 = t_table[j];
+ src[r + 2] = t_tmp1 >> 4;
+ src[r + 1] = ((t_tmp1 & 0x0f) << 4) | (t_tmp2 & 0x0f);
+ }
+ s += 12;
+ c += 12;
+ k++;
+ } while (k < t);
+ }
+ free(t_table);
+ break;
+
+ case 13:
+ case 15:
+ if (codec == 13) {
+ channels = 1;
+ } else {
+ channels = 2;
+ }
+
+ {
+ const int MAX_CHANNELS = 2;
+ int32 left, startPos, origLeft, curTableEntry, destPos, esiReg;
+ int16 firstWord;
+ byte sByte[MAX_CHANNELS] = {0, 0};
+ int32 sDWord1[MAX_CHANNELS] = {0, 0};
+ int32 sDWord2[MAX_CHANNELS] = {0, 0};
+ int32 tableEntrySum, imcTableEntry, curTablePos, outputWord, adder;
+ byte decompTable, otherTablePos, bitMask;
+ byte *readPos, *dst;
+ uint16 readWord;
+
+ assert(0 <= channels && channels <= MAX_CHANNELS);
+
+ src = comp_input;
+ dst = comp_output;
+ if (channels == 2) {
+ output_size = left = 0x2000;
+ } else {
+ left = 0x1000;
+ output_size = 0x2000;
+ }
+ firstWord = READ_BE_UINT16(src);
+ src += 2;
+ if (firstWord != 0) {
+ memcpy(dst, src, firstWord);
+ dst += firstWord;
+ src += firstWord;
+ startPos = 0;
+ if (channels == 2) {
+ left = 0x2000 - firstWord;
+ output_size = left;
+ } else {
+ left = 0x1000 - firstWord / 2;
+ output_size = left * 2;
+ }
+ } else {
+ startPos = 1;
+ for (int i = 0; i < channels; i++) {
+ sByte[i] = *(src++);
+ sDWord1[i] = READ_BE_UINT32(src);
+ src += 4;
+ sDWord2[i] = READ_BE_UINT32(src);
+ src += 4;
+ }
+ }
+
+ origLeft = left >> (channels - 1);
+ tableEntrySum = 0;
+ for (int l = 0; l < channels; l++) {
+ if (startPos != 0) {
+ curTablePos = sByte[l];
+ imcTableEntry = sDWord1[l];
+ outputWord = sDWord2[l];
+ } else {
+ curTablePos = 0;
+ imcTableEntry = 7;
+ outputWord = 0;
+ }
+
+ left = origLeft;
+ destPos = l * 2;
+
+ if (channels == 2) {
+ if (l == 0)
+ left++;
+ left /= 2;
+ }
+
+ while (left--) {
+ curTableEntry = _destImcTable[curTablePos];
+ decompTable = (byte)(curTableEntry - 2);
+ bitMask = 2 << decompTable;
+ readPos = src + tableEntrySum / 8;
+
+ // FIXME - it seems the decoder often reads exactly one byte too
+ // far - that is, it reads 2 bytes at once, and the second byte
+ // is just outside the buffer. However, it seems of these two bytes,
+ // only the upper one is actually used, so this should be fine.
+ // Still, I put this error message into place. If somebody one day
+ // encounters a situation where the second byte would be used, too,
+ // then this would indicate there is a bug in the decoder...
+ if (readPos + 1 >= comp_input + input_size) {
+ // OK an overflow... if it is more than one byte or if we
+ // need more than 8 bit of data -> error
+ if (readPos + 1 > comp_input + input_size ||
+ curTableEntry + (tableEntrySum & 7) > 8) {
+ error("decompressCodec: input buffer overflow: %d bytes over (we need %d bits of data)",
+ (int)((readPos + 1) - (comp_input + input_size)) + 1,
+ curTableEntry + (tableEntrySum & 7)
+ );
+ }
+ }
+ readWord = (uint16)(READ_BE_UINT16(readPos) << (tableEntrySum & 7));
+ otherTablePos = (byte)(readWord >> (16 - curTableEntry));
+ tableEntrySum += curTableEntry;
+ esiReg = ((imxShortTable[curTableEntry] & otherTablePos)
+ << (7 - curTableEntry)) + (curTablePos * 64);
+ imcTableEntry >>= (curTableEntry - 1);
+ adder = imcTableEntry + _destImcTable2[esiReg];
+ if ((otherTablePos & bitMask) != 0) {
+ adder = -adder;
+ }
+ outputWord += adder;
+
+ // Clip outputWord to 16 bit signed, and write it into the destination stream
+ if (outputWord > 0x7fff)
+ outputWord = 0x7fff;
+ if (outputWord < -0x8000)
+ outputWord = -0x8000;
+ dst[destPos] = ((int16)outputWord) >> 8;
+ dst[destPos + 1] = (byte)(outputWord);
+
+ // Adjust the curTablePos / imcTableEntry
+ assert(decompTable < 6);
+ curTablePos += (signed char)imxOtherTable[decompTable][otherTablePos];
+ if (curTablePos > 88)
+ curTablePos = 88;
+ if (curTablePos < 0)
+ curTablePos = 0;
+ imcTableEntry = imcTable[curTablePos];
+
+ destPos += channels * 2;
+ }
+ }
+ }
+ break;
+
+ default:
+ error("BundleCodecs::decompressCodec() Unknown codec %d!", (int)codec);
+ output_size = 0;
+ break;
+ }
+
+ return output_size;
+}
+
+} // End of namespace BundleCodecs
+
+} // End of namespace Scumm
+
+#ifdef __PALM_OS__
+#include "scumm_globals.h"
+
+_GINIT(BundleCodecs)
+_GSETPTR(Scumm::BundleCodecs::imcTable, GBVARS_IMCTABLE_INDEX, int16, GBVARS_SCUMM)
+_GEND
+
+_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/dimuse_tables.cpp b/scumm/imuse_digi/dimuse_tables.cpp
new file mode 100644
index 0000000000..d9f5fa9301
--- /dev/null
+++ b/scumm/imuse_digi/dimuse_tables.cpp
@@ -0,0 +1,583 @@
+/* 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 "scumm/imuse_digi/dimuse.h"
+
+namespace Scumm {
+
+imuse_music_map _digStateMusicMap[] = {
+ {0, 0, 0, 0, 0, 0 },
+ {1, 0, 0, 0, 0, 0 },
+ {2, 2, 0, 0, 0, 0 },
+ {4, 3, 0, 0, 0, 0 },
+ {5, 3, 0, 0, 0, 0 },
+ {6, 3, 0, 0, 0, 0 },
+ {7, 3, 0, 0, 0, 0 },
+ {8, 4, 0, 0, 0, 0 },
+ {9, 5, 0, 0, 0, 0 },
+ {10, 4, 0, 0, 0, 0 },
+ {12, 5, 0, 0, 0, 0 },
+ {14, 5, 0, 0, 0, 0 },
+ {15, 6, 29, 7, 0, 0 },
+ {16, 8, 0, 0, 0, 0 },
+ {17, 1, 0, 0, 0, 0 },
+ {18, 9, 0, 0, 0, 0 },
+ {19, 9, 0, 0, 0, 0 },
+ {20, 6, 0, 0, 0, 0 },
+ {21, 6, 0, 0, 0, 0 },
+ {22, 44, 0, 0, 0, 0 },
+ {23, 10, 7, 0, 0, 0 },
+ {24, 26, 0, 0, 0, 0 },
+ {25, 17, 0, 0, 0, 0 },
+ {26, 17, 0, 0, 0, 0 },
+ {27, 18, 0, 0, 0, 0 },
+ {28, 1, 0, 0, 0, 0 },
+ {29, 20, 0, 0, 0, 0 },
+ {30, 22, 0, 0, 0, 0 },
+ {31, 23, 0, 0, 0, 0 },
+ {32, 22, 0, 0, 0, 0 },
+ {33, 26, 0, 0, 0, 0 },
+ {34, 24, 0, 0, 0, 0 },
+ {35, 1, 0, 0, 0, 0 },
+ {36, 1, 0, 0, 0, 0 },
+ {37, 42, 0, 0, 0, 0 },
+ {38, 43, 0, 0, 0, 0 },
+ {39, 44, 0, 0, 0, 0 },
+ {40, 1, 0, 0, 0, 0 },
+ {41, 43, 0, 0, 0, 0 },
+ {42, 44, 0, 0, 0, 0 },
+ {43, 43, 0, 0, 0, 0 },
+ {44, 45, 117,45, 114,46},
+ {47, 1, 0, 0, 0, 0 },
+ {48, 43, 0, 0, 0, 0 },
+ {49, 44, 0, 0, 0, 0 },
+ {51, 1, 0, 0, 0, 0 },
+ {53, 28, 0, 0, 0, 0 },
+ {54, 28, 0, 0, 0, 0 },
+ {55, 29, 0, 0, 0, 0 },
+ {56, 29, 0, 0, 0, 0 },
+ {57, 29, 0, 0, 0, 0 },
+ {58, 31, 0, 0, 0, 0 },
+ {59, 1, 0, 0, 0, 0 },
+ {60, 37, 0, 0, 0, 0 },
+ {61, 39, 0, 0, 0, 0 },
+ {62, 38, 0, 0, 0, 0 },
+ {63, 39, 0, 0, 0, 0 },
+ {64, 39, 0, 0, 0, 0 },
+ {65, 40, 0, 0, 0, 0 },
+ {67, 40, 0, 0, 0, 0 },
+ {68, 39, 0, 0, 0, 0 },
+ {69, 1, 0, 0, 0, 0 },
+ {70, 49, 0, 0, 0, 0 },
+ {73, 50, 0, 0, 0, 0 },
+ {75, 51, 0, 0, 0, 0 },
+ {76, 1, 0, 0, 0, 0 },
+ {77, 52, 7, 0, 0, 0 },
+ {78, 63, 0, 0, 0, 0 },
+ {79, 1, 0, 0, 0, 0 },
+ {82, 21, 0, 0, 0, 0 },
+ {85, 1, 0, 0, 0, 0 },
+ {86, 0, 0, 0, 0, 0 },
+ {89, 33, 6, 35, 5, 34},
+ {90, 16, 0, 0, 0, 0 },
+ {91, 57, 0, 0, 0, 0 },
+ {88, 32, 0, 0, 0, 0 },
+ {92, 25, 0, 0, 0, 0 },
+ {93, 0, 0, 0, 0, 0 },
+ {95, 19, 0, 0, 0, 0 },
+ {80, 41, 0, 0, 0, 0 },
+ {81, 48, 0, 0, 0, 0 },
+ {83, 27, 0, 0, 0, 0 },
+ {94, 36, 0, 0, 0, 0 },
+ {40, 1, 0, 0, 0, 0 },
+ {96, 13, 0, 0, 0, 0 },
+ {97, 14, 0, 0, 0, 0 },
+ {98, 11, 0, 0, 0, 0 },
+ {99, 15, 0, 0, 0, 0 },
+ {100, 17, 0, 0, 0, 0 },
+ {101, 38, 0, 0, 0, 0 },
+ {103, 0, 0, 0, 0, 0 },
+ {104, 0, 0, 0, 0, 0 },
+ {11, 44, 0, 0, 0, 0 },
+ {3, 47, 0, 0, 0, 0 },
+ {105, 30, 128,29, 0, 0 },
+ {106, 0, 0, 0, 0, 0 },
+ {107, 1, 0, 0, 0, 0 },
+ {108, 1, 0, 0, 0, 0 },
+ {47, 1, 0, 0, 0, 0 },
+ {50, 1, 0, 0, 0, 0 },
+ {52, 0, 0, 0, 0, 0 },
+ {71, 1, 0, 0, 0, 0 },
+ {13, 1, 0, 0, 0, 0 },
+ {72, 1, 0, 0, 0, 0 },
+ {46, 33, 6, 35, 5, 34},
+ {74, 1, 0, 0, 0, 0 },
+ {84, 1, 0, 0, 0, 0 },
+ {66, 1, 0, 0, 0, 0 },
+ {102, 1, 0, 0, 0, 0 },
+ {109, 1, 0, 0, 0, 0 },
+ {110, 2, 0, 0, 0, 0 },
+ {45, 1, 0, 0, 0, 0 },
+ {87, 1, 0, 0, 0, 0 },
+ {111, 1, 0, 0, 0, 0 },
+ {-1, 1, 0, 0, 0, 0 }
+};
+
+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"},
+ {3, 1120, 0, 3, 2, 0, "stateAstClose", "Asteroid (amb-close)", "ASTERO~2.IMU"},
+ {4, 1140, 0, 3, 0, 0, "stateAstInside", "Asteroid (inside)", "ASTERO~3.IMU"},
+ {5, 1150, 0, 3, 0, 0, "stateAstCore", "Asteroid (core)", "ASTERO~4.IMU"},
+ {6, 1200, 0, 3, 0, 0, "stateCanyonClose", "Canyon (close)", "CANYON~1.IMU"},
+ {7, 1205, 0, 3, 0, 0, "stateCanyonClose_m", "Canyon (close-m)", "CANYON~2.IMU"},
+ {8, 1210, 0, 3, 0, 0, "stateCanyonOver", "Canyon (over)", "CANYON~3.IMU"},
+ {9, 1220, 0, 3, 0, 0, "stateCanyonWreck", "Canyon (wreck)", "CANYON~4.IMU"},
+ {10, 1300, 0, 3,10, 0, "stateNexusCanyon", "Nexus (plan)", "NEXUS(~1.IMU"},
+ {11, 1310, 0, 3,10, 0, "stateNexusPlan", "Nexus (plan)", "NEXUS(~1.IMU"},
+ {12, 1320, 0, 3,10, 0, "stateNexusRamp", "Nexus (ramp)", "NEXUS(~2.IMU"},
+ {13, 1330, 0, 3,10, 0, "stateNexusMuseum", "Nexus (museum)", "NEXUS(~3.IMU"},
+ {14, 1340, 0, 3,10, 0, "stateNexusMap", "Nexus (map)", "NEXUS(~4.IMU"},
+ {15, 1350, 0, 3,10, 0, "stateNexusTomb", "Nexus (tomb)", "NE3706~5.IMU"},
+ {16, 1360, 0, 3,10, 0, "stateNexusCath", "Nexus (cath)", "NE3305~5.IMU"},
+ {17, 1370, 0, 3, 0, 0, "stateNexusAirlock", "Nexus (airlock)", "NE2D3A~5.IMU"},
+ {18, 1380, 0, 3, 0, 0, "stateNexusPowerOff", "Nexus (power)", "NE8522~5.IMU"},
+ {19, 1400, 0, 3, 0, 0, "stateMuseumTramNear", "Tram (mu-near)", "TRAM(M~1.IMU"},
+ {20, 1410, 0, 3, 0, 0, "stateMuseumTramFar", "Tram (mu-far)", "TRAM(M~2.IMU"},
+ {21, 1420, 0, 3, 0, 0, "stateMuseumLockup", "Museum (lockup)", "MUSEUM~1.IMU"},
+ {22, 1433, 0, 3,22, 0, "stateMuseumPool", "Museum (amb-pool)", "MUSEUM~2.IMU"},
+ {23, 1436, 0, 3,22, 0, "stateMuseumSpire", "Museum (amb-spire)", "MUSEUM~3.IMU"},
+ {24, 1440, 0, 3,22, 0, "stateMuseumMuseum", "Museum (amb-mu)", "MUSEUM~4.IMU"},
+ {25, 1450, 0, 3, 0, 0, "stateMuseumLibrary", "Museum (library)", "MUB575~5.IMU"},
+ {26, 1460, 0, 3, 0, 0, "stateMuseumCavern", "Museum (cavern)", "MUF9BE~5.IMU"},
+ {27, 1500, 0, 3, 0, 0, "stateTombTramNear", "Tram (tomb-near)", "TRAM(T~1.IMU"},
+ {28, 1510, 0, 3,28, 0, "stateTombBase", "Tomb (amb-base)", "TOMB(A~1.IMU"},
+ {29, 1520, 0, 3,28, 0, "stateTombSpire", "Tomb (amb-spire)", "TOMB(A~2.IMU"},
+ {30, 1530, 0, 3,28, 0, "stateTombCave", "Tomb (amb-cave)", "TOMB(A~3.IMU"},
+ {31, 1540, 0, 3,31, 0, "stateTombCrypt", "Tomb (crypt)", "TOMB(C~1.IMU"},
+ {32, 1550, 0, 3,31, 0, "stateTombGuards", "Tomb (crypt-guards)", "TOMB(C~2.IMU"},
+ {33, 1560, 0, 3, 0, 0, "stateTombInner", "Tomb (inner)", "TOMB(I~1.IMU"},
+ {34, 1570, 0, 3, 0, 0, "stateTombCreator1", "Tomb (creator 1)", "TOMB(C~3.IMU"},
+ {35, 1580, 0, 3, 0, 0, "stateTombCreator2", "Tomb (creator 2)", "TOMB(C~4.IMU"},
+ {36, 1600, 0, 3, 0, 0, "statePlanTramNear", "Tram (plan-near)", "TRAM(P~1.IMU"},
+ {37, 1610, 0, 3, 0, 0, "statePlanTramFar", "Tram (plan-far)", "TRAM(P~2.IMU"},
+ {38, 1620, 0, 3,38, 0, "statePlanBase", "Plan (amb-base)", "PLAN(A~1.IMU"},
+ {39, 1630, 0, 3,38, 0, "statePlanSpire", "Plan (amb-spire)", "PLAN(A~2.IMU"},
+ {40, 1650, 0, 3, 0, 0, "statePlanDome", "Plan (dome)", "PLAN(D~1.IMU"},
+ {41, 1700, 0, 3, 0, 0, "stateMapTramNear", "Tram (map-near)", "TRAM(M~3.IMU"},
+ {42, 1710, 0, 3, 0, 0, "stateMapTramFar", "Tram (map-far)", "TRAM(M~4.IMU"},
+ {43, 1720, 0, 3,43, 0, "stateMapCanyon", "Map (amb-canyon)", "MAP(AM~1.IMU"},
+ {44, 1730, 0, 3,43, 0, "stateMapExposed", "Map (amb-exposed)", "MAP(AM~2.IMU"},
+ {45, 1750, 0, 3,43, 0, "stateMapNestEmpty", "Map (amb-nest)", "MAP(AM~4.IMU"},
+ {46, 1760, 0, 3, 0, 0, "stateMapNestMonster", "Map (monster)", "MAP(MO~1.IMU"},
+ {47, 1770, 0, 3, 0, 0, "stateMapKlein", "Map (klein)", "MAP(KL~1.IMU"},
+ {48, 1800, 0, 3, 0, 0, "stateCathTramNear", "Tram (cath-near)", "TRAM(C~1.IMU"},
+ {49, 1810, 0, 3, 0, 0, "stateCathTramFar", "Tram (cath-far)", "TRAM(C~2.IMU"},
+ {50, 1820, 0, 3,50, 0, "stateCathLab", "Cath (amb-inside)", "CATH(A~1.IMU"},
+ {51, 1830, 0, 3,50, 0, "stateCathOutside", "Cath (amb-outside)", "CATH(A~2.IMU"},
+ {52, 1900, 0, 3,52, 0, "stateWorldMuseum", "World (museum)", "WORLD(~1.IMU"},
+ {53, 1901, 0, 3,52, 0, "stateWorldPlan", "World (plan)", "WORLD(~2.IMU"},
+ {54, 1902, 0, 3,52, 0, "stateWorldTomb", "World (tomb)", "WORLD(~3.IMU"},
+ {55, 1903, 0, 3,52, 0, "stateWorldMap", "World (map)", "WORLD(~4.IMU"},
+ {56, 1904, 0, 3,52, 0, "stateWorldCath", "World (cath)", "WO3227~5.IMU"},
+ {57, 1910, 0, 3, 0, 0, "stateEye1", "Eye 1", "EYE1~1.IMU"},
+ {58, 1911, 0, 3, 0, 0, "stateEye2", "Eye 2", "EYE2~1.IMU"},
+ {59, 1912, 0, 3, 0, 0, "stateEye3", "Eye 3", "EYE3~1.IMU"},
+ {60, 1913, 0, 3, 0, 0, "stateEye4", "Eye 4", "EYE4~1.IMU"},
+ {61, 1914, 0, 3, 0, 0, "stateEye5", "Eye 5", "EYE5~1.IMU"},
+ {62, 1915, 0, 3, 0, 0, "stateEye6", "Eye 6", "EYE6~1.IMU"},
+ {63, 1916, 0, 3, 0, 0, "stateEye7", "Eye 7", "EYE7~1.IMU"},
+ {-1, -1, 0, 0, 0, 0, "", "", ""}
+};
+
+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", "", "" },
+ {0, 2020, 0, 6, 0, 0, "seqExplosion1b", "", "" },
+ {0, 2030, 0, 3, 0, 0, "seqAstTunnel1a", "Seq (ast tunnel 1a)", "SEQ(AS~1.IMU"},
+ {0, 2031, 0, 6, 0, 0, "seqAstTunnel2b", "", "" },
+ {0, 2032, 0, 4, 0, 0, "seqAstTunnel3a", "Seq (ast tunnel 3a)", "SEQ(AS~2.IMU"},
+ {0, 2040, 0, 5, 0, 0, "seqToPlanet1b", "", "" },
+ {0, 2045, 0, 4, 0, 0, "seqArgBegin", "Seq (arg begin)", "SEQ(AR~1.IMU"},
+ {0, 2046, 0, 4, 0, 0, "seqArgEnd", "Seq (arg end)", "SEQ(AR~2.IMU"},
+ {0, 2050, 0, 4, 0, 0, "seqWreckGhost", "Seq (ghost-wreck)", "SEQ(GH~1.IMU"},
+ {0, 2060, 0, 4, 0, 0, "seqCanyonGhost", "Seq (ghost-canyon)", "SEQ(GH~2.IMU"},
+ {0, 2070, 0, 0, 0, 0, "seqBrinkFall", "", "" },
+ {0, 2080, 0, 4, 0, 0, "seqPanUpCanyon", "Seq (pan up canyon)", "SEQ(PA~1.IMU"},
+ {0, 2091, 0, 6, 0, 0, "seqAirlockTunnel1b", "", "" },
+ {0, 2100, 0, 6, 0, 0, "seqTramToMu", "", "" },
+ {0, 2101, 0, 6, 0, 0, "seqTramFromMu", "", "" },
+ {0, 2102, 0, 6, 0, 0, "seqTramToTomb", "", "" },
+ {0, 2103, 0, 6, 0, 0, "seqTramFromTomb", "", "" },
+ {0, 2104, 0, 6, 0, 0, "seqTramToPlan", "", "" },
+ {0, 2105, 0, 6, 0, 0, "seqTramFromPlan", "", "" },
+ {0, 2106, 0, 6, 0, 0, "seqTramToMap", "", "" },
+ {0, 2107, 0, 6, 0, 0, "seqTramFromMap", "", "" },
+ {0, 2108, 0, 6, 0, 0, "seqTramToCath", "", "" },
+ {0, 2109, 0, 6, 0, 0, "seqTramFromCath", "", "" },
+ {0, 2110, 0, 0, 0, 0, "seqMuseumGhost", "", "" },
+ {0, 2120, 0, 0, 0, 0, "seqSerpentAppears", "", "" },
+ {0, 2130, 0, 0, 0, 0, "seqSerpentEats", "", "" },
+ {0, 2140, 0, 6, 0, 0, "seqBrinkRes1b", "", "" },
+ {0, 2141, 0, 4, 0, 0, "seqBrinkRes2a", "Seq (brink's madness)", "SEQ(BR~1.IMU"},
+ {0, 2150, 0, 3, 0, 0, "seqLockupEntry", "Seq (brink's madness)", "SEQ(BR~1.IMU"},
+ {0, 2160, 0, 0, 0, 0, "seqSerpentExplodes", "", "" },
+ {0, 2170, 0, 4, 0, 0, "seqSwimUnderwater", "Seq (descent)", "SEQ(DE~1.IMU"},
+ {0, 2175, 0, 4, 0, 0, "seqWavesPlunge", "Seq (plunge)", "SEQ(PL~1.IMU"},
+ {0, 2180, 0, 0, 0, 0, "seqCryptOpens", "", "" },
+ {0, 2190, 0, 0, 0, 0, "seqGuardsFight", "", "" },
+ {0, 2200, 0, 3, 0, 0, "seqCreatorRes1.1a", "Seq (creator res 1.1a)", "SEQ(CR~1.IMU"},
+ {0, 2201, 0, 6, 0, 0, "seqCreatorRes1.2b", "", "" },
+ {0, 2210, 0, 6, 0, 0, "seqMaggieCapture1b", "", "" },
+ {0, 2220, 0, 3, 0, 0, "seqStealCrystals", "Seq (brink's madness)", "SEQ(BR~1.IMU"},
+ {0, 2230, 0, 0, 0, 0, "seqGetByMonster", "", "" },
+ {0, 2240, 0, 6, 0, 0, "seqKillMonster1b", "", "" },
+ {0, 2250, 0, 3, 0, 0, "seqCreatorRes2.1a", "Seq (creator res 2.1a)", "SEQ(CR~2.IMU"},
+ {0, 2251, 0, 6, 0, 0, "seqCreatorRes2.2b", "", "" },
+ {0, 2252, 0, 4, 0, 0, "seqCreatorRes2.3a", "Seq (creator res 2.3a)", "SEQ(CR~3.IMU"},
+ {0, 2260, 0, 0, 0, 0, "seqMaggieInsists", "", "" },
+ {0, 2270, 0, 0, 0, 0, "seqBrinkHelpCall", "", "" },
+ {0, 2280, 0, 3, 0, 0, "seqBrinkCrevice1a", "Seq (brink crevice 1a)", "SEQ(BR~2.IMU"},
+ {0, 2281, 0, 3, 0, 0, "seqBrinkCrevice2a", "Seq (brink crevice 2a)", "SEQ(BR~3.IMU"},
+ {0, 2290, 0, 6, 0, 0, "seqCathAccess1b", "", "" },
+ {0, 2291, 0, 4, 0, 0, "seqCathAccess2a", "Seq (cath access 2a)", "SEQ(CA~1.IMU"},
+ {0, 2300, 0, 3, 0, 0, "seqBrinkAtGenerator", "Seq (brink's madness)", "SEQ(BR~1.IMU"},
+ {0, 2320, 0, 6, 0, 0, "seqFightBrink1b", "", "" },
+ {0, 2340, 0, 6, 0, 0, "seqMaggieDies1b", "", "" },
+ {0, 2346, 0, 6, 0, 0, "seqMaggieRes1b", "", "" },
+ {0, 2347, 0, 4, 0, 0, "seqMaggieRes2a", "Seq (maggie res 2a)", "SEQ(MA~1.IMU"},
+ {0, 2350, 0, 0, 0, 0, "seqCreatureFalls", "", "" },
+ {0, 2360, 0, 5, 0, 0, "seqFinale1b", "", "" },
+ {0, 2370, 0, 3, 0, 0, "seqFinale2a", "Seq (finale 2a)", "SEQ(FI~1.IMU"},
+ {0, 2380, 0, 6, 0, 0, "seqFinale3b1", "", "" },
+ {0, 2390, 0, 6, 0, 0, "seqFinale3b2", "", "" },
+ {0, 2400, 0, 3, 0, 0, "seqFinale4a", "Seq (finale 4a)", "SEQ(FI~2.IMU"},
+ {0, 2410, 0, 3, 0, 0, "seqFinale5a", "Seq (finale 5a)", "SEQ(FI~3.IMU"},
+ {0, 2420, 0, 3, 0, 0, "seqFinale6a", "Seq (finale 6a)", "SEQ(FI~4.IMU"},
+ {0, 2430, 0, 3, 0, 0, "seqFinale7a", "Seq (finale 7a)", "SE3D2B~5.IMU"},
+ {0, 2440, 0, 6, 0, 0, "seqFinale8b", "", "" },
+ {0, 2450, 0, 4, 0, 0, "seqFinale9a", "Seq (finale 9a)", "SE313B~5.IMU"},
+ {-1, -1, 0, 0, 0, 0, "", "", "" }
+};
+
+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"},
+ {0, 1099, 0, 3, 0, 0, "stateMenu", "1099-Menu", "1099-M~1.IMX"},
+ {0, 1100, 0, 3, 0, 0, "stateHold1", "1100-Hold1", "1100-H~1.IMX"},
+ {0, 1101, 0, 3, 1, 0, "stateWaterline1", "1101-Waterline1", "1101-W~1.IMX"},
+ {0, 1102, 0, 3, 0, 0, "stateHold2", "1102-Hold2", "1102-H~1.IMX"},
+ {0, 1103, 0, 3, 0, 0, "stateWaterline2", "1103-Waterline2", "1103-W~1.IMX"},
+ {0, 1104, 0, 3, 0, 0, "stateCannon", "1104-Cannon", "1104-C~1.IMX"},
+ {0, 1105, 0, 3, 0, 0, "stateTreasure", "1105-Treasure", "1105-T~1.IMX"},
+ {0, 1200, 0, 3, 1, 0, "stateFortBase", "1200-Fort Base", "1200-F~1.IMX"},
+ {0, 1201, 0, 3, 1, 0, "statePreFort", "1201-Pre-Fort", "1201-P~1.IMX"},
+ {0, 1202, 0, 3, 0, 0, "statePreVooOut", "1202-PreVoo Out", "1202-P~1.IMX"},
+ {0, 1203, 0, 3, 0, 0, "statePreVooIn", "1203-PreVoo In", "1203-P~1.IMX"},
+ {0, 1204, 0, 3, 0, 0, "statePreVooLad", "1204-PreVoo Lady", "1204-P~1.IMX"},
+ {0, 1205, 0, 3, 0, 0, "stateVoodooOut", "1205-Voodoo Out", "1205-V~1.IMX"},
+ {0, 1210, 0, 3, 0, 0, "stateVoodooIn", "1210-Voodoo In", "1210-V~1.IMX"},
+ {0, 1212, 0,12, 1, 0, "stateVoodooInAlt", "1210-Voodoo In", "1210-V~1.IMX"},
+ {0, 1215, 0, 3, 0, 0, "stateVoodooLady", "1215-Voodoo Lady", "1215-V~1.IMX"},
+ {0, 1219, 0, 3, 0, 0, "statePrePlundermap", "1219-Pre-Map", "1219-P~1.IMX"},
+ {0, 1220, 0, 3, 0, 0, "statePlundermap", "1220-Plunder Map", "1220-P~1.IMX"},
+ {0, 1222, 0, 3, 0, 0, "statePreCabana", "1222-Pre-Cabana", "1222-P~1.IMX"},
+ {0, 1223, 0, 3, 0, 0, "stateCabana", "1223-Cabana", "1223-C~1.IMX"},
+ {0, 1224, 0, 3, 0, 0, "statePostCabana", "1224-Post-Cabana", "1224-P~1.IMX"},
+ {0, 1225, 0, 3, 0, 0, "stateBeachClub", "1225-Beach Club", "1225-B~1.IMX"},
+ {0, 1230, 0, 3, 0, 0, "stateCliff", "1230-Cliff", "1230-C~1.IMX"},
+ {0, 1232, 0, 3, 0,800, "stateBelly", "1232-Belly", "1232-B~1.IMX"},
+ {0, 1235, 0, 3, 0, 0, "stateQuicksand", "1235-Quicksand", "1235-Q~1.IMX"},
+ {0, 1240, 0, 3, 0,800, "stateDangerBeach", "1240-Danger Beach", "1240-D~1.IMX"},
+ {0, 1241, 0,12, 2,800, "stateDangerBeachAlt","1240-Danger Beach", "1240-D~1.IMX"},
+ {0, 1245, 0, 3, 0, 0, "stateRowBoat", "1245-Row Boat", "1245-R~1.IMX"},
+ {0, 1247, 0, 3, 0,800, "stateAlongside", "1247-Alongside", "1247-A~1.IMX"},
+ {0, 1248, 0,12, 1,800, "stateAlongsideAlt", "1247-Alongside", "1247-A~1.IMX"},
+ {0, 1250, 0, 3, 0,500, "stateChimpBoat", "1250-Chimp Boat", "1250-C~1.IMX"},
+ {0, 1255, 0, 3, 0,800, "stateMrFossey", "1255-Mr Fossey", "1255-M~1.IMX"},
+ {0, 1259, 0, 3, 0, 0, "statePreTown", "1259-Pre-Town", "1259-P~1.IMX"},
+ {0, 1260, 0, 3, 0, 0, "stateTown", "1260-Town", "1260-T~1.IMX"},
+ {0, 1264, 0, 3, 0, 0, "statePreMeadow", "1264-Pre-Meadow", "1264-P~1.IMX"},
+ {0, 1265, 0, 3, 0, 0, "stateMeadow", "1265-Meadow", "1265-M~1.IMX"},
+ {0, 1266, 0, 3, 0, 0, "stateMeadowAmb", "1266-Meadow Amb", "1266-M~1.IMX"},
+ {0, 1270, 0, 3, 0, 0, "stateWardrobePre", "1270-Wardrobe-Pre", "1270-W~1.IMX"},
+ {0, 1272, 0, 3, 0, 0, "statePreShow", "1272-Pre-Show", "1272-P~1.IMX"},
+ {0, 1274, 0, 3, 0, 0, "stateWardrobeShow", "1274-Wardrobe-Show", "1274-W~1.IMX"},
+ {0, 1276, 0, 3, 0, 0, "stateShow", "1276-Show", "1276-S~1.IMX"},
+ {0, 1277, 0, 3, 0, 0, "stateWardrobeJug", "1277-Wardrobe-Jug", "1277-W~1.IMX"},
+ {0, 1278, 0, 3, 0, 0, "stateJuggling", "1278-Juggling", "1278-J~1.IMX"},
+ {0, 1279, 0, 3, 0, 0, "statePostShow", "1279-Post-Show", "1279-P~1.IMX"},
+ {0, 1280, 0, 3, 0, 0, "stateChickenShop", "1280-Chicken Shop", "1280-C~1.IMX"},
+ {0, 1285, 0, 3, 0, 0, "stateBarberShop", "1285-Barber Shop", "1285-B~1.IMX"},
+ {0, 1286, 0, 3, 0, 0, "stateVanHelgen", "1286-Van Helgen", "1286-V~1.IMX"},
+ {0, 1287, 0, 3, 0, 0, "stateBill", "1287-Bill", "1287-B~1.IMX"},
+ {0, 1288, 0, 3, 0, 0, "stateHaggis", "1288-Haggis", "1288-H~1.IMX"},
+ {0, 1289, 0, 3, 0, 0, "stateRottingham", "1289-Rottingham", "1289-R~1.IMX"},
+ {0, 1305, 0, 3, 0, 0, "stateDeck", "1305-Deck", "1305-D~1.IMX"},
+ {0, 1310, 0, 3, 0, 0, "stateCombatMap", "1310-Combat Map", "1310-C~1.IMX"},
+ {0, 1320, 0, 3, 0, 0, "stateShipCombat", "1320-Ship Combat", "1320-S~1.IMX"},
+ {0, 1325, 0, 3, 0, 0, "stateSwordfight", "1325-Swordfight", "1325-S~1.IMX"},
+ {0, 1327, 0, 3, 0, 0, "stateSwordRott", "1327-Sword Rott", "1327-S~1.IMX"},
+ {0, 1330, 0, 3, 0, 0, "stateTownEdge", "1330-Town Edge", "1330-T~1.IMX"},
+ {0, 1335, 0, 3, 0, 0, "stateSwordLose", "1335-Sword Lose", "1335-S~1.IMX"},
+ {0, 1340, 0, 3, 0, 0, "stateSwordWin", "1340-Sword Win", "1340-S~1.IMX"},
+ {0, 1345, 0, 3, 0, 0, "stateGetMap", "1345-Get Map", "1345-G~1.IMX"},
+ {0, 1400, 0, 3, 0, 0, "stateWreckBeach", "1400-Wreck Beach", "1400-W~1.IMX"},
+ {0, 1405, 0, 3, 0, 0, "stateBloodMap", "1405-Blood Map", "1405-B~1.IMX"},
+ {0, 1410, 0, 3, 0, 0, "stateClearing", "1410-Clearing", "1410-C~1.IMX"},
+ {0, 1415, 0, 3, 0, 0, "stateLighthouse", "1415-Lighthouse", "1415-L~1.IMX"},
+ {0, 1420, 0, 3, 0, 0, "stateVillage", "1420-Village", "1420-V~1.IMX"},
+ {0, 1423, 0, 3, 0, 0, "stateVolcano", "1423-Volcano", "1423-V~1.IMX"},
+ {0, 1425, 0, 3, 0, 0, "stateAltar", "1425-Altar", "1425-A~1.IMX"},
+ {0, 1430, 0, 3, 0, 0, "stateHotelOut", "1430-Hotel Out", "1430-H~1.IMX"},
+ {0, 1435, 0, 3, 0, 0, "stateHotelBar", "1435-Hotel Bar", "1435-H~1.IMX"},
+ {0, 1440, 0, 3, 0, 0, "stateHotelIn", "1440-Hotel In", "1440-H~1.IMX"},
+ {0, 1445, 0, 3, 0, 0, "stateTarotLady", "1445-Tarot Lady", "1445-T~1.IMX"},
+ {0, 1447, 0, 3, 0, 0, "stateGoodsoup", "1447-Goodsoup", "1447-G~1.IMX"},
+ {0, 1448, 0, 3, 0, 0, "stateGuestRoom", "1448-Guest Room", "1448-G~1.IMX"},
+ {0, 1450, 0, 3, 0, 0, "stateWindmill", "1450-Windmill", "1450-W~1.IMX"},
+ {0, 1455, 0, 3, 0, 0, "stateCemetary", "1455-Cemetary", "1455-C~1.IMX"},
+ {0, 1460, 0, 3, 0, 0, "stateCrypt", "1460-Crypt", "1460-C~1.IMX"},
+ {0, 1463, 0, 3, 0, 0, "stateGraveDigger", "1463-Gravedigger", "1463-G~1.IMX"},
+ {0, 1465, 0, 3, 0, 0, "stateMonkey1", "1465-Monkey1", "1465-M~1.IMX"},
+ {0, 1475, 0, 3, 0, 0, "stateStanDark", "1475-Stan Dark", "1475-S~1.IMX"},
+ {0, 1477, 0, 3, 0, 0, "stateStanLight", "1477-Stan", "1477-S~1.IMX"},
+ {0, 1480, 0, 3, 0, 0, "stateEggBeach", "1480-Egg Beach", "1480-E~1.IMX"},
+ {0, 1485, 0, 3, 0, 0, "stateSkullIsland", "1485-Skull Island", "1485-S~1.IMX"},
+ {0, 1490, 0, 3, 0, 0, "stateSmugglersCave", "1490-Smugglers", "1490-S~1.IMX"},
+ {0, 1500, 0, 3, 0, 0, "stateLeChuckTalk", "1500-Le Talk", "1500-L~1.IMX"},
+ {0, 1505, 0, 3, 0, 0, "stateCarnival", "1505-Carnival", "1505-C~1.IMX"},
+ {0, 1511, 0, 3, 0, 0, "stateHang", "1511-Hang", "1511-H~1.IMX"},
+ {0, 1512, 0, 3, 0, 0, "stateRum", "1512-Rum", "1512-RUM.IMX"},
+ {0, 1513, 0, 3, 0, 0, "stateTorture", "1513-Torture", "1513-T~1.IMX"},
+ {0, 1514, 0, 3, 0, 0, "stateSnow", "1514-Snow", "1514-S~1.IMX"},
+ {0, 1515, 0, 3, 0, 0, "stateCredits", "1515-Credits (end)", "1515-C~1.IMX"},
+ {0, 1520, 0, 3, 0, 0, "stateCarnAmb", "1520-Carn Amb", "1520-C~1.IMX"},
+ {-1, -1, 0, 0, 0, 0, "", "", ""}
+};
+
+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"},
+ {0, 2110, 0, 8, 1, 0, "seqLastBoat", "", ""},
+ {0, 2115, 0, 0, 0, 0, "seqSINK_SHIP", "", ""},
+ {0, 2120, 0, 0, 0, 0, "seqCURSED_RING", "", ""},
+ {0, 2200, 0, 3, 0, 0, "seqInterlude2", "2200-Interlude2", "2200-I~1.IMX"},
+ {0, 2210, 0, 3, 0, 0, "seqKidnapped", "2210-Kidnapped", "2210-K~1.IMX"},
+ {0, 2220, 0, 8, 1, 0, "seqSnakeVomits", "", ""},
+ {0, 2222, 0, 8, 1, 0, "seqPopBalloon", "", ""},
+ {0, 2225, 0, 3, 0, 0, "seqDropBalls", "2225-Drop Balls", "2225-D~1.IMX"},
+ {0, 2232, 0, 4, 0, 0, "seqArriveBarber", "2232-Arrive Barber", "2232-A~1.IMX"},
+ {0, 2233, 0, 3, 0, 0, "seqAtonal", "2233-Atonal", "2233-A~1.IMX"},
+ {0, 2235, 0, 3, 0, 0, "seqShaveHead1", "2235-Shave Head", "2235-S~1.IMX"},
+ {0, 2236, 0, 2, 2, 0, "seqShaveHead2", "2235-Shave Head", "2235-S~1.IMX"},
+ {0, 2245, 0, 3, 0, 0, "seqCaberLose", "2245-Caber Lose", "2245-C~1.IMX"},
+ {0, 2250, 0, 3, 0, 0, "seqCaberWin", "2250-Caber Win", "2250-C~1.IMX"},
+ {0, 2255, 0, 3, 0, 0, "seqDuel1", "2255-Duel", "2255-D~1.IMX"},
+ {0, 2256, 0, 2, 2, 0, "seqDuel2", "2255-Duel", "2255-D~1.IMX"},
+ {0, 2257, 0, 2, 3, 0, "seqDuel3", "2255-Duel", "2255-D~1.IMX"},
+ {0, 2260, 0, 3, 0, 0, "seqBlowUpTree1", "2260-Blow Up Tree", "2260-B~1.IMX"},
+ {0, 2261, 0, 2, 2, 0, "seqBlowUpTree2", "2260-Blow Up Tree", "2260-B~1.IMX"},
+ {0, 2275, 0, 3, 0, 0, "seqMonkeys", "2275-Monkeys", "2275-M~1.IMX"},
+ {0, 2277, 0, 9, 1, 0, "seqAttack", "", ""},
+ {0, 2285, 0, 3, 0, 0, "seqSharks", "2285-Sharks", "2285-S~1.IMX"},
+ {0, 2287, 0, 3, 0, 0, "seqTowelWalk", "2287-Towel Walk", "2287-T~1.IMX"},
+ {0, 2293, 0, 0, 0, 0, "seqNICE_BOOTS", "", ""},
+ {0, 2295, 0, 0, 0, 0, "seqBIG_BONED", "", ""},
+ {0, 2300, 0, 3, 0, 0, "seqToBlood", "2300-To Blood", "2300-T~1.IMX"},
+ {0, 2301, 0, 3, 0, 0, "seqInterlude3", "2301-Interlude3", "2301-I~1.IMX"},
+ {0, 2302, 0, 3, 0, 0, "seqRott1", "2302-Rott Attack", "2302-R~1.IMX"},
+ {0, 2304, 0, 2, 2, 0, "seqRott2", "2302-Rott Attack", "2302-R~1.IMX"},
+ {0, 2305, 0, 2,21, 0, "seqRott2b", "2302-Rott Attack", "2302-R~1.IMX"},
+ {0, 2306, 0, 2, 3, 0, "seqRott3", "2302-Rott Attack", "2302-R~1.IMX"},
+ {0, 2308, 0, 2, 4, 0, "seqRott4", "2302-Rott Attack", "2302-R~1.IMX"},
+ {0, 2309, 0, 2, 5, 0, "seqRott5", "2302-Rott Attack", "2302-R~1.IMX"},
+ {0, 2311, 0, 3, 0, 0, "seqVerse1", "2311-Song", "2311-S~1.IMX"},
+ {0, 2312, 0, 2, 2, 0, "seqVerse2", "2311-Song", "2311-S~1.IMX"},
+ {0, 2313, 0, 2, 3, 0, "seqVerse3", "2311-Song", "2311-S~1.IMX"},
+ {0, 2314, 0, 2, 4, 0, "seqVerse4", "2311-Song", "2311-S~1.IMX"},
+ {0, 2315, 0, 2, 5, 0, "seqVerse5", "2311-Song", "2311-S~1.IMX"},
+ {0, 2316, 0, 2, 6, 0, "seqVerse6", "2311-Song", "2311-S~1.IMX"},
+ {0, 2317, 0, 2, 7, 0, "seqVerse7", "2311-Song", "2311-S~1.IMX"},
+ {0, 2318, 0, 2, 8, 0, "seqVerse8", "2311-Song", "2311-S~1.IMX"},
+ {0, 2319, 0, 2, 9, 0, "seqSongEnd", "2311-Song", "2311-S~1.IMX"},
+ {0, 2336, 0, 2, 0, 0, "seqRiposteLose", "2336-Riposte Lose", "2336-R~1.IMX"},
+ {0, 2337, 0, 2, 0, 0, "seqRiposteWin", "2337-Riposte Win", "2337-R~1.IMX"},
+ {0, 2338, 0, 2, 0, 0, "seqInsultLose", "2338-Insult Lose", "2338-I~1.IMX"},
+ {0, 2339, 0, 2, 0, 0, "seqInsultWin", "2339-Insult Win", "2339-I~1.IMX"},
+ {0, 2340, 0, 3, 0, 0, "seqSwordLose", "1335-Sword Lose", "1335-S~1.IMX"},
+ {0, 2345, 0, 3, 0, 0, "seqSwordWin", "1340-Sword Win", "1340-S~1.IMX"},
+ {0, 2347, 0, 3, 0, 0, "seqGetMap", "1345-Get Map", "1345-G~1.IMX"},
+ {0, 2400, 0, 3, 0, 0, "seqInterlude4", "2400-Interlude4", "2400-I~1.IMX"},
+ {0, 2405, 0, 0, 0, 0, "seqSHIPWRECK", "", ""},
+ {0, 2408, 0, 3, 0, 0, "seqFakeCredits", "2408-Fake Credits", "2408-F~1.IMX"},
+ {0, 2410, 0, 3, 0, 0, "seqPassOut", "2410-Pass Out", "2410-P~1.IMX"},
+ {0, 2414, 0, 3, 0, 0, "seqGhostTalk", "2414-Ghost Talk", "2414-G~1.IMX"},
+ {0, 2415, 0, 2, 1, 0, "seqGhostWedding", "2414-Ghost Talk", "2414-G~1.IMX"},
+ {0, 2420, 0, 3, 0, 0, "seqEruption", "2420-Eruption", "2420-E~1.IMX"},
+ {0, 2425, 0, 3, 0, 0, "seqSacrifice", "2425-Sacrifice", "2425-S~1.IMX"},
+ {0, 2426, 0, 2, 1, 0, "seqSacrificeEnd", "2425-Sacrifice", "2425-S~1.IMX"},
+ {0, 2430, 0, 3, 0, 0, "seqScareDigger", "2430-Scare Digger", "2430-S~1.IMX"},
+ {0, 2445, 0, 3, 0, 0, "seqSkullArrive", "2445-Skull Arrive", "2445-S~1.IMX"},
+ {0, 2450, 0, 3, 0, 0, "seqFloat", "2450-Cliff Fall", "2450-C~1.IMX"},
+ {0, 2451, 0, 2, 1, 0, "seqFall", "2450-Cliff Fall", "2450-C~1.IMX"},
+ {0, 2452, 0, 2, 2, 0, "seqUmbrella", "2450-Cliff Fall", "2450-C~1.IMX"},
+ {0, 2460, 0, 3, 0, 0, "seqFight", "2460-Fight", "2460-F~1.IMX"},
+ {0, 2465, 0, 0, 0, 0, "seqLAVE_RIDE", "", ""},
+ {0, 2470, 0, 0, 0, 0, "seqMORE_SLAW", "", ""},
+ {0, 2475, 0, 0, 0, 0, "seqLIFT_CURSE", "", ""},
+ {0, 2500, 0, 3, 0, 0, "seqInterlude5", "2500-Interlude5", "2500-I~1.IMX"},
+ {0, 2502, 0, 3, 0, 0, "seqExitSkycar", "2502-Exit Skycar", "2502-E~1.IMX"},
+ {0, 2504, 0, 3, 0, 0, "seqGrow1", "2504-Grow", "2504-G~1.IMX"},
+ {0, 2505, 0, 2, 1, 0, "seqGrow2", "2504-Grow", "2504-G~1.IMX"},
+ {0, 2508, 0, 3, 0, 0, "seqInterlude6", "2508-Interlude6", "2508-I~1.IMX"},
+ {0, 2515, 0, 0, 0, 0, "seqFINALE", "", ""},
+ {0, 2520, 0, 3, 0, 0, "seqOut", "2520-Out", "2520-OUT.IMX"},
+ {0, 2530, 0, 3, 0, 0, "seqZap1a", "2530-Zap1", "2530-Z~1.IMX"},
+ {0, 2531, 0, 2, 1, 0, "seqZap1b", "2530-Zap1", "2530-Z~1.IMX"},
+ {0, 2532, 0, 2, 2, 0, "seqZap1c", "2530-Zap1", "2530-Z~1.IMX"},
+ {0, 2540, 0, 3, 0, 0, "seqZap2a", "2540-Zap2", "2540-Z~1.IMX"},
+ {0, 2541, 0, 2, 1, 0, "seqZap2b", "2540-Zap2", "2540-Z~1.IMX"},
+ {0, 2542, 0, 2, 2, 0, "seqZap2c", "2540-Zap2", "2540-Z~1.IMX"},
+ {0, 2550, 0, 3, 0, 0, "seqZap3a", "2550-Zap3", "2550-Z~1.IMX"},
+ {0, 2551, 0, 2, 1, 0, "seqZap3b", "2550-Zap3", "2550-Z~1.IMX"},
+ {0, 2552, 0, 2, 2, 0, "seqZap3c", "2550-Zap3", "2550-Z~1.IMX"},
+ {0, 2560, 0, 3, 0, 0, "seqZap4a", "2560-Zap4", "2560-Z~1.IMX"},
+ {0, 2561, 0, 2, 1, 0, "seqZap4b", "2560-Zap4", "2560-Z~1.IMX"},
+ {0, 2562, 0, 2, 2, 0, "seqZap4c", "2560-Zap4", "2560-Z~1.IMX"},
+ {-1, -1, 0, 0, 0, 0, "", "", ""}
+};
+
+const imuse_ft_music_table _ftStateMusicTable[] = {
+ {0, "", 0, 0, "STATE_NULL" },
+ {1, "", 4, 127, "stateKstandOutside" },
+ {2, "kinside", 2, 127, "stateKstandInside" },
+ {3, "moshop", 3, 64, "stateMoesInside" },
+ {4, "melcut", 2, 127, "stateMoesOutside" },
+ {5, "mellover", 2, 127, "stateMellonAbove" },
+ {6, "radloop", 3, 28, "stateTrailerOutside" },
+ {7, "radloop", 3, 58, "stateTrailerInside" },
+ {8, "radloop", 3, 127, "stateTodShop" },
+ {9, "junkgate", 2, 127, "stateJunkGate" },
+ {10, "junkover", 3, 127, "stateJunkAbove" },
+ {11, "gastower", 2, 127, "stateGasTower" },
+ {12, "", 4, 0, "stateTowerAlarm" },
+ {13, "melcut", 2, 127, "stateCopsOnGround" },
+ {14, "melcut", 2, 127, "stateCopsAround" },
+ {15, "melcut", 2, 127, "stateMoesRuins" },
+ {16, "melcut", 2, 127, "stateKstandNight" },
+ {17, "trukblu2", 2, 127, "stateTruckerTalk" },
+ {18, "stretch", 2, 127, "stateMumblyPeg" },
+ {19, "kstand", 2, 100, "stateRanchOutside" },
+ {20, "kinside", 2, 127, "stateRanchInside" },
+ {21, "desert", 2, 127, "stateWreckedTruck" },
+ {22, "opening", 2, 100, "stateGorgeVista" },
+ {23, "caveopen", 2, 127, "stateCaveOpen" },
+ {24, "cavecut1", 2, 127, "stateCaveOuter" },
+ {25, "cavecut1", 1, 127, "stateCaveMiddle" },
+ {26, "cave", 2, 127, "stateCaveInner" },
+ {27, "corville", 2, 127, "stateCorvilleFront" },
+ {28, "mines", 2, 127, "stateMineField" },
+ {29, "bunyman3", 2, 127, "stateBunnyStore" },
+ {30, "stretch", 2, 127, "stateStretchBen" },
+ {31, "saveme", 2, 127, "stateBenPleas" },
+ {32, "", 4, 0, "stateBenConvinces" },
+ {33, "derby", 3, 127, "stateDemoDerby" },
+ {34, "fire", 3, 127, "stateLightMyFire" },
+ {35, "derby", 3, 127, "stateDerbyChase" },
+ {36, "carparts", 2, 127, "stateVultureCarParts"},
+ {37, "cavecut1", 2, 127, "stateVulturesInside" },
+ {38, "mines", 2, 127, "stateFactoryRear" },
+ {39, "croffice", 2, 127, "stateCorleyOffice" },
+ {40, "melcut", 2, 127, "stateCorleyHall" },
+ {41, "", 4, 0, "stateProjRoom" },
+ {42, "", 4, 0, "stateMMRoom" },
+ {43, "bumper", 2, 127, "stateBenOnBumper" },
+ {44, "benump", 2, 127, "stateBenOnBack" },
+ {45, "plane", 2, 127, "stateInCargoPlane" },
+ {46, "saveme", 2, 127, "statePlaneControls" },
+ {47, "", 4, 0, "stateCliffHanger1" },
+ {48, "", 4, 0, "stateCliffHanger2" },
+ {-1, "", 0, 0, "" }
+};
+
+const imuse_ft_music_table _ftSeqMusicTable[] = {
+ {0, "", 2, 127, "SEQ_NULL" },
+ {1, "opening", 2, 127, "seqLogo" },
+ {2, "barbeat", 2, 127, "seqOpenFlick" },
+ {3, "barwarn", 2, 127, "seqBartender" },
+ {4, "benwakes", 2, 127, "seqBenWakes" },
+ {5, "barwarn", 2, 127, "seqPhotoScram" },
+ {6, "swatben", 2, 127, "seqClimbChain" },
+ {7, "dogattak", 2, 127, "seqDogChase" },
+ {8, "", 0, 0, "seqDogSquish" },
+ {9, "", 0, 0, "seqDogHoist" },
+ {10, "cops2", 2, 127, "seqCopsArrive" },
+ {11, "cops2", 2, 127, "seqCopsLand" },
+ {12, "cops2", 2, 127, "seqCopsLeave" },
+ {13, "", 0, 0, "seqCopterFlyby" },
+ {14, "bunymrch", 2, 127, "seqCopterCrash" },
+ {15, "", 0, 0, "seqMoGetsParts" },
+ {16, "", 0, 0, "seqMoFixesBike" },
+ {17, "", 0, 0, "seqFirstGoodbye" },
+ {18, "trucker", 2, 127, "seqCopRoadblock" },
+ {19, "cops2", 2, 127, "seqDivertCops" },
+ {20, "barwarn", 2, 127, "seqMurder" },
+ {21, "corldie", 2, 127, "seqCorleyDies" },
+ {22, "barwarn", 2, 127, "seqTooLateAtMoes" },
+ {23, "picture", 2, 127, "seqPicture" },
+ {24, "ripintro", 2, 127, "seqNewsReel" },
+ {25, "trucker", 2, 127, "seqCopsInspect" },
+ {26, "ripdead", 2, 127, "seqHijack" },
+ {27, "nesranch", 2, 127, "seqNestolusAtRanch" },
+ {28, "scolding", 2, 127, "seqRipLimo" },
+ {29, "desert", 2, 127, "seqGorgeTurn" },
+ {30, "cavecut1", 2, 127, "seqStealRamp" },
+ {31, "vaceamb", 2, 80, "seqCavefishTalk" },
+ {32, "castle", 2, 127, "seqArriveCorville" },
+ {33, "bunymrch", 2, 105, "seqSingleBunny" },
+ {34, "valkyrs", 2, 127, "seqBunnyArmy" },
+ {35, "melcut", 2, 127, "seqArriveAtMines" },
+ {36, "veltures", 2, 127, "seqArriveAtVultures" },
+ {37, "sorry", 2, 127, "seqMakePlan" },
+ {38, "makeplan", 2, 127, "seqShowPlan" },
+ {39, "castle", 2, 127, "seqDerbyStart" },
+ {40, "fire", 3, 127, "seqLightBales" },
+ {41, "saveme", 3, 127, "seqNestolusBBQ" },
+ {42, "cops2", 2, 127, "seqCallSecurity" },
+ {43, "sorry", 2, 127, "seqFilmFail" },
+ {44, "sorry", 2, 127, "seqFilmBurn" },
+ {45, "caveamb", 2, 127, "seqRipSpeech" },
+ {46, "expose", 2, 127, "seqExposeRip" },
+ {47, "ripscram", 2, 127, "seqRipEscape" },
+ {48, "", 0, 0, "seqRareMoment" },
+ {49, "valkyrs", 2, 127, "seqFanBunnies" },
+ {50, "ripdead", 2, 127, "seqRipDead" },
+ {51, "funeral", 2, 127, "seqFuneral" },
+ {52, "bornbad", 2, 127, "seqCredits" },
+ {-1, "", 0, 0, "" }
+};
+
+} // End of namespace Scumm