[Scummvm-cvs-logs] CVS: scummvm/scumm/imuse_digi .cvsignore,NONE,1.1 dimuse.cpp,NONE,1.1 dimuse.h,NONE,1.1 dimuse_bndmgr.cpp,NONE,1.1 dimuse_bndmgr.h,NONE,1.1 dimuse_codecs.cpp,NONE,1.1 dimuse_sndmgr.cpp,NONE,1.1 dimuse_sndmgr.h,NONE,1.1 dimuse_tables.cpp,NONE,1.1

Pawel Kolodziejski aquadran at users.sourceforge.net
Tue Jan 6 09:29:08 CET 2004


Update of /cvsroot/scummvm/scummvm/scumm/imuse_digi
In directory sc8-pr-cvs1:/tmp/cvs-serv18225/imuse_digi

Added Files:
	.cvsignore dimuse.cpp dimuse.h dimuse_bndmgr.cpp 
	dimuse_bndmgr.h dimuse_codecs.cpp dimuse_sndmgr.cpp 
	dimuse_sndmgr.h dimuse_tables.cpp 
Log Message:
synced imuse digital with local tree

--- NEW FILE: .cvsignore ---
.deps

--- NEW FILE: dimuse.cpp ---
/* 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: /cvsroot/scummvm/scummvm/scumm/imuse_digi/dimuse.cpp,v 1.1 2004/01/06 17:28:29 aquadran Exp $
 */

#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

--- NEW FILE: dimuse.h ---
/* 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: /cvsroot/scummvm/scummvm/scumm/imuse_digi/dimuse.h,v 1.1 2004/01/06 17:28:29 aquadran Exp $
 */

#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

--- NEW FILE: dimuse_bndmgr.cpp ---
/* 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: /cvsroot/scummvm/scummvm/scumm/imuse_digi/dimuse_bndmgr.cpp,v 1.1 2004/01/06 17:28:29 aquadran Exp $
 */

#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

--- NEW FILE: dimuse_bndmgr.h ---
/* 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: /cvsroot/scummvm/scummvm/scumm/imuse_digi/dimuse_bndmgr.h,v 1.1 2004/01/06 17:28:29 aquadran Exp $
 */

#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

--- NEW FILE: dimuse_codecs.cpp ---
/* 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: /cvsroot/scummvm/scummvm/scumm/imuse_digi/dimuse_codecs.cpp,v 1.1 2004/01/06 17:28:29 aquadran Exp $
 */

#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

--- NEW FILE: dimuse_sndmgr.cpp ---
/* 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: /cvsroot/scummvm/scummvm/scumm/imuse_digi/dimuse_sndmgr.cpp,v 1.1 2004/01/06 17:28:29 aquadran Exp $
 */

#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

--- NEW FILE: dimuse_sndmgr.h ---
/* 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: /cvsroot/scummvm/scummvm/scumm/imuse_digi/dimuse_sndmgr.h,v 1.1 2004/01/06 17:28:29 aquadran Exp $
 */

#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

--- NEW FILE: dimuse_tables.cpp ---
/* 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: /cvsroot/scummvm/scummvm/scumm/imuse_digi/dimuse_tables.cpp,v 1.1 2004/01/06 17:28:29 aquadran Exp $
 */

#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





More information about the Scummvm-git-logs mailing list